From 795f483366523ee7c82a46f4dbece33232c26bc0 Mon Sep 17 00:00:00 2001 From: REBOL Technologies Date: Wed, 2 Dec 2009 23:39:06 +0000 Subject: [PATCH] RT R3 A96 Hostkit for Win32 --- info.txt | 8 + makefile | 84 +++++ r3lib.dll | Bin 0 -> 323584 bytes r3lib.exp | Bin 0 -> 1530 bytes r3lib.lib | Bin 0 -> 3542 bytes src/include/host-init.h | 17 + src/include/host-lib.h | 171 +++++++++ src/include/reb-args.h | 79 ++++ src/include/reb-c.h | 253 +++++++++++++ src/include/reb-config.h | 133 +++++++ src/include/reb-defs.h | 48 +++ src/include/reb-device.h | 172 +++++++++ src/include/reb-event.h | 42 +++ src/include/reb-evtypes.h | 86 +++++ src/include/reb-file.h | 42 +++ src/include/reb-filereq.h | 33 ++ src/include/reb-host.h | 27 ++ src/include/reb-net.h | 34 ++ src/include/reb-to.h | 1 + src/include/rebol-lib.h | 27 ++ src/include/sys-net.h | 74 ++++ src/os/dev-dns.c | 205 +++++++++++ src/os/dev-net.c | 610 +++++++++++++++++++++++++++++++ src/os/host-args.c | 267 ++++++++++++++ src/os/host-device.c | 449 +++++++++++++++++++++++ src/os/host-init.c | 672 +++++++++++++++++++++++++++++++++++ src/os/host-main.c | 149 ++++++++ src/os/host-stdio.c | 159 +++++++++ src/os/win32/dev-clipboard.c | 194 ++++++++++ src/os/win32/dev-event.c | 203 +++++++++++ src/os/win32/dev-file.c | 462 ++++++++++++++++++++++++ src/os/win32/dev-stdio.c | 373 +++++++++++++++++++ src/os/win32/host-lib.c | 648 +++++++++++++++++++++++++++++++++ 33 files changed, 5722 insertions(+) create mode 100644 info.txt create mode 100644 makefile create mode 100644 r3lib.dll create mode 100644 r3lib.exp create mode 100644 r3lib.lib create mode 100644 src/include/host-init.h create mode 100644 src/include/host-lib.h create mode 100644 src/include/reb-args.h create mode 100644 src/include/reb-c.h create mode 100644 src/include/reb-config.h create mode 100644 src/include/reb-defs.h create mode 100644 src/include/reb-device.h create mode 100644 src/include/reb-event.h create mode 100644 src/include/reb-evtypes.h create mode 100644 src/include/reb-file.h create mode 100644 src/include/reb-filereq.h create mode 100644 src/include/reb-host.h create mode 100644 src/include/reb-net.h create mode 100644 src/include/reb-to.h create mode 100644 src/include/rebol-lib.h create mode 100644 src/include/sys-net.h create mode 100644 src/os/dev-dns.c create mode 100644 src/os/dev-net.c create mode 100644 src/os/host-args.c create mode 100644 src/os/host-device.c create mode 100644 src/os/host-init.c create mode 100644 src/os/host-main.c create mode 100644 src/os/host-stdio.c create mode 100644 src/os/win32/dev-clipboard.c create mode 100644 src/os/win32/dev-event.c create mode 100644 src/os/win32/dev-file.c create mode 100644 src/os/win32/dev-stdio.c create mode 100644 src/os/win32/host-lib.c diff --git a/info.txt b/info.txt new file mode 100644 index 0000000..9ac15b6 --- /dev/null +++ b/info.txt @@ -0,0 +1,8 @@ +REBOL 3 Host Build Distribution + + Version: 2.100.96.0.0 + Built: 2-Dec-2009/15:37:52-8:00 + +Test build only for early alpha-test developers. Do not distribute. + +Documentation: http://www.rebol.net/wiki/Host-Builds diff --git a/makefile b/makefile new file mode 100644 index 0000000..0353919 --- /dev/null +++ b/makefile @@ -0,0 +1,84 @@ +# REBOL 3.0 Host Makefile - Build A96 + +C= gcc +CFLAGS= -c -O1 -DUNICODE -fpack-struct -I src/include/ +LIBS= r3lib.lib -L c:/mingw/lib/ -lm -lwsock32 -lcomdlg32 +#-lc -lm -lstdc++ + +S= src +O= obj +I= src/include + +# Included from reb-host.h: +INCS = \ + $I/reb-config.h\ + $I/reb-c.h\ + $I/reb-defs.h\ + $I/reb-args.h\ + $I/reb-device.h\ + $I/reb-file.h\ + $I/reb-event.h\ + $I/reb-evtypes.h\ + $I/reb-net.h\ + $I/reb-filereq.h\ + +OBJS = \ + $O/host-main.o\ + $O/host-args.o\ + $O/host-device.o\ + $O/host-stdio.o\ + $O/dev-net.o\ + $O/dev-dns.o\ + $O/host-init.o\ + $O/host-lib.o\ + $O/dev-stdio.o\ + $O/dev-event.o\ + $O/dev-file.o\ + $O/dev-clipboard.o\ + +# Link the files +core: $(OBJS) + $C -o core.exe $(OBJS) $(LIBS) + strip core.exe + +clean: + del /q obj\* + make core + +# Compile: +$O/host-main.o: $S/os/host-main.c $(INCS) $I/reb-host.h $I/host-lib.h $I/rebol-lib.h $I/host-init.h + $C $(CFLAGS) -o $O/host-main.o $S/os/host-main.c + +$O/host-args.o: $S/os/host-args.c $(INCS) $I/reb-config.h $I/reb-c.h $I/reb-args.h + $C $(CFLAGS) -o $O/host-args.o $S/os/host-args.c + +$O/host-device.o: $S/os/host-device.c $(INCS) $I/reb-host.h $I/host-lib.h $I/rebol-lib.h + $C $(CFLAGS) -o $O/host-device.o $S/os/host-device.c + +$O/host-stdio.o: $S/os/host-stdio.c $(INCS) $I/reb-host.h $I/host-lib.h + $C $(CFLAGS) -o $O/host-stdio.o $S/os/host-stdio.c + +$O/dev-net.o: $S/os/dev-net.c $(INCS) $I/reb-host.h $I/host-lib.h $I/sys-net.h + $C $(CFLAGS) -o $O/dev-net.o $S/os/dev-net.c + +$O/dev-dns.o: $S/os/dev-dns.c $(INCS) $I/reb-host.h $I/host-lib.h $I/sys-net.h + $C $(CFLAGS) -o $O/dev-dns.o $S/os/dev-dns.c + +$O/host-init.o: $S/os/host-init.c $(INCS) + $C $(CFLAGS) -o $O/host-init.o $S/os/host-init.c + +$O/host-lib.o: $S/os/win32/host-lib.c $(INCS) $I/reb-host.h $I/host-lib.h + $C $(CFLAGS) -o $O/host-lib.o $S/os/win32/host-lib.c + +$O/dev-stdio.o: $S/os/win32/dev-stdio.c $(INCS) $I/reb-host.h $I/host-lib.h + $C $(CFLAGS) -o $O/dev-stdio.o $S/os/win32/dev-stdio.c + +$O/dev-event.o: $S/os/win32/dev-event.c $(INCS) $I/reb-host.h $I/host-lib.h + $C $(CFLAGS) -o $O/dev-event.o $S/os/win32/dev-event.c + +$O/dev-file.o: $S/os/win32/dev-file.c $(INCS) $I/reb-host.h $I/host-lib.h + $C $(CFLAGS) -o $O/dev-file.o $S/os/win32/dev-file.c + +$O/dev-clipboard.o: $S/os/win32/dev-clipboard.c $(INCS) $I/reb-host.h $I/host-lib.h $I/sys-net.h + $C $(CFLAGS) -o $O/dev-clipboard.o $S/os/win32/dev-clipboard.c + diff --git a/r3lib.dll b/r3lib.dll new file mode 100644 index 0000000000000000000000000000000000000000..8c29f7950396de3f1e9b80099133dd52ff7b041b GIT binary patch literal 323584 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%0A{OV)kF;PtvUx+pgdMnlOr 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 z±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�DU@@$h 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 z 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 +#define OS_FREE(a) Host_Lib->os_free(a) +#define OS_EXIT(a) Host_Lib->os_exit(a) +#define OS_CRASH(a,b) Host_Lib->os_crash(a,b) +#define OS_FORM_ERROR(a,b,c) Host_Lib->os_form_error(a,b,c) +#define OS_GET_BOOT_PATH(a) Host_Lib->os_get_boot_path(a) +#define OS_GET_LOCALE(a) Host_Lib->os_get_locale(a) +#define OS_GET_ENV(a,b) Host_Lib->os_get_env(a,b) +#define OS_SET_ENV(a,b) Host_Lib->os_set_env(a,b) +#define OS_LIST_ENV() Host_Lib->os_list_env() +#define OS_GET_TIME(a) Host_Lib->os_get_time(a) +#define OS_DELTA_TIME(a,b) Host_Lib->os_delta_time(a,b) +#define OS_GET_CURRENT_DIR(a) Host_Lib->os_get_current_dir(a) +#define OS_SET_CURRENT_DIR(a) Host_Lib->os_set_current_dir(a) +#define OS_FILE_TIME(a,b) Host_Lib->os_file_time(a,b) +#define OS_OPEN_LIBRARY(a,b) Host_Lib->os_open_library(a,b) +#define OS_CLOSE_LIBRARY(a) Host_Lib->os_close_library(a) +#define OS_FIND_FUNCTION(a,b) Host_Lib->os_find_function(a,b) +#define OS_CREATE_THREAD(a,b,c) Host_Lib->os_create_thread(a,b,c) +#define OS_DELETE_THREAD() Host_Lib->os_delete_thread() +#define OS_TASK_READY(a) Host_Lib->os_task_ready(a) +#define OS_CREATE_PROCESS(a,b) Host_Lib->os_create_process(a,b) +#define OS_BROWSE(a,b) Host_Lib->os_browse(a,b) +#define OS_REQUEST_FILE(a) Host_Lib->os_request_file(a) +#define OS_CALL_DEVICE(a,b) Host_Lib->os_call_device(a,b) +#define OS_DO_DEVICE(a,b) Host_Lib->os_do_device(a,b) +#define OS_MAKE_DEVREQ(a) Host_Lib->os_make_devreq(a) +#define OS_ABORT_DEVICE(a) Host_Lib->os_abort_device(a) +#define OS_POLL_DEVICES() Host_Lib->os_poll_devices() +#define OS_WAIT(a,b) Host_Lib->os_wait(a,b) + +#endif //AS_LIB diff --git a/src/include/reb-args.h b/src/include/reb-args.h new file mode 100644 index 0000000..3e82683 --- /dev/null +++ b/src/include/reb-args.h @@ -0,0 +1,79 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Program startup arguments +** Date: 1-Dec-2009 +** File: reb-args.h +** +************************************************************************ +** +** Note: arg struct is used by R3 lib, so must not be modified. +** +***********************************************************************/ + +// REBOL startup option structure: +typedef struct rebol_args { + REBCNT options; + REBCHR *script; + REBCHR *args; + REBCHR *do_arg; + REBCHR *version; + REBCHR *debug; + REBCHR *import; + REBCHR *secure; + REBCHR *exe_path; + REBCHR *home_dir; +} REBARGS; + +// REBOL arg option flags: +// Must stay matched to system/catalog/boot-flags. +enum arg_opts { + ROF_EXT, + + ROF_SCRIPT, + ROF_ARGS, + ROF_DO, + ROF_IMPORT, + ROF_VERSION, + ROF_DEBUG, + ROF_SECURE, + + ROF_HELP, + ROF_VERS, + ROF_QUIET, + ROF_VERBOSE, + ROF_NO_BOOT, + ROF_SECURE_MIN, + ROF_SECURE_MAX, + ROF_TRACE, + ROF_HALT, + ROF_CGI, + ROF_IGNORE, +}; + +#define RO_EXT (1< (b)) ? (a) : (b)) +#endif + +// Memory related functions: +#define MAKE_MEM(n) malloc(n) +#define MAKE_NEW(s) malloc(sizeof(s)) +#define FREE_MEM(m) free(m) +#define CLEAR(m, s) memset((void*)(m), 0, s); +#define CLEARS(m) memset((void*)(m), 0, sizeof(*m)); +#define COPY_MEM(t,f,l) memcpy((void*)(t), (void*)(f), l) +#define MOVE_MEM(t,f,l) memmove((void*)(t), (void*)(f), l) + +// Byte string functions: +#define COPY_BYTES(t,f,l) strncpy((char*)t, (char*)f, l) +#define APPEND_BYTES(t,f,l) strncat((char*)t, (char*)f, l) +#define LEN_BYTES(s) strlen((char*)s) +#define CMP_BYTES(s,t) strcmp((char*)s, (char*)t) +#define BYTES(s) (REBYTE*)(s) + +// OS has wide char string interfaces: +#ifdef OS_WIDE_CHAR +#define OS_WIDE TRUE +#define TXT(s) (L##s) +#define COPY_STR(t,f,l) wcsncpy(t, f, l) +#define JOIN_STR(d,s,l) wcsncat(d,s,l) +#define FIND_STR(d,s) wcsstr(d,s) +#define FIND_CHR(d,s) wcschr(d,s) +#define LEN_STR(s) wcslen(s) +#define TO_OS_STR(s1,s2,l) mbstowcs(s1,s2,l) +#define FROM_OS_STR(s1,s2,l) wcstombs(s1,s2,l) +#else +// OS has UTF-8 byte string interfaces: +#define OS_WIDE FALSE +#define TXT(s) (s) +#define COPY_STR(t,f,l) strncpy(t, f, l) +#define JOIN_STR(d,s,l) strncat(d,s,l) +#define FIND_STR(d,s) strstr(d,s) +#define FIND_CHR(d,s) strchr(d,s) +#define LEN_STR(s) strlen(s) +#define TO_OS_STR(s1,s2,l) strncpy(s1,s2,l) +#define FROM_OS_STR(s1,s2,l) strncpy(s1,s2,l) +#endif + +#define MAKE_STR(n) (REBCHR*)(malloc((n) * sizeof(REBCHR))) // OS chars! diff --git a/src/include/reb-config.h b/src/include/reb-config.h new file mode 100644 index 0000000..823f3f3 --- /dev/null +++ b/src/include/reb-config.h @@ -0,0 +1,133 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: General build configuration +** Date: 1-Dec-2009 +** File: reb-config.h +** +** Note: This is the first file included. +** +***********************************************************************/ + +#include "reb-to.h" // build target (#define TO_osname) + +//* Common ************************************************************* + +#define INT_64_MODE // 64 bit integer datatype +#define THREADED // enable threads + + +//* MS Windows 32 ****************************************************** + +#ifdef TO_WIN32 // Win32/Intel + +#define FULL_DEF // fully defined +#define WIN32_LEAN_AND_MEAN // trim down the Win32 headers +#define ENDIAN_LITTLE // uses little endian byte order +#define OS_WIDE_CHAR // OS uses WIDE_CHAR API +#define OS_CRLF TRUE // uses CRLF as line terminator +#define OS_DIR_SEP '\\' // file path separator (Thanks Bill.) +#define HAS_ASYNC_DNS // supports it +#define ATOI // supports it +#define ATOI64 // supports it +#define ITOA64 // supports it +#define HAS_ECVT // supports ecvt() +#define FINITE _finite // name used for it +#define INLINE __inline // name used for it + +#ifdef THREADED +#define THREAD __declspec(thread) +#endif + +// Used when we build REBOL as a DLL: +#define API_EXPORT __declspec(dllexport) +#define API_IMPORT __declspec(dllimport) + +// Use non-standard int64 declarations: +#if (defined(_MSC_VER) && (_MSC_VER <= 1200)) +#define ODD_INT_64 +#else +#define HAS_LONG_DOUBLE +#endif + +// Disable various warnings +#pragma warning(disable : 4201) // nameless unions +#pragma warning(disable : 4100) // unreferenced formal parameter +#pragma warning(disable : 4127) // conditional expression is constant +//#pragma warning(disable : 4057) +//#pragma warning(disable : 4701) + +#else + +//* Non Windows ******************************************************** + +#define MIN_OS // not all devices are working +#define NO_GRAPHICS // no graphics yet +#define FINITE finite +#define INLINE +#define API_EXPORT __attribute__((visibility("default"))) +#define API_IMPORT +#endif + +#ifdef TO_LINUX // Linux/Intel +#define ENDIAN_LITTLE +#define HAS_ECVT +#define HAS_LONG_DOUBLE +#endif + +#ifdef TO_LINUX_PPC // Linux/PPC +#define ENDIAN_BIG +#define HAS_ECVT +#define HAS_LONG_DOUBLE +#endif + +#ifdef TO_OSXI // OSX/Intel +#define ENDIAN_LITTLE +#define HAS_ECVT +#define HAS_LONG_DOUBLE +#endif + +#ifdef TO_OSX // OSX/PPC +#define ENDIAN_BIG +#define HAS_ECVT +#define HAS_LL_CONSTS +#define OLD_COMPILER +#endif + +#ifdef TO_OBSD // OpenBSD +#define COPY_STR(d,s,m) strlcpy(d,s,m) +#define JOIN_STR(d,s,m) strlcat(d,s,m) +#endif + +//* Defaults *********************************************************** + +#ifdef HAS_LONG_DOUBLE +#define HAS_LL_CONSTS +#endif + +#ifndef THREAD +#define THREAD +#endif + +#ifndef OS_DIR_SEP +#define OS_DIR_SEP '/' // rest of the world uses it +#endif + +#ifndef OS_CRLF +#define OS_CRLF FALSE +#endif + +#ifdef REBOL_ONLY +#define REBOL_API // REBOL stand-alone test version +#else +#ifdef REBOL_EXPORTS +#define REBOL_API API_EXPORT // for REBOL library build +#else +#define REBOL_API API_IMPORT // for host files when DLL used +#endif +#endif // REBOL_ONLY diff --git a/src/include/reb-defs.h b/src/include/reb-defs.h new file mode 100644 index 0000000..049aee1 --- /dev/null +++ b/src/include/reb-defs.h @@ -0,0 +1,48 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Miscellaneous structures and definitions +** Date: 1-Dec-2009 +** File: reb_defs.h +** +** Note: This file is used by internal and external C code. It +** should not depend on many other header files prior to it. +** +***********************************************************************/ + +#ifndef FULL_DEFS +typedef void REBSER; +typedef void REBGOB; +#endif + +// X/Y coordinate pair: +typedef struct rebol_pair { + int x; + int y; +} REBPAR; + +// Standard date and time: +typedef struct rebol_dat { + int year; + int month; + int day; + int time; + int nano; + int zone; +} REBOL_DAT; // not same as REBDAT + +// OS metrics: +typedef struct rebol_met { + int len; // # entries in this table + REBPAR screen_size; + REBPAR title_size; + REBPAR border_size; + REBPAR border_fixed; + REBPAR work_origin; + REBPAR work_size; +} REBOL_OS_METRICS; diff --git a/src/include/reb-device.h b/src/include/reb-device.h new file mode 100644 index 0000000..7a2f588 --- /dev/null +++ b/src/include/reb-device.h @@ -0,0 +1,172 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: External REBOL Devices (OS Independent) +** Date: 1-Dec-2009 +** File: host-device.h +** +** Critical: all struct alignment must be 4 bytes (see compile options) +** +***********************************************************************/ + +// REBOL Device Identifiers: +// Critical: Must be in same order as Device table in host-device.c +enum { + RDI_SYSTEM, + RDI_STDIO, + RDI_CONSOLE, + RDI_FILE, + RDI_EVENT, + RDI_NET, + RDI_DNS, + RDI_CLIPBOARD, + RDI_MAX, + RDI_LIMIT = 32 +}; + + +// REBOL Device Commands: +enum { + RDC_INIT, // init device driver resources + RDC_QUIT, // cleanup device driver resources + + RDC_OPEN, // open device unit (port) + RDC_CLOSE, // close device unit + + RDC_READ, // read from unit + RDC_WRITE, // write to unit + + RDC_POLL, // check for activity + RDC_CONNECT, // connect (in or out) + + RDC_QUERY, // query unit info + RDC_MODIFY, // set modes (also get modes) + + RDC_CREATE, // create unit target + RDC_DELETE, // delete unit target + RDC_RENAME, + RDC_LOOKUP, + RDC_MAX, + + RDC_CUSTOM=32 // start of custom commands +}; + +// Device Request (Command) Return Codes: +#define DR_PEND 1 // request is still pending +#define DR_DONE 0 // request is complete w/o errors +#define DR_ERROR -1 // request had an error + +// REBOL Device Flags and Options (bitnums): +enum { + // Status flags: + RDF_INIT, // Device is initialized + RDF_OPEN, // Global open (for devs that cannot multi-open) + // Options: + RDO_MUST_INIT = 16, // Do not allow auto init (manual init required) + RDO_AUTO_POLL, // Poll device, even if no requests (e.g. interrupts) +}; + +// REBOL Request Flags (bitnums): +enum { + RRF_OPEN, // Port is open + RRF_DONE, // Request is done (used when extern proc changes it) + RRF_FLUSH, // Flush WRITE +// RRF_PREWAKE, // C-callback before awake happens (to update port object) + RRF_PENDING, // Request is attached to pending list + RRF_ALLOC, // Request is allocated, not a temp on stack + RRF_WIDE, // Wide char IO +}; + +// REBOL Device Errors: +enum { + RDE_NONE, + RDE_NO_DEVICE, // command did not provide device + RDE_NO_COMMAND, // command past end + RDE_NO_INIT, // device has not been inited +}; + +enum { + RDM_NULL, // Null device +}; + +// Forward references: +typedef struct rebol_device REBDEV; +typedef struct rebol_devreq REBREQ; + +// Commands: +typedef int (*DEV_CMD)(REBREQ *req); +#define DEVICE_CMD static int // Used to define + +// Device structure: +struct rebol_device { + char *title; // title of device + u32 version; // version, revision, release + u32 date; // year, month, day, hour + DEV_CMD *commands; // command dispatch table + u32 max_command; // keep commands in bounds + REBREQ *pending; // pending requests + u32 flags; // state: open, signal + i32 req_size; // size of request struct +}; + +// Inializer (keep ordered same as above) +#define DEFINE_DEV(w,t,v,c,m,s) REBDEV w = {t, v, 0, c, m, 0, 0, s} + +// Request structure: // Allowed to be extended by some devices +struct rebol_devreq { + u32 clen; // size of extended structure + + // Linkages: + u32 device; // device id (dev table) + REBREQ *next; // linked list (pending or done lists) + void *port; // link back to REBOL port object + union { + void *handle; // OS object + int socket; // OS identifier + int id; + }; + + // Command info: + i32 command; // command code + u32 error; // error code + u32 modes; // special modes, types or attributes + u16 flags; // request flags + u16 state; // device process flags + i32 timeout; // request timeout +// int (*prewake)(void *); // callback before awake + + // Common fields: + union { + REBYTE *data; // data to transfer + REBREQ *sock; // temp link to related socket + }; + u32 length; // length to transfer + u32 actual; // length actually transferred + + // Special fields for common IO uses: + union { + struct { + REBCHR *path; // file string (in OS local format) + i64 size; // file size + i64 index; // file index position + I64 time; // file modification time (struct) + } file; + struct { + u32 local_ip; // local address used + u32 local_port; // local port used + u32 remote_ip; // remote address + u32 remote_port; // remote port + void *host_info; // for DNS usage + } net; + }; +}; + +// Simple macros for common OPEN? test (for some but not all ports): +#define SET_OPEN(r) SET_FLAG(((REBREQ*)(r))->flags, RRF_OPEN) +#define SET_CLOSED(r) CLR_FLAG(((REBREQ*)(r))->flags, RRF_OPEN) +#define IS_OPEN(r) GET_FLAG(((REBREQ*)(r))->flags, RRF_OPEN) diff --git a/src/include/reb-event.h b/src/include/reb-event.h new file mode 100644 index 0000000..e4c9b54 --- /dev/null +++ b/src/include/reb-event.h @@ -0,0 +1,42 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: REBOL event definitions +** Date: 1-Dec-2009 +** File: reb-event.h +** +***********************************************************************/ + +// Note: size must be 12 bytes! + +typedef struct rebol_event { + u8 type; // event id (mouse-move, mouse-button, etc) + u8 flags; // special flags + u8 win; // window id + u8 info; // other info + u32 data; // an x/y position or keycode (raw/decoded) + union { + REBREQ *req; // request (for device events) + void *ser; // port or object + }; +} REBEVT; + +// Special event flags: + +enum { + EVF_NO_REQ, // request field not used (e.g. GUI) + EVF_DOUBLE, // double click detected + EVF_CONTROL, + EVF_SHIFT, + EVF_IS_PORT, + EVF_IS_OBJ, + EVF_COPIED, // event data has been copied +}; + +// Special messages +#define WM_DNS (WM_USER+100) diff --git a/src/include/reb-evtypes.h b/src/include/reb-evtypes.h new file mode 100644 index 0000000..08f0340 --- /dev/null +++ b/src/include/reb-evtypes.h @@ -0,0 +1,86 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Event Types +** Build: A96 +** Date: 2-Dec-2009/15:37:16-8:00 +** File: reb-evtypes.h +** +** AUTO-GENERATED FILE - Do not modify. (From: make-boot.r) +** +***********************************************************************/ + +enum event_types { + EVT_IGNORE, + EVT_INTERRUPT, + EVT_DEVICE, + EVT_CUSTOM, + EVT_ERROR, + EVT_INIT, + EVT_OPEN, + EVT_CLOSE, + EVT_CONNECT, + EVT_ACCEPT, + EVT_READ, + EVT_WRITE, + EVT_WROTE, + EVT_LOOKUP, + EVT_READY, + EVT_DONE, + EVT_TIME, + EVT_SHOW, + EVT_HIDE, + EVT_OFFSET, + EVT_RESIZE, + EVT_ACTIVE, + EVT_INACTIVE, + EVT_MINIMIZE, + EVT_MAXIMIZE, + EVT_RESTORE, + EVT_MOVE, + EVT_DOWN, + EVT_UP, + EVT_ALT_DOWN, + EVT_ALT_UP, + EVT_AUX_DOWN, + EVT_AUX_UP, + EVT_KEY, + EVT_KEY_UP, + EVT_SCROLL_LINE, + EVT_SCROLL_PAGE, + EVT_DROP_FILE, + EVT_MAX +}; + +enum event_keys { + EVK_NONE, + EVK_PAGE_UP, + EVK_PAGE_DOWN, + EVK_END, + EVK_HOME, + EVK_LEFT, + EVK_UP, + EVK_RIGHT, + EVK_DOWN, + EVK_INSERT, + EVK_DELETE, + EVK_F1, + EVK_F2, + EVK_F3, + EVK_F4, + EVK_F5, + EVK_F6, + EVK_F7, + EVK_F8, + EVK_F9, + EVK_F10, + EVK_F11, + EVK_F12, + EVK_MAX +}; + diff --git a/src/include/reb-file.h b/src/include/reb-file.h new file mode 100644 index 0000000..6f4da91 --- /dev/null +++ b/src/include/reb-file.h @@ -0,0 +1,42 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Special file device definitions +** Date: 1-Dec-2009 +** File: reb-file.h +** +***********************************************************************/ + +// RFM - REBOL File Modes +enum { + RFM_READ = 0, + RFM_WRITE, + RFM_APPEND, + RFM_SEEK, + RFM_NEW, + RFM_READONLY, + RFM_TRUNCATE, + RFM_RESEEK, // file index has moved, reseek + RFM_NAME_MEM, // converted name allocated in mem + RFM_DIR = 16, +}; + +// RFE - REBOL File Error +enum { + RFE_BAD_PATH = 1, + RFE_NO_MODES, // No file modes specified + RFE_OPEN_FAIL, // File open failed + RFE_BAD_SEEK, // Seek not supported for this file + RFE_NO_HANDLE, // File struct has no handle + RFE_NO_SEEK, // Seek action failed + RFE_BAD_READ, // Read failed (general) + RFE_BAD_WRITE, // Write failed (general) + RFE_DISK_FULL, // No space on target volume +}; + +#define MAX_FILE_NAME 1022 diff --git a/src/include/reb-filereq.h b/src/include/reb-filereq.h new file mode 100644 index 0000000..a239ca9 --- /dev/null +++ b/src/include/reb-filereq.h @@ -0,0 +1,33 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: File requestor definitions +** Date: 1-Dec-2009 +** File: reb-filereq.h +** +***********************************************************************/ + +#define MAX_FILE_REQ_BUF (16*1024) + +typedef struct Reb_File_Requestor { + REBCNT flags; // multi, load/save, unicode + REBCHR *title; // title of requestor + REBCHR *button; // button name + REBCHR *dir; // dir path + REBCHR *files; // buffer to hold results + REBCHR *filter; // buffer to hold results + REBINT len; // length of buffer +} REBRFR; + +// File Request Flags: +enum { + FRF_MULTI, + FRF_SAVE, + FRF_KEEP, +}; + diff --git a/src/include/reb-host.h b/src/include/reb-host.h new file mode 100644 index 0000000..52df722 --- /dev/null +++ b/src/include/reb-host.h @@ -0,0 +1,27 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Include files for hosting +** Date: 1-Dec-2009 +** File: reb-host.h +** +***********************************************************************/ + +#include "reb-config.h" + +#include "reb-c.h" +#include "reb-defs.h" +#include "reb-args.h" +#include "reb-device.h" +#include "reb-file.h" +#include "reb-event.h" +#include "reb-evtypes.h" +#include "reb-net.h" +#include "reb-filereq.h" + + diff --git a/src/include/reb-net.h b/src/include/reb-net.h new file mode 100644 index 0000000..6755858 --- /dev/null +++ b/src/include/reb-net.h @@ -0,0 +1,34 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Network device definitions +** Date: 1-Dec-2009 +** File: reb-net.h +** +***********************************************************************/ + +// REBOL Socket types: +enum socket_types { + RST_UDP, // TCP or UDP + RST_LISTEN = 8, // LISTEN + RST_REVERSE, // DNS reverse +}; + +// REBOL Socket Modes (state flags) +enum { + RSM_OPEN = 0, // socket is allocated + RSM_ATTEMPT, // attempting connection + RSM_CONNECT, // connection is open + RSM_BIND, // socket is bound to port + RSM_LISTEN, // socket is listening (TCP) + RSM_SEND, // sending + RSM_RECEIVE, // receiving + RSM_ACCEPT, // an inbound connection +}; + +#define IPA(a,b,c,d) (a<<24 | b<<16 | c<<8 | d) diff --git a/src/include/reb-to.h b/src/include/reb-to.h new file mode 100644 index 0000000..a3ad08c --- /dev/null +++ b/src/include/reb-to.h @@ -0,0 +1 @@ +#define TO_WIN32 diff --git a/src/include/rebol-lib.h b/src/include/rebol-lib.h new file mode 100644 index 0000000..6531533 --- /dev/null +++ b/src/include/rebol-lib.h @@ -0,0 +1,27 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: REBOL Interface Library +** Build: A96 +** Date: 2-Dec-2009/15:36:34-8:00 +** File: rebol-lib.h +** +** AUTO-GENERATED FILE - Do not modify. (From: make-headers.r) +** +***********************************************************************/ + +extern REBOL_API void Reb_Version(REBYTE vers[]); // a-lib.c +extern REBOL_API REBINT Reb_Init(REBARGS *rargs, REBOL_HOST_LIB *lib); // a-lib.c +extern REBOL_API REBINT Reb_Start(REBINT reserved); // a-lib.c +extern REBOL_API void Reb_Reset(); // a-lib.c +extern REBOL_API void Reb_Escape(REBINT reserved); // a-lib.c +extern REBOL_API REBFLG Reb_Do_String(REBYTE *text); // a-lib.c +extern REBOL_API REBINT Reb_Do_Binary(REBYTE *bin, REBINT length, REBCNT flags, REBCNT key); // a-lib.c +extern REBOL_API void Reb_Print(REBYTE *fmt, ...); // a-lib.c +extern REBOL_API void Reb_Print_TOS(REBCNT flags, REBYTE *marker); // a-lib.c +extern REBOL_API REBINT Reb_Event(REBEVT *evt); // a-lib.c diff --git a/src/include/sys-net.h b/src/include/sys-net.h new file mode 100644 index 0000000..f49e03d --- /dev/null +++ b/src/include/sys-net.h @@ -0,0 +1,74 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: System network definitions +** Date: 1-Dec-2009 +** File: sys-net.h +** +***********************************************************************/ + +//----- Windows - "Network standards? What network standards?" -Bill G. +#ifdef TO_WIN32 + +#include + +#define GET_ERROR WSAGetLastError() +#define IOCTL ioctlsocket +#define CLOSE_SOCKET closesocket + +#define NE_ISCONN WSAEISCONN +#define NE_WOULDBLOCK WSAEWOULDBLOCK +#define NE_INPROGRESS WSAEINPROGRESS +#define NE_ALREADY WSAEALREADY +#define NE_NOTCONN WSAENOTCONN +#define NE_INVALID WSAEINVAL + +//----- BSD - The network standard the rest of the world uses +#else + +#include +#include +#include +#include +#include + +#define GET_ERROR errno +#define IOCTL ioctl +#define CLOSE_SOCKET close +#define SOCKET unsigned int + +#define NE_ISCONN EISCONN +#define NE_WOULDBLOCK EAGAIN // see include/asm/errno.h +#define NE_INPROGRESS EINPROGRESS +#define NE_ALREADY EALREADY +#define NE_NOTCONN ENOTCONN +#define NE_INVALID EINVAL + +// Null Win32 functions: +#define WSADATA int + +// FreeBSD mystery define: +#ifndef u_int32_t +#define u_int32_t long +#endif + +#ifndef HOSTENT +typedef struct hostent HOSTENT; +#endif + +#ifndef MAXGETHOSTSTRUCT +#define MAXGETHOSTSTRUCT ((sizeof(struct hostent)+15) & ~15) +#endif + +#endif // BSD + +typedef struct sockaddr_in SOCKAI; // Internet extensions + +#define BAD_SOCKET (~0) +#define MAX_TRANSFER 32000 // Max send/recv buffer size +#define MAX_HOST_NAME 256 // Max length of host name diff --git a/src/os/dev-dns.c b/src/os/dev-dns.c new file mode 100644 index 0000000..2f2afd1 --- /dev/null +++ b/src/os/dev-dns.c @@ -0,0 +1,205 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Device: DNS access +** Build: A95 +** Date: 27-Nov-2009 +** File: dev-dns.c +** Author: Carl Sassenrath +** Purpose: Calls local DNS services for domain name lookup. +** +** Notes: +** See MS WSAAsyncGetHost* details regarding multiple requests. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include +#include + +#include "reb-host.h" +#include "host-lib.h" +#include "sys-net.h" + +int Init_Net(REBREQ *); // Share same init +int Quit_Net(REBREQ *); + +void Signal_Device(REBREQ *req, REBINT type); + +#ifdef HAS_ASYNC_DNS +// Async DNS requires a window handle to signal completion (WSAASync) +extern HWND Event_Handle; +#endif + +/*********************************************************************** +** +*/ DEVICE_CMD Open_DNS(REBREQ *sock) +/* +***********************************************************************/ +{ + SET_OPEN(sock); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Close_DNS(REBREQ *sock) +/* +** Note: valid even if not open. +** +***********************************************************************/ +{ + // Terminate a pending request: +#ifdef HAS_ASYNC_DNS + if (GET_FLAG(sock->flags, RRF_PENDING)) { + CLR_FLAG(sock->flags, RRF_PENDING); + if (sock->handle) WSACancelAsyncRequest(sock->handle); + } +#endif + if (sock->net.host_info) OS_Free(sock->net.host_info); + sock->net.host_info = 0; + sock->handle = 0; + SET_CLOSED(sock); + return DR_DONE; // Removes it from device's pending list (if needed) +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Read_DNS(REBREQ *sock) +/* +** Initiate the GetHost request and return immediately. +** Note the temporary results buffer (must be freed later). +** +***********************************************************************/ +{ + void *host; +#ifdef HAS_ASYNC_DNS + HANDLE handle; +#else + HOSTENT *he; +#endif + + host = OS_Make(MAXGETHOSTSTRUCT); // be sure to free it + +#ifdef HAS_ASYNC_DNS + if (!GET_FLAG(sock->modes, RST_REVERSE)) // hostname lookup + handle = WSAAsyncGetHostByName(Event_Handle, WM_DNS, sock->data, host, MAXGETHOSTSTRUCT); + else + handle = WSAAsyncGetHostByAddr(Event_Handle, WM_DNS, (char*)&(sock->net.remote_ip), 4, AF_INET, host, MAXGETHOSTSTRUCT); + + if (handle != 0) { + sock->net.host_info = host; + sock->handle = handle; + return DR_PEND; // keep it on pending list + } +#else + // Use old-style blocking DNS (mainly for testing purposes): + if (GET_FLAG(sock->modes, RST_REVERSE)) { + he = gethostbyaddr((char*)&sock->net.remote_ip, 4, AF_INET); + if (he) { + sock->net.host_info = host; //??? + sock->data = he->h_name; + SET_FLAG(sock->flags, RRF_DONE); + return DR_DONE; + } + } + else { + he = gethostbyname(sock->data); + if (he) { + sock->net.host_info = host; // ?? who deallocs? + COPY_MEM((char*)&(sock->net.remote_ip), (char *)(*he->h_addr_list), 4); //he->h_length); + SET_FLAG(sock->flags, RRF_DONE); + return DR_DONE; + } + } +#endif + + OS_Free(host); + sock->net.host_info = 0; + + sock->error = GET_ERROR; + //Signal_Device(sock, EVT_ERROR); + return DR_ERROR; // Remove it from pending list +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Poll_DNS(REBREQ *dr) +/* +** Check for completed DNS requests. These are marked with +** RRF_DONE by the windows message event handler (dev-event.c). +** Completed requests are removed from the pending queue and +** event is signalled (for awake dispatch). +** +***********************************************************************/ +{ + REBDEV *dev = (REBDEV*)dr; // to keep compiler happy + REBREQ **prior = &dev->pending; + REBREQ *req; + BOOL change = FALSE; + HOSTENT *host; + + // Scan the pending request list: + for (req = *prior; req; req = *prior) { + + // If done or error, remove command from list: + if (GET_FLAG(req->flags, RRF_DONE)) { // req->error may be set + *prior = req->next; + req->next = 0; + CLR_FLAG(req->flags, RRF_PENDING); + + if (!req->error) { // success! + host = (HOSTENT*)req->net.host_info; + if (GET_FLAG(req->modes, RST_REVERSE)) + req->data = host->h_name; + else + COPY_MEM((char*)&(req->net.remote_ip), (char *)(*host->h_addr_list), 4); //he->h_length); + Signal_Device(req, EVT_READ); + } + else + Signal_Device(req, EVT_ERROR); + change = TRUE; + } + else prior = &req->next; + } + + return change; +} + + +/*********************************************************************** +** +** Command Dispatch Table (RDC_ enum order) +** +***********************************************************************/ + +static DEV_CMD Dev_Cmds[RDC_MAX] = +{ + Init_Net, // Shared init - called only once + Quit_Net, // Shared + Open_DNS, + Close_DNS, + Read_DNS, + 0, // write + Poll_DNS, +}; + +DEFINE_DEV(Dev_DNS, "DNS", 1, Dev_Cmds, RDC_MAX, 0); diff --git a/src/os/dev-net.c b/src/os/dev-net.c new file mode 100644 index 0000000..969ed44 --- /dev/null +++ b/src/os/dev-net.c @@ -0,0 +1,610 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Device: TCP/IP network access +** Build: A95 +** Date: 27-Nov-2009 +** File: dev-net.c +** Author: Carl Sassenrath +** Purpose: Supports TCP and UDP (but not raw socket modes.) +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include +#include + +#include "reb-host.h" +#include "host-lib.h" +#include "sys-net.h" + +#if (0) +#define WATCH1(s,a) printf(s, a) +#define WATCH2(s,a,b) printf(s, a, b) +#define WATCH4(s,a,b,c,d) printf(s, a, b, c, d) +#else +#define WATCH1(s,a) +#define WATCH2(s,a,b) +#define WATCH4(s,a,b,c,d) +#endif + +void Signal_Device(REBREQ *req, REBINT type); +DEVICE_CMD Listen_Socket(REBREQ *sock); + +#ifdef TO_WIN32 +extern HWND Event_Handle; // For WSAAsync API +#endif + + +/*********************************************************************** +** +** Local Functions +** +***********************************************************************/ + +static void Set_Addr(SOCKAI *sa, long ip, int port) +{ + // Set the IP address and port number in a socket_addr struct. + sa->sin_family = AF_INET; + sa->sin_addr.s_addr = ip; //htonl(ip); NOTE: REBOL stays in network byte order + sa->sin_port = htons((unsigned short)port); +} + +static void Get_Local_IP(REBREQ *sock) +{ + // Get the local IP address and port number. + // This code should be fast and never fail. + SOCKAI sa; + int len = sizeof(sa); + + getsockname(sock->socket, (struct sockaddr *)&sa, &len); + sock->net.local_ip = sa.sin_addr.s_addr; //htonl(ip); NOTE: REBOL stays in network byte order + sock->net.local_port = ntohs(sa.sin_port); +} + +static BOOL Nonblocking_Mode(SOCKET sock) +{ + // Set non-blocking mode. Return TRUE if no error. +#ifdef FIONBIO + long mode = 1; + return !IOCTL(sock, FIONBIO, &mode); +#else + int flags; + flags = fcntl(sock, F_GETFL, 0); + flags |= O_NONBLOCK; + //else flags &= ~O_NONBLOCK; + fcntl(sock, F_SETFL, flags); + return TRUE; +#endif +} + + +/*********************************************************************** +** +*/ int Init_Net(REBREQ *dr) +/* +** Intialize networking libraries and related interfaces. +** This function will be called prior to any socket functions. +** +***********************************************************************/ +{ + REBDEV *dev = (REBDEV*)dr; // just to keep compiler happy +#ifdef TO_WIN32 + WSADATA wsaData; + // Initialize Windows Socket API with given VERSION. + // It is ok to call twice, as long as WSACleanup twice. + if (WSAStartup(0x0101, &wsaData)) return DR_ERROR; +#endif + SET_FLAG(dev->flags, RDF_INIT); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ int Quit_Net(REBREQ *dr) +/* +** Close and cleanup networking libraries and related interfaces. +** +***********************************************************************/ +{ + REBDEV *dev = (REBDEV*)dr; // just to keep compiler happy +#ifdef TO_WIN32 + if (GET_FLAG(dev->flags, RDF_INIT)) WSACleanup(); +#endif + CLR_FLAG(dev->flags, RDF_INIT); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ int Host_Address(char *hostname, char *hostaddr) +/* +** Simple lookup of a host address. +** The hostaddr must be at least 16 bytes in size (IPv6). +** This is a synchronous function and blocks during access. +** +** On success, returns length of address. +** On failure, returns 0. +** +** Current version is IPv4 only. +** +***********************************************************************/ +{ + struct hostent *he; + + if (!(he = gethostbyname(hostname))) return DR_DONE; + + COPY_MEM(hostaddr, (char *)(*he->h_addr_list), he->h_length); + + return he->h_length; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Open_Socket(REBREQ *sock) +/* +** Setup a socket with the specified protocol and bind it to +** the related transport service. +** +** Returns 0 on success. +** On failure, error code is OS local. +** +** Note: This is an intialization procedure and no actual +** connection is made at this time. The IP address and port +** number are not needed, only the type of service required. +** +** After usage: +** Close_Socket() - to free OS allocations +** +***********************************************************************/ +{ + int type; + int protocol; + long result; + + sock->error = 0; + sock->state = 0; // clear all flags + + // Setup for correct type and protocol: + if (GET_FLAG(sock->modes, RST_UDP)) { + type = SOCK_DGRAM; + protocol = IPPROTO_UDP; + } + else { // TCP is default + type = SOCK_STREAM; + protocol = IPPROTO_TCP; + } + + // Bind to the transport service, return socket handle or error: + result = (int)socket(AF_INET, type, protocol); + + // Failed, get error code (os local): + if (result == BAD_SOCKET) { + sock->error = GET_ERROR; + return DR_ERROR; + } + + sock->socket = result; + SET_FLAG(sock->state, RSM_OPEN); + + // Set socket to non-blocking async mode: + if (!Nonblocking_Mode(sock->socket)) { + sock->error = GET_ERROR; + return DR_ERROR; + } + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Close_Socket(REBREQ *sock) +/* +** Close a socket. +** +** Returns 0 on success. +** On failure, error code is OS local. +** +***********************************************************************/ +{ + sock->error = 0; + + if (GET_FLAG(sock->state, RSM_OPEN)) { + + sock->state = 0; // clear: RSM_OPEN, RSM_CONNECT + + // If DNS pending, abort it: + if (sock->net.host_info) { // indicates DNS phase active +#ifdef HAS_ASYNC_DNS + if (sock->handle) WSACancelAsyncRequest(sock->handle); +#endif + OS_Free(sock->net.host_info); + sock->socket = sock->length; // Restore TCP socket (see Lookup) + } + + if (CLOSE_SOCKET(sock->socket)) { + sock->error = GET_ERROR; + return DR_ERROR; + } + } + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Lookup_Socket(REBREQ *sock) +/* +** Initiate the GetHost request and return immediately. +** This is very similar to the DNS device. +** The request will pend until the main event handler gets WM_DNS. +** Note the temporary results buffer (must be freed later). +** Note we use the sock->handle for the DNS handle. During use, +** we store the TCP socket in the length field. +** +***********************************************************************/ +{ +#ifdef TO_WIN32 + HANDLE handle; +#endif + HOSTENT *host; + +#ifdef HAS_ASYNC_DNS + // Check if we are polling for completion: + if (host = (HOSTENT*)(sock->net.host_info)) { + // The windows main event handler will change this when it gets WM_DNS event: + if (!GET_FLAG(sock->flags, RRF_DONE)) return DR_PEND; // still waiting + CLR_FLAG(sock->flags, RRF_DONE); + if (!sock->error) { // Success! + host = (HOSTENT*)sock->net.host_info; + COPY_MEM((char*)&(sock->net.remote_ip), (char *)(*host->h_addr_list), 4); //he->h_length); + Signal_Device(sock, EVT_LOOKUP); + } + else + Signal_Device(sock, EVT_ERROR); + OS_Free(host); // free what we allocated earlier + sock->socket = sock->length; // Restore TCP socket saved below + sock->net.host_info = 0; + return DR_DONE; + } + + // Else, make the lookup request: + host = OS_Make(MAXGETHOSTSTRUCT); // be sure to free it + handle = WSAAsyncGetHostByName(Event_Handle, WM_DNS, sock->data, (char*)host, MAXGETHOSTSTRUCT); + if (handle != 0) { + sock->net.host_info = host; + sock->length = sock->socket; // save TCP socket temporarily + sock->handle = handle; + return DR_PEND; // keep it on pending list + } + OS_Free(host); +#else + // Use old-style blocking DNS (mainly for testing purposes): + host = gethostbyname(sock->data); + sock->net.host_info = 0; // no allocated data + + if (host) { + COPY_MEM((char*)&(sock->net.remote_ip), (char *)(*host->h_addr_list), 4); //he->h_length); + CLR_FLAG(sock->flags, RRF_DONE); + Signal_Device(sock, EVT_LOOKUP); + return DR_DONE; + } +#endif + + sock->error = GET_ERROR; + //Signal_Device(sock, EVT_ERROR); + return DR_ERROR; // Remove it from pending list +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Connect_Socket(REBREQ *sock) +/* +** Connect a socket to a service. +** Only required for connection-based protocols (e.g. not UDP). +** The IP address must already be resolved before calling. +** +** This function is asynchronous. It will return immediately. +** You can call this function again to check the pending connection. +** +** The function will return: +** =0: connection succeeded (or already is connected) +** >0: in-progress, still trying +** <0: error occurred, no longer trying +** +** Before usage: +** Open_Socket() -- to allocate the socket +** +***********************************************************************/ +{ + int result; + SOCKAI sa; + + if (GET_FLAG(sock->modes, RST_LISTEN)) + return Listen_Socket(sock); + + if (GET_FLAG(sock->state, RSM_CONNECT)) return DR_DONE; // already connected + + Set_Addr(&sa, sock->net.remote_ip, sock->net.remote_port); + result = connect(sock->socket, (struct sockaddr *)&sa, sizeof(sa)); + + if (result != 0) result = GET_ERROR; + + WATCH2("connect() error: %d - %s\n", result, strerror(result)); + + switch (result) { + + case 0: // no error + case NE_ISCONN: + // Connected, set state: + CLR_FLAG(sock->state, RSM_ATTEMPT); + SET_FLAG(sock->state, RSM_CONNECT); + Get_Local_IP(sock); + Signal_Device(sock, EVT_CONNECT); + return DR_DONE; // done + +#ifdef TO_WIN32 + case NE_INVALID: // Corrects for Microsoft bug +#endif + case NE_WOULDBLOCK: + case NE_INPROGRESS: + case NE_ALREADY: + // Still trying: + SET_FLAG(sock->state, RSM_ATTEMPT); + return DR_PEND; + + default: + // An error happened: + CLR_FLAG(sock->state, RSM_ATTEMPT); + sock->error = result; + //Signal_Device(sock, EVT_ERROR); + return DR_ERROR; + } +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Transfer_Socket(REBREQ *sock) +/* +** Write or read a socket (for connection-based protocols). +** +** This function is asynchronous. It will return immediately. +** You can call this function again to check the pending connection. +** +** The mode is RSM_RECEIVE or RSM_SEND. +** +** The function will return: +** =0: succeeded +** >0: in-progress, still trying +** <0: error occurred, no longer trying +** +** Before usage: +** Open_Socket() +** Connect_Socket() +** Verify that RSM_CONNECT is true +** Setup the sock->data and sock->length +** +** Note that the mode flag is cleared by the caller, not here. +** +***********************************************************************/ +{ + int result; + long len; + int mode = (sock->command == RDC_READ ? RSM_RECEIVE : RSM_SEND); + + if (!GET_FLAG(sock->state, RSM_CONNECT)) { + sock->error = -18; + return DR_ERROR; + } + + SET_FLAG(sock->state, mode); + + // Limit size of transfer: + len = MIN(sock->length, MAX_TRANSFER); + + if (mode == RSM_SEND) { + // If host is no longer connected: + result = send(sock->socket, sock->data, len, 0); + WATCH2("send() len: %d actual: %d\n", len, result); + + if (result >= 0) { + sock->data += result; + sock->actual += result; + if (sock->actual >= sock->length) { + Signal_Device(sock, EVT_WROTE); + return DR_DONE; + } + return DR_PEND; + } + // if (result < 0) ... + } + else { + result = recv(sock->socket, sock->data, len, 0); + WATCH2("recv() len: %d result: %d\n", len, result); + + if (result > 0) { + sock->actual = result; + Signal_Device(sock, EVT_READ); + return DR_DONE; + } + if (result == 0) { // The socket gracefully closed. + sock->actual = 0; + CLR_FLAG(sock->state, RSM_CONNECT); // But, keep RRF_OPEN true + Signal_Device(sock, EVT_CLOSE); + return DR_DONE; + } + // if (result < 0) ... + } + + // Check error code: + result = GET_ERROR; + WATCH2("get error: %d %s\n", result, strerror(result)); + if (result == NE_WOULDBLOCK) return DR_PEND; // still waiting + + WATCH4("ERROR: recv(%d %x) len: %d error: %d\n", sock->socket, sock->data, len, result); + // A nasty error happened: + sock->error = result; + //Signal_Device(sock, EVT_ERROR); + return DR_ERROR; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Listen_Socket(REBREQ *sock) +/* +** Setup a server (listening) socket (TCP or UDP). +** +** Before usage: +** Open_Socket(); +** Set local_port to desired port number. +** +** Use this instead of Connect_Socket(). +** +***********************************************************************/ +{ + int result; + int len = 1; + SOCKAI sa; + + // Setup socket address range and port: + Set_Addr(&sa, INADDR_ANY, sock->net.local_port); + + // Allow listen socket reuse: + result = setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (char*)(&len), sizeof(len)); + if (result) { +lserr: + sock->error = GET_ERROR; + return DR_ERROR; + } + + // Bind the socket to our local address: + result = bind(sock->socket, (struct sockaddr *)&sa, sizeof(sa)); + if (result) goto lserr; + + SET_FLAG(sock->state, RSM_BIND); + + // For TCP connections, setup listen queue: + if (!GET_FLAG(sock->modes, RST_UDP)) { + result = listen(sock->socket, SOMAXCONN); + if (result) goto lserr; + SET_FLAG(sock->state, RSM_LISTEN); + } + + Get_Local_IP(sock); + sock->command = RDC_CREATE; // the command done on wakeup + + return DR_PEND; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Accept_Socket(REBREQ *sock) +/* +** Accept an inbound connection on a TCP listen socket. +** +** The function will return: +** =0: succeeded +** >0: in-progress, still trying +** <0: error occurred, no longer trying +** +** Before usage: +** Open_Socket(); +** Set local_port to desired port number. +** Listen_Socket(); +** +***********************************************************************/ +{ + SOCKAI sa; + REBREQ *news; + int len = sizeof(sa); + int result; + extern void Attach_Request(REBREQ **prior, REBREQ *req); + + // Accept a new socket, if there is one: + result = accept(sock->socket, (struct sockaddr *)&sa, &len); + + if (result == BAD_SOCKET) { + result = GET_ERROR; + if (result == NE_WOULDBLOCK) return DR_PEND; + sock->error = result; + //Signal_Device(sock, EVT_ERROR); + return DR_ERROR; + } + + // To report the new socket, the code here creates a temporary + // request and copies the listen request to it. Then, it stores + // the new values for IP and ports and links this request to the + // original via the sock->data. + news = MAKE_NEW(*news); // Be sure to deallocate it + CLEARS(news); +// *news = *sock; + news->device = sock->device; + + SET_OPEN(news); + SET_FLAG(news->state, RSM_OPEN); + SET_FLAG(news->state, RSM_CONNECT); + + news->socket = result; + news->net.remote_ip = sa.sin_addr.s_addr; //htonl(ip); NOTE: REBOL stays in network byte order + news->net.remote_port = ntohs(sa.sin_port); + Get_Local_IP(news); + + //Nonblocking_Mode(news->socket); ???Needed? + + Attach_Request((REBREQ**)&sock->data, news); + Signal_Device(sock, EVT_ACCEPT); + + // Even though we signalled, we keep the listen pending to + // accept additional connections. + return DR_PEND; +} + + +/*********************************************************************** +** +** Command Dispatch Table (RDC_ enum order) +** +***********************************************************************/ + +static DEV_CMD Dev_Cmds[RDC_MAX] = { + Init_Net, + Quit_Net, + Open_Socket, + Close_Socket, + Transfer_Socket, // Read + Transfer_Socket, // Write + 0, // poll + Connect_Socket, + 0, // query + 0, // modify + Accept_Socket, // Create + 0, // delete + 0, // rename + Lookup_Socket +}; + +DEFINE_DEV(Dev_Net, "TCP/IP Network", 1, Dev_Cmds, RDC_MAX, sizeof(REBREQ)); diff --git a/src/os/host-args.c b/src/os/host-args.c new file mode 100644 index 0000000..78e3aee --- /dev/null +++ b/src/os/host-args.c @@ -0,0 +1,267 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Command line argument processing +** Build: A95 +** Date: 27-Nov-2009 +** File: host-args.c +** Author: Carl Sassenrath +** Caution: OS independent +** Purpose: +** Parses command line arguments and options, storing them +** in a structure to be used by the REBOL library. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include + +#include "reb-config.h" +#include "reb-c.h" +#include "reb-args.h" + +#define ARG_BUF_SIZE 1024 + +extern int OS_Get_Current_Dir(REBCHR **lp); + +// REBOL Option --Words: + +const struct {const char *word; const int flag;} arg_words[] = { + // Keep in Alpha order! + {"args", RO_ARGS | RO_EXT}, + {"cgi", RO_CGI | RO_QUIET}, + {"debug", RO_DEBUG | RO_EXT}, + {"do", RO_DO | RO_EXT}, + {"halt", RO_HALT}, + {"help", RO_HELP}, + {"import", RO_IMPORT | RO_EXT}, + {"no-boot", RO_NO_BOOT}, + {"quiet", RO_QUIET}, + {"script", RO_SCRIPT | RO_EXT}, + {"secure", RO_SECURE | RO_EXT}, + {"trace", RO_TRACE}, + {"verbose", RO_VERBOSE}, + {"version", RO_VERSION | RO_EXT}, + {"", 0}, +}; + +// REBOL Option -Characters (in alpha sorted order): + +const struct arg_chr {const char cflg; const int flag;} arg_chars[] = { + {'?', RO_HELP}, + {'V', RO_VERS}, + {'c', RO_CGI | RO_QUIET}, + {'h', RO_HALT}, + {'q', RO_QUIET}, + {'s', RO_SECURE_MIN}, + {'t', RO_TRACE}, + {'v', RO_VERS}, + {'\0', 0}, +}; + +// REBOL Option +Characters: + +const struct arg_chr arg_chars2[] = { + {'s', RO_SECURE_MAX}, + {'\0', 0}, +}; + + +/*********************************************************************** +** +*/ static int find_option_word(REBCHR *word) +/* +** Scan options, return flag bits, else zero. +** +***********************************************************************/ +{ + int n; + int i; + char buf[16]; + + // Some shells will pass us the line terminator. Ignore it. + if (word[0] == '\r' || word[0] == '\n') return RO_IGNORE; + + FROM_OS_STR(buf, word, 15); + + for (i = 0; arg_words[i].flag; i++) { + n = strncmp(buf, arg_words[i].word, 15); // correct (bytes) + if (n < 0) break; + if (n == 0) return arg_words[i].flag; + } + return 0; +} + + +/*********************************************************************** +** +*/ static int find_option_char(REBCHR chr, const struct arg_chr list[]) +/* +** Scan option char flags, return flag bits, else zero. +** +***********************************************************************/ +{ + int i; + + // Some shells will pass us the line terminator. Ignore it. + if (chr == '\r' || chr == '\n') return RO_IGNORE; + + for (i = 0; list[i].flag; i++) { + if (chr < list[i].cflg) break; + if (chr == list[i].cflg) return list[i].flag; + } + return 0; +} + + +/*********************************************************************** +** +*/ static int Get_Ext_Arg(int flag, REBARGS *rargs, REBCHR *arg) +/* +** Get extended argument field. +** +***********************************************************************/ +{ + if (arg[1] == (REBCHR)'-') return flag; + + flag &= ~RO_EXT; + + switch (flag) { + + case RO_VERSION: + rargs->version = arg; + break; + + case RO_SCRIPT: + rargs->script = arg; + break; + + case RO_ARGS: + rargs->args = arg; + break; + + case RO_DO: + rargs->do_arg = arg; + break; + + case RO_DEBUG: + rargs->debug = arg; + break; + + case RO_SECURE: + rargs->secure = arg; + break; + + case RO_IMPORT: + rargs->import = arg; + break; + } + + return flag; +} + + +/*********************************************************************** +** +*/ void Parse_Args(int argc, REBCHR **argv, REBARGS *rargs) +/* +** Parse REBOL's command line arguments, setting options +** and values in the provided args structure. +** +***********************************************************************/ +{ + REBCHR *arg; + REBCHR *args = 0; // holds trailing args + int flag; + int i; + + CLEARS(rargs); + + // First arg is path to execuable (on most systems): + if (argc > 0) rargs->exe_path = *argv; + + OS_Get_Current_Dir(&rargs->home_dir); + + // Parse each argument: + for (i = 1; i < argc ; i++) { + arg = argv[i]; + if (arg == 0) continue; // shell bug + if (*arg == '-') { + if (arg[1] == '-') { + // --option words + flag = find_option_word(arg+2); + if (flag & RO_EXT) { + flag = Get_Ext_Arg(flag, rargs, (i+1 >= argc) ? 0 : argv[i+1]); + if ((flag & RO_EXT) == 0) i++; // used it + else flag &= ~RO_EXT; + } + if (!flag) flag = RO_HELP; + rargs->options |= flag; + } + else { + // -x option chars + while (*++arg) { + flag = find_option_char(*arg, arg_chars); + if (flag & RO_EXT) { + flag = Get_Ext_Arg(flag, rargs, (i+1 >= argc) ? 0 : argv[i+1]); + if ((flag & RO_EXT) == 0) i++; // used it + else flag &= ~RO_EXT; + } + if (!flag) flag = RO_HELP; + rargs->options |= flag; + } + } + } + else if (*arg == '+') { + // +x option chars + while (*++arg) { + flag = find_option_char(*arg, arg_chars2); + if (flag & RO_EXT) { + flag = Get_Ext_Arg(flag, rargs, (i+1 >= argc) ? 0 : argv[i+1]); + if ((flag & RO_EXT) == 0) i++; // used it + else flag &= ~RO_EXT; + } + if (!flag) flag = RO_HELP; + rargs->options |= flag; + } + } + else { + // script filename + if (!rargs->script) + rargs->script = arg; + else { + int len; + if (!args) { + args = MAKE_STR(ARG_BUF_SIZE); + args[0] = 0; + } + len = ARG_BUF_SIZE - LEN_STR(args) - 2; // space remaining + JOIN_STR(args, arg, len); + JOIN_STR(args, TXT(" "), 1); + } + } + } + + if (args) { + args[LEN_STR(args)-1] = 0; // remove trailing space + Get_Ext_Arg(RO_ARGS, rargs, args); + } +} + + + diff --git a/src/os/host-device.c b/src/os/host-device.c new file mode 100644 index 0000000..b35ff52 --- /dev/null +++ b/src/os/host-device.c @@ -0,0 +1,449 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Device management and command dispatch +** Build: A95 +** Date: 27-Nov-2009 +** File: host-device.c +** Author: Carl Sassenrath +** Caution: OS independent +** Purpose: +** This module implements a device management system for +** REBOL devices and tracking their I/O requests. +** It is intentionally kept very simple (makes debugging easy!) +** +** Special note: +** This module is parsed for function declarations used to +** build prototypes, tables, and other definitions. To change +** function arguments requires a rebuild of the REBOL library. +** +** Design comments: +** 1. Not a lot of devices are needed (dozens, not hundreds). +** 2. Devices are referenced by integer (index into device table). +** 3. A single device can support multiple requests. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include + +#include "reb-host.h" + +#include "host-lib.h" +#include "rebol-lib.h" + + +/*********************************************************************** +** +** REBOL Device Table +** +** The table most be in same order as the RDI_ enums. +** Table is in polling priority order. +** +***********************************************************************/ + +extern REBDEV Dev_StdIO; +extern REBDEV Dev_File; +extern REBDEV Dev_Event; +extern REBDEV Dev_Net; +extern REBDEV Dev_DNS; +#ifndef MIN_OS +extern REBDEV Dev_Clipboard; +#endif + +REBDEV *Devices[RDI_LIMIT] = +{ + 0, + &Dev_StdIO, + 0, + &Dev_File, +#ifdef TO_WIN32 // temporary? + &Dev_Event, +#else + 0, +#endif + &Dev_Net, + &Dev_DNS, +#ifndef MIN_OS + &Dev_Clipboard, +#endif + 0, +}; + + +static int Poll_Default(REBDEV *dev) +{ + // The default polling function for devices. + // Retries pending requests. Return TRUE if status changed. + REBREQ **prior = &dev->pending; + REBREQ *req; + BOOL change = FALSE; + int result; + + for (req = *prior; req; req = *prior) { + + // Call command again: + if (req->command < RDC_MAX) + result = dev->commands[req->command](req); + else { + result = -1; // invalid command, remove it + req->error = ((REBCNT)-1); + } + + // If done or error, remove command from list: + if (result <= 0) { + *prior = req->next; + req->next = 0; + CLR_FLAG(req->flags, RRF_PENDING); + change = TRUE; + } + else prior = &req->next; + } + + return change; +} + + +/*********************************************************************** +** +*/ void Attach_Request(REBREQ **node, REBREQ *req) +/* +** Attach a request to a device's pending or accept list. +** Node is a pointer to the head pointer of the req list. +** +***********************************************************************/ +{ + REBREQ *r; + +#ifdef special_debug + if (req->device == 5) + Debug_Fmt("Attach: %x %x %x %x", req, req->device, req->port, req->next); +#endif + + // See if its there, and get last req: + for (r = *node; r; r = *node) { + if (r == req) return; // already in list + node = &r->next; + } + + // Link the new request to end: + *node = req; + req->next = 0; + SET_FLAG(req->flags, RRF_PENDING); +} + + +/*********************************************************************** +** +*/ void Detach_Request(REBREQ **node, REBREQ *req) +/* +** Detach a request to a device's pending or accept list. +** If it is not in list, then no harm done. +** +***********************************************************************/ +{ + REBREQ *r; + +#ifdef special_debug + if (req->device == 5) + Debug_Fmt("Detach= n: %x r: %x p: %x %x", *node, req, req->port, &req->next); +#endif + + // See if its there, and get last req: + for (r = *node; r; r = *node) { +#ifdef special_debug + if (req->device == 5) + Debug_Fmt("Detach: r: %x n: %x", r, r->next); +#endif + if (r == req) { + *node = req->next; + req->next = 0; + CLR_FLAG(req->flags, RRF_PENDING); + return; + } + node = &r->next; + } +} + + +/*********************************************************************** +** +*/ void Done_Device(int handle, int error) +/* +** Given a handle mark the related request as done. +** (Used by DNS device). +** +***********************************************************************/ +{ + REBINT d; + REBDEV *dev; + REBREQ **prior; + REBREQ *req; + + for (d = RDI_NET; d <= RDI_DNS; d++) { + dev = Devices[d]; + prior = &dev->pending; + // Scan the pending requests, mark the one we got: + for (req = *prior; req; req = *prior) { + if ((int)(req->handle) == handle) { + req->error = error; // zero when no error + SET_FLAG(req->flags, RRF_DONE); + return; + } + prior = &req->next; + } + } +} + + +/*********************************************************************** +** +*/ void Signal_Device(REBREQ *req, REBINT type) +/* +** Generate a device event to awake a port on REBOL. +** +***********************************************************************/ +{ + REBEVT evt; + + CLEARS(&evt); + + evt.type = (REBYTE)type; + evt.req = req; + if (type == EVT_ERROR) evt.data = req->error; + + Reb_Event(&evt); // (returns 0 if queue is full, ignored) +} + + +/*********************************************************************** +** +*/ int OS_Call_Device(REBINT device, REBCNT command) +/* +** Shortcut for non-request calls to device. +** +** Init - Initialize any device-related resources (e.g. libs). +** Quit - Cleanup any device-related resources. +** Make - Create and initialize a request for a device. +** Free - Free a device request structure. +** Poll - Poll device for activity. +** +***********************************************************************/ +{ + REBDEV *dev; + + // Validate device: + if (device >= RDI_MAX || !(dev = Devices[device])) + return -1; + + // Validate command: + if (command > dev->max_command || dev->commands[command] == 0) + return -2; + + // Do command, return result: + return dev->commands[command]((REBREQ*)dev); +} + + +/*********************************************************************** +** +*/ int OS_Do_Device(REBREQ *req, REBCNT command) +/* +** Tell a device to perform a command. Non-blocking in many +** cases and will attach the request for polling. +** +** Returns: +** =0: for command success +** >0: for command still pending +** <0: for command error +** +***********************************************************************/ +{ + REBDEV *dev; + REBINT result; + + req->error = 0; // A94 - be sure its cleared + + // Validate device: + if (req->device >= RDI_MAX || !(dev = Devices[req->device])) { + req->error = RDE_NO_DEVICE; + return -1; + } + + // Confirm device is initialized. If not, return an error or init + // it if auto init option is set. + if (!GET_FLAG(dev->flags, RDF_INIT)) { + if (GET_FLAG(dev->flags, RDO_MUST_INIT)) { + req->error = RDE_NO_INIT; + return -1; + } + if (!dev->commands[RDC_INIT] || !dev->commands[RDC_INIT]((REBREQ*)dev)) + SET_FLAG(dev->flags, RDF_INIT); + } + + // Validate command: + if (command > dev->max_command || dev->commands[command] == 0) { + req->error = RDE_NO_COMMAND; + return -1; + } + + // Do the command: + req->command = command; + result = dev->commands[command](req); + + // If request is pending, attach it to device for polling: + if (result > 0) Attach_Request(&dev->pending, req); + else if (dev->pending) { + Detach_Request(&dev->pending, req); // often a no-op + if (result == DR_ERROR && GET_FLAG(req->flags, RRF_ALLOC)) { // not on stack + Signal_Device(req, EVT_ERROR); + } + } + + return result; +} + + +/*********************************************************************** +** +*/ REBREQ *OS_Make_Devreq(int device) +/* +***********************************************************************/ +{ + REBDEV *dev; + REBREQ *req; + int size; + + // Validate device: + if (device >= RDI_MAX || !(dev = Devices[device])) + return 0; + + size = dev->req_size ? dev->req_size : sizeof(REBREQ); + req = OS_Make(size); + CLEARS(req); + SET_FLAG(req->flags, RRF_ALLOC); + req->clen = size; + req->device = device; + + return req; +} + + +/*********************************************************************** +** +*/ int OS_Abort_Device(REBREQ *req) +/* +** Ask device to abort prior request. +** +***********************************************************************/ +{ + REBDEV *dev; + + if ((dev = Devices[req->device]) != 0) Detach_Request(&dev->pending, req); + return 0; +} + + +/*********************************************************************** +** +*/ int OS_Poll_Devices(void) +/* +** Poll devices for activity. +** +** Returns count of devices that changed status. +** +** Devices with pending lists will be called to see if +** there is a change in status of those requests. If so, +** those devices are allowed to change the state of those +** requests or call-back into special REBOL functions +** (e.g. Add_Event for GUI) to invoke special actions. +** +***********************************************************************/ +{ + int d; + int cnt = 0; + REBDEV *dev; + //int cc = 0; + + //printf("Polling Devices\n"); + + // Check each device: + for (d = 0; d < RDI_MAX; d++) { + dev = Devices[d]; + if (dev && (dev->pending || GET_FLAG(dev->flags, RDO_AUTO_POLL))) { + // If there is a custom polling function, use it: + if (dev->commands[RDC_POLL]) { + if (dev->commands[RDC_POLL]((REBREQ*)dev)) cnt++; + } + else { + if (Poll_Default(dev)) cnt++; + } + } + //if (cc != cnt) {printf("dev=%s ", dev->title); cc = cnt;} + } + + return cnt; +} + + +/*********************************************************************** +** +*/ REBINT OS_Wait(REBCNT millisec, REBCNT res) +/* +** Check if devices need attention, and if not, then wait. +** The wait can be interrupted by a GUI event, otherwise +** the timeout will wake it. +** +** Res specifies resolution. (No wait if less than this.) +** +** Returns: +** -1: Devices have changed state. +** 0: past given millsecs +** 1: wait in timer +** +** The time it takes for the devices to be scanned is +** subtracted from the timer value. +** +***********************************************************************/ +{ + REBREQ req; // OK: QUERY below does not store it + REBCNT delta; + i64 base; + + //printf("OS_Wait %d\n", millisec); + + base = OS_Delta_Time(0, 0); // start timing + + // Setup for timing: + CLEARS(&req); + req.device = RDI_EVENT; + + // Let any pending device I/O have a chance to run: + if (OS_Poll_Devices()) return -1; + + // Nothing, so wait for period of time + delta = (REBCNT)OS_Delta_Time(base, 0)/1000 + res; + if (delta >= millisec) return 0; + millisec -= delta; // account for time lost above + req.length = millisec; + + //printf("Wait: %d ms\n", millisec); + OS_Do_Device(&req, RDC_QUERY); // wait for timer or other event + + return 1; // layer above should check delta again +} diff --git a/src/os/host-init.c b/src/os/host-init.c new file mode 100644 index 0000000..99ea1f5 --- /dev/null +++ b/src/os/host-init.c @@ -0,0 +1,672 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Host custom init code +** Build: A96 +** Date: 2-Dec-2009/15:37:15-8:00 +** File: host-init.h +** +** AUTO-GENERATED FILE - Do not modify. (From: make-host-init.r) +** +***********************************************************************/ + +const unsigned char Reb_Init_Code[6532] = { + 120, 156, 237, 60, 107, 115, 219, 198, 181, 247, + 179, 126, 197, 154, 153, 142, 237, 76, 192, 151, + 36, 91, 70, 235, 106, 28, 219, 105, 50, 227, + 76, 51, 174, 219, 126, 224, 40, 51, 16, 176, + 36, 81, 129, 0, 2, 128, 162, 152, 56, 255, + 253, 158, 115, 246, 129, 221, 197, 2, 164, 100, + 245, 182, 31, 46, 19, 219, 228, 62, 206, 158, + 247, 57, 123, 118, 129, 63, 178, 183, 69, 185, + 175, 210, 213, 186, 97, 31, 223, 127, 251, 215, + 15, 236, 19, 143, 215, 121, 145, 21, 171, 148, + 215, 108, 30, 188, 227, 113, 48, 159, 78, 95, + 77, 102, 231, 225, 233, 203, 112, 118, 30, 92, + 132, 211, 233, 201, 73, 189, 175, 27, 190, 153, + 36, 105, 148, 241, 184, 169, 39, 73, 21, 237, + 66, 22, 23, 121, 195, 239, 26, 182, 56, 97, + 240, 105, 246, 37, 15, 234, 146, 199, 33, 91, + 92, 103, 69, 124, 243, 228, 138, 81, 71, 148, + 55, 105, 16, 101, 105, 84, 67, 15, 46, 21, + 235, 158, 10, 7, 211, 87, 252, 148, 81, 90, + 61, 145, 127, 39, 60, 78, 55, 81, 102, 124, + 217, 21, 85, 242, 132, 233, 193, 118, 59, 53, + 107, 168, 85, 1, 216, 45, 154, 109, 153, 113, + 9, 79, 118, 93, 23, 119, 208, 225, 91, 71, + 14, 136, 211, 42, 206, 184, 30, 211, 193, 66, + 13, 203, 210, 210, 1, 100, 17, 22, 111, 171, + 91, 132, 242, 181, 181, 58, 95, 46, 129, 123, + 206, 60, 139, 85, 60, 3, 192, 53, 183, 135, + 200, 190, 101, 154, 101, 65, 201, 243, 150, 50, + 192, 104, 197, 157, 149, 105, 84, 181, 37, 26, + 136, 51, 178, 125, 21, 109, 54, 17, 180, 57, + 132, 172, 170, 40, 145, 64, 5, 127, 197, 223, + 38, 73, 30, 81, 12, 124, 177, 200, 73, 243, + 91, 94, 53, 193, 38, 106, 170, 20, 25, 175, + 154, 17, 111, 248, 41, 241, 151, 212, 152, 235, + 167, 160, 88, 43, 94, 13, 126, 177, 121, 75, + 176, 2, 160, 190, 225, 149, 67, 140, 67, 114, + 150, 230, 93, 209, 96, 99, 16, 71, 165, 195, + 53, 106, 254, 87, 145, 230, 190, 246, 50, 106, + 96, 177, 92, 43, 181, 34, 228, 107, 223, 138, + 193, 46, 77, 154, 181, 33, 0, 102, 194, 211, + 28, 178, 216, 119, 80, 216, 101, 145, 237, 87, + 69, 222, 161, 166, 220, 214, 107, 23, 88, 197, + 107, 222, 21, 69, 85, 52, 81, 195, 187, 122, + 81, 199, 81, 102, 54, 187, 36, 213, 235, 168, + 228, 238, 18, 245, 13, 223, 121, 64, 149, 146, + 227, 90, 114, 66, 44, 54, 202, 232, 72, 180, + 220, 122, 237, 163, 169, 162, 188, 94, 22, 213, + 198, 68, 173, 207, 97, 88, 224, 113, 98, 38, + 72, 181, 219, 211, 40, 95, 101, 142, 197, 201, + 191, 37, 231, 237, 127, 58, 158, 160, 32, 123, + 53, 12, 191, 35, 142, 181, 100, 128, 51, 117, + 83, 120, 124, 196, 47, 18, 66, 167, 173, 59, + 244, 214, 15, 22, 44, 26, 220, 116, 40, 241, + 41, 242, 52, 150, 223, 161, 121, 83, 228, 73, + 216, 42, 101, 84, 181, 93, 160, 71, 237, 172, + 237, 181, 158, 149, 23, 121, 240, 43, 175, 10, + 249, 147, 223, 242, 60, 40, 18, 5, 229, 26, + 228, 197, 21, 20, 4, 200, 235, 70, 117, 165, + 214, 18, 0, 209, 128, 186, 138, 182, 117, 13, + 172, 15, 181, 114, 70, 155, 18, 197, 32, 198, + 110, 27, 5, 165, 254, 101, 11, 64, 213, 176, + 98, 155, 39, 92, 173, 189, 73, 27, 189, 52, + 125, 15, 174, 1, 187, 204, 28, 171, 224, 25, + 237, 203, 244, 78, 67, 32, 225, 37, 154, 208, + 106, 163, 57, 80, 241, 146, 71, 141, 254, 177, + 204, 200, 113, 11, 198, 69, 213, 74, 33, 84, + 239, 56, 47, 229, 247, 91, 24, 82, 84, 45, + 235, 129, 113, 252, 4, 100, 226, 198, 78, 161, + 233, 253, 177, 179, 6, 157, 204, 87, 74, 223, + 116, 224, 202, 18, 55, 122, 166, 13, 4, 213, + 216, 109, 69, 14, 85, 82, 51, 236, 200, 0, + 43, 66, 91, 113, 253, 47, 64, 67, 123, 138, + 168, 138, 58, 141, 117, 250, 171, 105, 175, 173, + 201, 39, 20, 87, 45, 227, 112, 7, 197, 85, + 145, 101, 142, 254, 38, 85, 81, 118, 225, 245, + 167, 5, 57, 223, 73, 2, 148, 85, 129, 10, + 116, 113, 143, 121, 46, 156, 189, 114, 179, 124, + 217, 24, 158, 13, 179, 156, 246, 231, 181, 148, + 74, 42, 255, 221, 42, 41, 29, 18, 151, 10, + 218, 253, 2, 83, 244, 160, 81, 168, 152, 38, + 254, 81, 61, 89, 185, 142, 54, 219, 204, 232, + 118, 88, 129, 144, 154, 182, 123, 32, 122, 93, + 103, 219, 74, 15, 84, 140, 128, 4, 174, 74, + 151, 251, 78, 72, 117, 150, 17, 227, 126, 237, + 132, 94, 221, 157, 223, 22, 217, 173, 209, 45, + 124, 111, 235, 81, 181, 7, 183, 147, 29, 224, + 76, 21, 213, 77, 47, 121, 177, 148, 191, 232, + 236, 102, 54, 73, 10, 60, 174, 120, 30, 115, + 151, 129, 54, 130, 124, 115, 93, 212, 181, 75, + 61, 8, 133, 231, 201, 16, 252, 101, 122, 28, + 111, 151, 34, 171, 51, 225, 24, 105, 18, 112, + 207, 93, 196, 138, 12, 198, 208, 148, 231, 205, + 177, 99, 45, 189, 24, 28, 186, 87, 65, 217, + 34, 127, 93, 223, 246, 200, 83, 100, 95, 238, + 248, 27, 222, 209, 19, 101, 63, 91, 202, 16, + 253, 50, 220, 80, 214, 224, 211, 110, 32, 160, + 73, 203, 108, 223, 35, 59, 23, 144, 118, 166, + 62, 62, 235, 116, 196, 143, 132, 118, 65, 93, + 81, 187, 225, 217, 74, 175, 96, 94, 37, 146, + 41, 11, 243, 38, 53, 216, 105, 167, 11, 208, + 19, 220, 166, 124, 215, 157, 146, 15, 232, 121, + 177, 217, 128, 228, 217, 111, 63, 7, 39, 63, + 7, 180, 71, 248, 57, 248, 57, 88, 92, 157, + 252, 46, 6, 20, 57, 178, 233, 209, 98, 165, + 114, 89, 215, 89, 20, 223, 132, 108, 58, 134, + 255, 216, 73, 92, 96, 8, 122, 113, 54, 166, + 255, 217, 9, 106, 78, 200, 102, 243, 139, 177, + 252, 195, 78, 74, 190, 35, 207, 57, 123, 57, + 29, 203, 63, 224, 248, 82, 176, 125, 108, 124, + 53, 31, 203, 63, 208, 152, 35, 191, 231, 103, + 211, 177, 252, 195, 78, 118, 235, 20, 69, 52, + 63, 63, 31, 203, 63, 136, 193, 150, 11, 4, + 232, 231, 170, 226, 200, 109, 250, 69, 40, 237, + 35, 253, 147, 6, 84, 24, 117, 169, 19, 187, + 247, 176, 237, 161, 101, 36, 72, 104, 66, 254, + 230, 77, 164, 6, 209, 164, 60, 186, 221, 139, + 69, 136, 136, 140, 71, 75, 252, 137, 84, 193, + 140, 134, 35, 217, 211, 150, 200, 77, 84, 21, + 152, 27, 83, 63, 142, 40, 178, 20, 157, 155, + 226, 4, 180, 148, 219, 138, 24, 41, 134, 208, + 172, 2, 18, 197, 149, 36, 111, 118, 14, 141, + 52, 17, 246, 187, 16, 64, 94, 206, 199, 240, + 255, 236, 5, 208, 11, 59, 76, 4, 125, 250, + 106, 252, 226, 21, 112, 10, 185, 14, 62, 12, + 230, 189, 124, 49, 158, 191, 24, 19, 59, 121, + 158, 3, 1, 179, 23, 211, 241, 197, 124, 124, + 6, 4, 196, 85, 186, 169, 17, 165, 249, 28, + 72, 154, 142, 95, 192, 176, 219, 180, 200, 48, + 182, 1, 224, 233, 248, 213, 20, 65, 167, 40, + 204, 217, 203, 139, 241, 233, 25, 252, 15, 88, + 166, 249, 141, 68, 8, 68, 10, 219, 115, 96, + 48, 165, 3, 196, 175, 233, 249, 24, 165, 210, + 68, 4, 23, 208, 187, 56, 27, 207, 78, 81, + 38, 60, 85, 132, 204, 145, 228, 87, 128, 119, + 122, 91, 84, 123, 67, 118, 56, 19, 53, 15, + 231, 158, 75, 25, 159, 66, 219, 205, 58, 186, + 73, 17, 9, 32, 14, 255, 204, 95, 160, 204, + 174, 49, 126, 64, 235, 217, 92, 112, 121, 70, + 218, 64, 121, 210, 252, 12, 87, 193, 118, 224, + 69, 4, 57, 91, 200, 206, 144, 121, 240, 7, + 225, 65, 202, 78, 202, 62, 29, 159, 17, 227, + 119, 17, 233, 223, 5, 14, 1, 64, 103, 160, + 105, 101, 84, 70, 123, 41, 112, 104, 63, 125, + 9, 44, 188, 65, 197, 21, 52, 11, 21, 216, + 144, 249, 9, 176, 47, 0, 1, 129, 22, 41, + 223, 233, 197, 248, 252, 2, 193, 1, 229, 81, + 13, 155, 57, 129, 44, 77, 21, 127, 164, 162, + 73, 242, 17, 189, 249, 84, 199, 251, 26, 24, + 152, 68, 85, 50, 17, 105, 146, 29, 237, 243, + 104, 3, 43, 140, 34, 204, 238, 70, 210, 165, + 52, 123, 101, 130, 102, 210, 52, 155, 27, 161, + 86, 155, 36, 217, 254, 114, 89, 163, 160, 231, + 119, 115, 181, 47, 138, 48, 224, 77, 239, 166, + 182, 115, 115, 18, 17, 141, 152, 72, 213, 108, + 196, 32, 156, 175, 112, 115, 170, 129, 130, 210, + 219, 13, 41, 164, 131, 72, 144, 94, 166, 137, + 174, 107, 20, 142, 248, 181, 171, 162, 242, 50, + 132, 109, 208, 86, 145, 33, 19, 56, 61, 30, + 50, 180, 21, 0, 124, 138, 217, 149, 76, 116, + 85, 83, 83, 148, 136, 168, 240, 147, 203, 109, + 30, 75, 172, 70, 239, 82, 216, 244, 65, 188, + 98, 17, 219, 1, 2, 197, 142, 225, 152, 177, + 100, 157, 108, 90, 172, 138, 107, 157, 98, 232, + 204, 110, 244, 79, 209, 11, 157, 223, 176, 127, + 252, 240, 142, 45, 129, 75, 223, 0, 161, 244, + 3, 128, 22, 219, 70, 76, 146, 208, 38, 69, + 217, 164, 69, 94, 51, 248, 183, 110, 55, 164, + 10, 142, 234, 197, 12, 203, 158, 151, 23, 193, + 46, 74, 193, 91, 127, 228, 205, 182, 202, 33, + 106, 109, 56, 100, 125, 13, 207, 246, 99, 246, + 174, 0, 57, 52, 140, 6, 0, 255, 89, 89, + 21, 49, 175, 107, 218, 254, 52, 245, 88, 250, + 243, 73, 84, 7, 105, 205, 70, 31, 120, 116, + 203, 21, 93, 81, 205, 210, 90, 67, 128, 172, + 16, 184, 0, 178, 195, 192, 0, 68, 41, 38, + 76, 0, 149, 40, 67, 118, 131, 171, 100, 205, + 166, 100, 119, 123, 96, 166, 96, 96, 186, 164, + 185, 162, 51, 100, 82, 19, 144, 135, 19, 209, + 22, 0, 36, 182, 168, 4, 226, 168, 48, 50, + 2, 33, 15, 66, 80, 130, 27, 14, 127, 149, + 79, 32, 86, 36, 219, 152, 35, 169, 160, 123, + 130, 67, 237, 2, 130, 252, 5, 182, 42, 102, + 8, 77, 184, 210, 131, 4, 125, 98, 8, 125, + 119, 7, 0, 30, 151, 90, 160, 212, 136, 159, + 109, 158, 33, 179, 218, 105, 70, 31, 233, 224, + 6, 242, 44, 57, 203, 237, 152, 40, 67, 209, + 26, 168, 62, 98, 130, 36, 143, 148, 103, 33, + 140, 14, 103, 225, 183, 43, 123, 124, 84, 66, + 204, 79, 212, 58, 48, 72, 247, 26, 3, 145, + 200, 124, 47, 73, 36, 171, 21, 104, 99, 133, + 243, 202, 65, 59, 205, 107, 72, 168, 20, 192, + 22, 13, 185, 80, 92, 148, 123, 103, 70, 235, + 24, 196, 36, 66, 147, 117, 134, 24, 36, 91, + 125, 87, 172, 132, 96, 224, 129, 185, 16, 5, + 88, 3, 211, 238, 16, 233, 130, 90, 194, 174, + 28, 216, 100, 13, 151, 45, 16, 31, 123, 76, + 73, 174, 193, 16, 50, 94, 57, 232, 136, 214, + 64, 24, 134, 7, 85, 225, 59, 159, 162, 242, + 6, 9, 95, 70, 144, 45, 118, 145, 45, 171, + 20, 92, 89, 3, 238, 254, 124, 218, 237, 149, + 11, 43, 31, 67, 75, 185, 178, 49, 32, 129, + 161, 45, 70, 180, 30, 141, 12, 71, 194, 106, + 39, 184, 103, 147, 95, 5, 195, 61, 92, 195, + 15, 168, 68, 189, 75, 155, 120, 109, 206, 243, + 175, 134, 31, 42, 34, 176, 133, 97, 23, 190, + 15, 164, 221, 18, 243, 9, 126, 125, 205, 56, + 100, 243, 37, 191, 242, 78, 232, 35, 14, 63, + 219, 220, 230, 120, 205, 179, 101, 255, 178, 219, + 28, 25, 33, 9, 241, 89, 156, 249, 249, 101, + 155, 54, 61, 248, 120, 155, 235, 117, 113, 12, + 104, 10, 104, 29, 144, 39, 254, 95, 226, 91, + 235, 96, 164, 146, 118, 92, 140, 114, 6, 34, + 34, 76, 174, 33, 3, 94, 81, 201, 71, 187, + 97, 109, 213, 168, 219, 29, 51, 104, 87, 16, + 161, 103, 96, 9, 105, 222, 134, 219, 177, 112, + 79, 34, 204, 83, 125, 12, 232, 88, 190, 97, + 97, 178, 21, 253, 184, 179, 224, 100, 153, 69, + 43, 220, 229, 66, 202, 132, 78, 205, 68, 87, + 142, 16, 37, 164, 150, 194, 38, 109, 50, 110, + 118, 178, 17, 29, 239, 132, 32, 127, 234, 75, + 70, 6, 189, 56, 67, 24, 128, 65, 9, 116, + 224, 142, 233, 178, 167, 27, 63, 70, 79, 200, + 120, 218, 172, 121, 101, 141, 126, 205, 158, 138, + 146, 12, 248, 101, 138, 82, 194, 219, 5, 150, + 239, 155, 176, 57, 104, 55, 100, 112, 119, 240, + 199, 16, 123, 135, 11, 106, 33, 99, 5, 87, + 112, 212, 179, 203, 113, 65, 53, 9, 127, 133, + 70, 143, 51, 154, 88, 171, 71, 75, 70, 183, + 61, 206, 104, 237, 240, 108, 139, 51, 251, 116, + 209, 141, 220, 164, 84, 130, 215, 42, 172, 47, + 164, 234, 200, 159, 162, 91, 239, 73, 97, 164, + 169, 53, 24, 137, 178, 204, 224, 57, 166, 0, + 102, 112, 102, 51, 128, 156, 241, 124, 213, 172, + 47, 37, 72, 201, 145, 118, 78, 82, 72, 44, + 187, 90, 131, 169, 154, 112, 7, 118, 178, 246, + 22, 253, 215, 129, 84, 77, 166, 103, 66, 253, + 69, 237, 4, 173, 218, 200, 179, 48, 77, 195, + 44, 237, 47, 127, 253, 118, 204, 158, 34, 33, + 144, 243, 35, 65, 99, 145, 35, 227, 175, 44, + 170, 27, 95, 250, 163, 243, 158, 3, 9, 143, + 200, 172, 163, 218, 244, 198, 174, 245, 42, 163, + 109, 237, 107, 34, 146, 175, 142, 134, 161, 190, + 18, 195, 73, 18, 49, 108, 39, 43, 37, 40, + 126, 151, 154, 227, 41, 19, 116, 224, 35, 45, + 114, 184, 101, 161, 21, 199, 178, 62, 91, 166, + 174, 216, 59, 82, 167, 157, 59, 238, 84, 116, + 120, 243, 109, 58, 158, 130, 240, 241, 155, 44, + 215, 234, 56, 57, 197, 233, 150, 94, 218, 82, + 125, 147, 36, 40, 83, 165, 194, 77, 193, 192, + 94, 89, 27, 12, 36, 143, 149, 160, 181, 170, + 91, 199, 45, 74, 74, 251, 154, 144, 212, 114, + 210, 24, 147, 79, 52, 137, 208, 128, 4, 181, + 114, 162, 45, 81, 90, 63, 40, 139, 170, 17, + 240, 181, 49, 213, 150, 49, 225, 158, 49, 130, + 32, 188, 0, 63, 3, 140, 192, 49, 87, 26, + 162, 237, 185, 228, 252, 137, 98, 15, 251, 51, + 53, 181, 191, 189, 121, 28, 194, 181, 241, 85, + 159, 107, 88, 249, 102, 34, 211, 107, 12, 236, + 157, 240, 212, 2, 84, 38, 174, 16, 147, 0, + 77, 157, 80, 77, 100, 128, 3, 50, 251, 72, + 186, 99, 138, 109, 89, 21, 155, 35, 5, 167, + 118, 80, 90, 72, 150, 38, 30, 199, 126, 139, + 25, 104, 4, 173, 146, 37, 18, 227, 75, 11, + 101, 185, 119, 146, 251, 34, 61, 95, 224, 130, + 167, 154, 241, 58, 205, 87, 64, 208, 42, 133, + 1, 164, 210, 106, 239, 132, 223, 53, 174, 74, + 214, 196, 193, 35, 145, 237, 104, 192, 132, 236, + 228, 53, 65, 214, 155, 35, 82, 27, 83, 24, + 106, 123, 173, 61, 165, 77, 208, 63, 193, 209, + 146, 238, 41, 179, 149, 59, 62, 166, 40, 221, + 173, 129, 16, 244, 27, 162, 31, 164, 5, 90, + 36, 14, 146, 198, 191, 107, 130, 200, 95, 251, + 9, 193, 197, 211, 60, 109, 168, 190, 24, 136, + 49, 182, 30, 252, 0, 189, 41, 108, 178, 33, + 92, 162, 236, 255, 129, 178, 175, 183, 215, 182, + 224, 165, 109, 242, 210, 220, 53, 250, 87, 132, + 196, 179, 117, 104, 120, 94, 85, 148, 24, 156, + 234, 120, 205, 201, 197, 200, 132, 90, 153, 172, + 7, 2, 196, 251, 82, 77, 151, 130, 48, 220, + 149, 18, 73, 40, 183, 64, 87, 122, 169, 73, + 180, 3, 15, 97, 37, 238, 10, 241, 181, 105, + 68, 235, 80, 230, 145, 253, 94, 129, 184, 186, + 78, 51, 55, 21, 39, 23, 46, 32, 163, 159, + 110, 162, 52, 187, 4, 224, 70, 102, 97, 143, + 23, 123, 2, 182, 158, 204, 116, 124, 23, 179, + 237, 93, 77, 200, 114, 164, 109, 237, 203, 80, + 196, 26, 254, 32, 37, 84, 141, 100, 188, 33, + 222, 111, 138, 100, 171, 145, 166, 100, 44, 148, + 217, 25, 59, 101, 223, 127, 250, 244, 19, 214, + 22, 154, 2, 82, 83, 38, 4, 34, 229, 123, + 11, 148, 167, 5, 149, 77, 103, 170, 134, 36, + 66, 194, 186, 105, 90, 161, 215, 251, 60, 14, + 240, 120, 69, 176, 152, 150, 188, 46, 146, 189, + 246, 221, 88, 80, 55, 121, 32, 189, 43, 49, + 154, 58, 49, 135, 4, 117, 160, 153, 109, 235, + 132, 84, 26, 172, 125, 207, 107, 131, 244, 90, + 212, 231, 141, 217, 118, 151, 18, 120, 8, 246, + 156, 4, 132, 28, 181, 180, 195, 146, 66, 224, + 103, 90, 175, 152, 42, 224, 65, 84, 198, 185, + 160, 70, 96, 161, 21, 255, 101, 203, 107, 129, + 87, 119, 87, 138, 173, 151, 194, 212, 22, 18, + 233, 34, 207, 193, 243, 0, 223, 36, 138, 37, + 143, 33, 59, 222, 112, 216, 35, 0, 19, 144, + 115, 1, 175, 42, 176, 238, 209, 39, 209, 58, + 50, 192, 34, 94, 82, 135, 137, 27, 86, 145, + 192, 74, 205, 136, 94, 142, 231, 24, 18, 247, + 52, 95, 22, 147, 53, 224, 141, 250, 250, 244, + 45, 90, 6, 152, 206, 39, 220, 57, 218, 147, + 58, 163, 39, 253, 131, 33, 113, 129, 92, 231, + 208, 148, 238, 86, 113, 132, 102, 57, 25, 129, + 243, 168, 182, 108, 244, 71, 22, 175, 17, 80, + 243, 250, 239, 159, 190, 11, 46, 70, 125, 27, + 47, 7, 144, 96, 6, 228, 13, 234, 60, 26, + 27, 124, 214, 160, 229, 39, 52, 134, 45, 196, + 134, 216, 17, 153, 158, 173, 243, 36, 75, 63, + 108, 23, 33, 254, 129, 44, 68, 57, 57, 20, + 153, 137, 160, 216, 159, 79, 84, 61, 161, 119, + 159, 46, 245, 129, 73, 141, 234, 112, 202, 80, + 177, 214, 255, 116, 119, 177, 75, 112, 71, 246, + 22, 214, 217, 17, 39, 152, 226, 118, 193, 91, + 169, 131, 103, 154, 44, 29, 220, 123, 158, 80, + 225, 238, 60, 106, 183, 92, 169, 144, 140, 24, + 223, 29, 238, 29, 103, 22, 181, 109, 26, 5, + 252, 35, 245, 199, 230, 153, 21, 130, 201, 12, + 251, 35, 3, 201, 128, 198, 208, 55, 225, 22, + 132, 23, 169, 208, 25, 25, 23, 6, 69, 104, + 242, 72, 78, 79, 151, 190, 74, 132, 148, 142, + 31, 211, 195, 92, 103, 38, 202, 130, 1, 98, + 135, 222, 228, 146, 133, 237, 80, 129, 202, 194, + 246, 119, 78, 183, 33, 48, 53, 194, 24, 207, + 238, 173, 200, 168, 192, 30, 129, 11, 104, 148, + 133, 11, 147, 97, 11, 156, 28, 10, 31, 42, + 249, 163, 81, 243, 148, 113, 32, 226, 196, 55, + 96, 3, 117, 89, 64, 82, 220, 14, 29, 210, + 190, 29, 196, 43, 159, 214, 246, 35, 35, 102, + 28, 198, 198, 136, 3, 146, 4, 240, 60, 129, + 114, 171, 157, 225, 154, 198, 7, 88, 108, 86, + 20, 55, 219, 210, 140, 125, 52, 197, 53, 80, + 233, 63, 60, 85, 221, 14, 170, 251, 46, 22, + 253, 28, 81, 128, 93, 158, 60, 196, 91, 128, + 244, 66, 85, 177, 52, 35, 169, 191, 134, 216, + 231, 10, 143, 192, 89, 251, 245, 94, 140, 123, + 48, 87, 159, 164, 64, 121, 42, 143, 235, 202, + 183, 31, 39, 203, 59, 33, 106, 129, 25, 201, + 255, 198, 43, 72, 150, 100, 14, 206, 218, 20, + 96, 212, 95, 233, 236, 39, 82, 192, 252, 18, + 34, 21, 89, 88, 23, 28, 160, 73, 22, 208, + 168, 136, 39, 239, 17, 92, 250, 98, 125, 44, + 99, 189, 40, 252, 248, 70, 136, 75, 145, 188, + 10, 120, 30, 23, 184, 52, 228, 80, 163, 120, + 189, 205, 111, 168, 238, 215, 143, 194, 191, 133, + 181, 143, 198, 94, 193, 226, 97, 236, 137, 123, + 131, 35, 134, 209, 161, 184, 125, 216, 47, 29, + 15, 240, 30, 54, 162, 105, 236, 167, 222, 175, + 118, 157, 86, 159, 95, 39, 60, 218, 32, 234, + 115, 26, 253, 129, 156, 206, 50, 204, 136, 237, + 40, 134, 181, 93, 197, 207, 232, 71, 228, 69, + 148, 203, 204, 4, 183, 207, 184, 115, 181, 182, + 55, 134, 206, 108, 32, 123, 143, 86, 188, 189, + 235, 40, 171, 78, 157, 226, 74, 123, 0, 160, + 167, 200, 47, 33, 139, 240, 94, 182, 106, 55, + 88, 32, 196, 130, 120, 184, 149, 122, 41, 163, + 55, 49, 29, 229, 90, 93, 105, 2, 29, 63, + 169, 141, 152, 189, 193, 172, 86, 179, 80, 173, + 51, 144, 208, 244, 112, 230, 211, 186, 162, 211, + 136, 199, 102, 13, 164, 99, 174, 185, 154, 56, + 118, 4, 39, 189, 110, 23, 193, 183, 224, 176, + 26, 18, 30, 225, 164, 188, 243, 179, 74, 22, + 60, 36, 34, 207, 45, 36, 155, 117, 145, 168, + 219, 218, 114, 192, 21, 27, 189, 31, 175, 198, + 236, 47, 239, 63, 125, 195, 190, 127, 255, 230, + 221, 55, 236, 167, 191, 254, 237, 19, 227, 77, + 60, 54, 230, 54, 120, 125, 22, 34, 234, 50, + 197, 235, 90, 122, 238, 111, 63, 228, 162, 180, + 91, 44, 85, 227, 55, 144, 136, 138, 99, 50, + 244, 105, 41, 236, 247, 120, 133, 119, 191, 193, + 19, 61, 227, 176, 208, 182, 230, 203, 109, 134, + 91, 148, 2, 156, 84, 149, 38, 188, 29, 141, + 139, 62, 31, 179, 183, 81, 133, 99, 158, 252, + 110, 100, 134, 42, 218, 232, 155, 2, 31, 37, + 197, 170, 231, 25, 94, 148, 183, 72, 163, 187, + 97, 181, 201, 1, 233, 149, 217, 2, 179, 68, + 45, 170, 52, 143, 170, 189, 46, 141, 255, 166, + 0, 203, 193, 0, 89, 109, 220, 62, 8, 103, + 14, 52, 197, 196, 253, 132, 69, 219, 166, 216, + 68, 77, 10, 105, 106, 182, 7, 204, 223, 111, + 202, 102, 47, 215, 167, 194, 6, 191, 139, 226, + 38, 219, 179, 44, 5, 245, 198, 21, 198, 6, + 81, 50, 115, 6, 163, 134, 44, 178, 163, 42, + 162, 57, 132, 127, 201, 100, 108, 163, 216, 150, + 192, 86, 226, 60, 242, 86, 137, 246, 171, 17, + 115, 124, 188, 140, 87, 40, 182, 75, 45, 68, + 170, 145, 108, 138, 44, 145, 45, 232, 59, 228, + 23, 107, 242, 136, 116, 107, 50, 27, 79, 71, + 236, 237, 199, 15, 223, 249, 246, 145, 186, 222, + 139, 172, 151, 148, 95, 49, 127, 114, 128, 215, + 179, 243, 68, 18, 6, 62, 1, 49, 160, 105, + 132, 183, 228, 26, 46, 228, 61, 97, 2, 175, + 162, 229, 231, 166, 123, 13, 85, 135, 64, 167, + 148, 48, 213, 200, 161, 245, 71, 182, 92, 67, + 192, 65, 157, 211, 168, 233, 189, 200, 200, 250, + 177, 4, 133, 195, 88, 71, 112, 6, 58, 114, + 156, 151, 22, 27, 148, 108, 190, 114, 193, 153, + 238, 161, 221, 255, 118, 253, 194, 79, 194, 218, + 92, 199, 96, 168, 133, 168, 45, 226, 223, 79, + 174, 58, 186, 72, 23, 110, 48, 79, 233, 168, + 163, 184, 54, 173, 235, 51, 6, 45, 48, 218, + 172, 45, 81, 154, 195, 172, 121, 42, 233, 9, + 169, 160, 16, 128, 179, 216, 232, 80, 172, 14, + 169, 108, 153, 162, 183, 47, 129, 188, 209, 215, + 147, 175, 29, 149, 22, 93, 193, 91, 81, 30, + 129, 33, 219, 102, 25, 92, 56, 131, 190, 47, + 234, 246, 184, 147, 80, 64, 4, 131, 52, 97, + 127, 250, 51, 187, 152, 122, 243, 113, 97, 102, + 196, 61, 129, 52, 192, 0, 213, 12, 71, 22, + 0, 55, 217, 239, 66, 178, 33, 12, 237, 13, + 254, 94, 67, 254, 247, 102, 69, 202, 43, 170, + 139, 35, 67, 217, 76, 206, 217, 226, 155, 216, + 251, 24, 59, 65, 183, 4, 211, 114, 158, 126, + 169, 45, 99, 32, 110, 234, 219, 109, 84, 184, + 74, 164, 40, 197, 249, 184, 13, 75, 156, 140, + 211, 215, 132, 86, 166, 175, 162, 188, 105, 87, + 31, 118, 85, 42, 183, 142, 147, 78, 137, 207, + 10, 249, 86, 148, 19, 20, 75, 95, 6, 214, + 35, 130, 13, 101, 139, 66, 2, 17, 120, 223, + 63, 76, 174, 252, 202, 37, 126, 72, 251, 49, + 205, 133, 232, 10, 8, 165, 64, 62, 32, 96, + 23, 94, 49, 164, 152, 6, 112, 148, 218, 139, + 50, 159, 152, 187, 88, 224, 73, 186, 248, 46, + 66, 208, 51, 131, 148, 80, 244, 60, 103, 159, + 157, 230, 167, 37, 232, 199, 115, 71, 39, 138, + 18, 235, 162, 26, 156, 140, 184, 159, 217, 182, + 194, 27, 239, 207, 52, 35, 20, 212, 43, 115, + 180, 188, 151, 247, 204, 49, 58, 123, 121, 221, + 190, 184, 178, 103, 91, 97, 241, 179, 114, 94, + 106, 81, 237, 102, 29, 112, 186, 29, 85, 224, + 121, 207, 157, 16, 187, 98, 97, 177, 95, 50, + 30, 53, 4, 125, 157, 142, 29, 201, 140, 37, + 115, 122, 224, 137, 244, 204, 170, 40, 117, 164, + 212, 95, 224, 70, 184, 33, 235, 215, 66, 225, + 190, 124, 158, 203, 54, 157, 142, 33, 250, 76, + 136, 176, 61, 178, 134, 212, 235, 79, 125, 101, + 107, 204, 37, 188, 21, 149, 4, 178, 92, 58, + 44, 68, 218, 200, 106, 33, 57, 201, 150, 32, + 59, 103, 220, 92, 140, 155, 224, 49, 8, 242, + 22, 71, 205, 97, 152, 185, 131, 176, 147, 107, + 143, 195, 16, 127, 27, 229, 101, 44, 187, 227, + 81, 125, 99, 172, 15, 192, 187, 128, 52, 51, + 245, 23, 152, 0, 80, 182, 49, 94, 67, 2, + 187, 134, 89, 210, 23, 200, 21, 189, 228, 26, + 30, 231, 40, 7, 33, 25, 218, 179, 45, 95, + 24, 110, 205, 63, 132, 150, 209, 15, 208, 248, + 199, 244, 47, 135, 215, 13, 130, 13, 236, 238, + 151, 41, 36, 139, 11, 195, 115, 226, 67, 168, + 27, 180, 116, 0, 143, 45, 79, 252, 115, 174, + 28, 216, 226, 116, 184, 195, 240, 185, 239, 184, + 194, 45, 200, 225, 80, 95, 42, 35, 143, 101, + 250, 82, 182, 72, 168, 150, 139, 7, 29, 211, + 58, 213, 98, 43, 103, 9, 69, 111, 103, 29, + 95, 204, 113, 22, 165, 198, 9, 26, 1, 217, + 147, 231, 168, 68, 230, 165, 35, 182, 248, 106, + 4, 201, 233, 103, 8, 211, 179, 17, 68, 204, + 98, 195, 69, 50, 233, 47, 47, 224, 40, 246, + 204, 31, 245, 158, 98, 243, 115, 127, 21, 225, + 179, 191, 249, 171, 209, 28, 86, 90, 140, 166, + 103, 136, 194, 104, 122, 14, 40, 244, 65, 207, + 139, 64, 106, 77, 207, 26, 98, 157, 190, 233, + 197, 205, 243, 251, 84, 179, 122, 17, 62, 237, + 99, 13, 126, 70, 211, 211, 126, 246, 212, 156, + 7, 5, 166, 83, 131, 248, 15, 192, 62, 235, + 135, 13, 222, 77, 171, 252, 67, 193, 159, 247, + 131, 223, 226, 143, 170, 184, 219, 63, 136, 245, + 21, 79, 210, 10, 162, 198, 227, 8, 224, 108, + 88, 0, 3, 250, 185, 205, 97, 183, 185, 166, + 71, 1, 31, 204, 164, 151, 253, 224, 137, 65, + 1, 46, 241, 32, 46, 197, 25, 62, 62, 39, + 74, 26, 143, 195, 169, 1, 129, 214, 84, 224, + 236, 91, 204, 179, 80, 63, 222, 242, 192, 62, + 64, 21, 172, 97, 87, 13, 241, 24, 216, 107, + 39, 237, 62, 15, 39, 143, 128, 208, 73, 29, + 225, 209, 10, 223, 117, 112, 115, 119, 34, 147, + 222, 215, 236, 233, 218, 127, 102, 68, 107, 30, + 115, 122, 129, 31, 114, 191, 71, 213, 79, 7, + 74, 167, 210, 95, 99, 74, 182, 56, 0, 80, + 160, 98, 64, 244, 85, 59, 251, 14, 54, 48, + 21, 160, 236, 144, 98, 153, 191, 238, 137, 31, + 149, 23, 97, 42, 132, 72, 249, 174, 31, 12, + 85, 158, 31, 133, 41, 143, 207, 24, 98, 78, + 151, 93, 67, 219, 70, 229, 145, 152, 246, 201, + 255, 77, 218, 21, 111, 235, 166, 216, 24, 68, + 67, 254, 144, 224, 35, 83, 95, 166, 20, 199, + 152, 249, 151, 168, 136, 58, 217, 233, 164, 222, + 230, 231, 240, 201, 5, 229, 226, 11, 44, 179, + 33, 171, 175, 44, 254, 15, 78, 28, 94, 88, + 83, 232, 243, 53, 175, 141, 232, 124, 248, 24, + 196, 222, 130, 174, 184, 255, 225, 1, 245, 25, + 58, 229, 233, 237, 130, 205, 135, 190, 85, 243, + 1, 118, 119, 184, 227, 234, 137, 9, 7, 236, + 149, 74, 93, 82, 219, 197, 13, 3, 149, 38, + 63, 20, 236, 240, 209, 217, 71, 181, 24, 150, + 36, 82, 212, 161, 77, 148, 111, 163, 140, 246, + 0, 21, 42, 250, 240, 57, 218, 1, 219, 48, + 15, 210, 6, 142, 40, 239, 231, 14, 204, 196, + 128, 153, 113, 152, 153, 113, 146, 181, 1, 254, + 223, 228, 45, 142, 54, 239, 131, 150, 125, 52, + 181, 125, 39, 252, 125, 226, 125, 3, 83, 81, + 134, 66, 119, 196, 227, 122, 42, 232, 179, 61, + 111, 60, 146, 253, 34, 137, 118, 238, 2, 244, + 9, 231, 158, 132, 44, 212, 25, 175, 236, 31, + 209, 78, 201, 99, 145, 143, 137, 189, 153, 165, + 171, 139, 52, 7, 194, 197, 23, 199, 220, 199, + 139, 181, 174, 26, 169, 61, 193, 67, 111, 137, + 12, 43, 218, 79, 0, 26, 95, 206, 246, 127, + 173, 97, 131, 70, 126, 47, 219, 144, 207, 207, + 254, 71, 168, 104, 55, 203, 15, 149, 206, 127, + 175, 226, 81, 141, 177, 75, 213, 35, 20, 235, + 253, 23, 0, 31, 114, 59, 11, 11, 62, 67, + 52, 120, 55, 77, 247, 86, 56, 121, 62, 37, + 47, 177, 73, 152, 182, 174, 61, 130, 158, 245, + 221, 178, 232, 222, 151, 235, 41, 100, 157, 24, + 77, 178, 180, 26, 178, 175, 126, 155, 190, 155, + 190, 249, 189, 109, 157, 27, 205, 110, 151, 93, + 49, 149, 131, 141, 59, 8, 110, 201, 211, 125, + 166, 8, 63, 238, 89, 165, 238, 248, 164, 238, + 17, 189, 151, 247, 136, 140, 190, 15, 88, 75, + 252, 81, 186, 236, 176, 125, 164, 211, 60, 71, + 20, 249, 142, 85, 145, 87, 135, 131, 57, 223, + 5, 219, 42, 101, 11, 60, 123, 208, 4, 80, + 209, 245, 202, 58, 48, 236, 92, 87, 239, 45, + 110, 15, 20, 234, 229, 106, 221, 194, 48, 199, + 253, 3, 116, 101, 26, 33, 49, 157, 238, 221, + 119, 139, 231, 114, 144, 236, 199, 243, 190, 167, + 200, 101, 247, 30, 248, 144, 106, 254, 166, 211, + 64, 16, 92, 212, 94, 245, 87, 175, 60, 106, + 196, 35, 62, 164, 192, 150, 190, 254, 110, 107, + 155, 44, 147, 154, 245, 255, 251, 249, 70, 67, + 19, 123, 247, 39, 138, 94, 58, 174, 124, 109, + 28, 93, 122, 71, 169, 99, 208, 215, 214, 161, + 166, 177, 160, 195, 166, 246, 184, 73, 67, 192, + 34, 187, 53, 200, 185, 242, 111, 119, 186, 53, + 226, 123, 136, 97, 100, 138, 65, 236, 110, 136, + 176, 160, 205, 206, 229, 102, 147, 158, 9, 1, + 237, 116, 252, 197, 23, 48, 222, 178, 122, 157, + 175, 250, 14, 174, 148, 43, 69, 116, 40, 167, + 197, 119, 93, 208, 69, 190, 128, 158, 157, 221, + 220, 204, 224, 207, 28, 95, 102, 152, 226, 115, + 43, 66, 237, 209, 197, 30, 121, 130, 165, 189, + 130, 231, 161, 5, 61, 232, 208, 49, 151, 175, + 34, 239, 60, 148, 105, 172, 53, 124, 59, 209, + 119, 37, 159, 152, 211, 30, 73, 116, 6, 0, + 83, 172, 96, 37, 158, 65, 148, 215, 35, 212, + 181, 11, 255, 84, 124, 26, 186, 111, 111, 44, + 173, 162, 61, 49, 56, 112, 127, 147, 30, 19, + 49, 132, 67, 39, 6, 107, 126, 23, 36, 233, + 10, 31, 33, 163, 135, 47, 212, 1, 26, 72, + 142, 92, 55, 207, 19, 47, 192, 161, 109, 102, + 187, 134, 125, 132, 132, 223, 235, 122, 203, 159, + 152, 88, 244, 66, 145, 228, 25, 67, 95, 51, + 223, 229, 5, 243, 3, 46, 176, 101, 7, 42, + 223, 225, 170, 130, 34, 248, 153, 212, 81, 216, + 80, 140, 158, 75, 202, 217, 103, 193, 52, 165, + 190, 208, 170, 67, 216, 0, 111, 142, 225, 145, + 250, 232, 85, 181, 231, 215, 171, 29, 156, 43, + 111, 207, 40, 123, 80, 247, 75, 142, 158, 127, + 116, 213, 203, 252, 136, 187, 219, 7, 156, 75, + 127, 29, 236, 240, 2, 226, 185, 102, 235, 196, + 206, 247, 57, 0, 169, 243, 64, 138, 61, 119, + 88, 48, 29, 203, 58, 82, 149, 12, 219, 186, + 73, 75, 244, 124, 161, 214, 175, 71, 210, 23, + 241, 36, 176, 56, 5, 165, 227, 108, 244, 184, + 202, 205, 30, 33, 188, 246, 12, 149, 188, 133, + 194, 147, 29, 49, 25, 15, 109, 247, 151, 199, + 72, 230, 24, 181, 31, 16, 15, 1, 233, 23, + 222, 189, 253, 81, 239, 98, 71, 93, 76, 150, + 187, 33, 255, 19, 127, 122, 203, 112, 96, 223, + 35, 111, 203, 247, 157, 197, 119, 22, 53, 162, + 197, 64, 96, 145, 122, 218, 3, 245, 79, 237, + 187, 23, 52, 184, 47, 173, 127, 107, 100, 156, + 40, 118, 58, 159, 78, 61, 239, 193, 193, 207, + 23, 58, 140, 163, 43, 107, 254, 221, 27, 205, + 24, 146, 13, 189, 72, 236, 161, 2, 232, 217, + 49, 30, 177, 155, 106, 227, 110, 168, 158, 118, + 100, 163, 217, 252, 244, 236, 252, 197, 203, 139, + 87, 211, 232, 58, 78, 248, 242, 205, 183, 111, + 223, 189, 255, 78, 38, 118, 148, 33, 202, 196, + 222, 120, 229, 134, 120, 231, 2, 101, 249, 186, + 81, 61, 180, 251, 61, 48, 183, 250, 132, 155, + 41, 218, 41, 17, 95, 245, 149, 241, 219, 217, + 120, 102, 228, 140, 98, 219, 66, 178, 233, 188, + 199, 13, 19, 101, 236, 15, 242, 206, 43, 86, + 68, 126, 252, 135, 137, 205, 27, 179, 196, 110, + 247, 24, 23, 176, 156, 250, 160, 121, 149, 202, + 17, 145, 120, 240, 53, 100, 179, 115, 31, 103, + 197, 45, 38, 47, 230, 184, 95, 11, 60, 85, + 7, 167, 188, 224, 239, 83, 101, 6, 63, 254, + 214, 59, 130, 204, 219, 177, 248, 78, 229, 176, + 179, 94, 148, 116, 238, 171, 106, 22, 26, 251, + 78, 71, 83, 123, 139, 213, 206, 163, 126, 230, + 83, 126, 94, 227, 208, 111, 197, 226, 249, 165, + 92, 48, 142, 176, 14, 40, 182, 1, 234, 9, + 3, 186, 141, 160, 31, 48, 19, 15, 35, 87, + 124, 217, 255, 218, 41, 247, 70, 38, 109, 57, + 165, 111, 180, 106, 130, 184, 164, 56, 154, 130, + 190, 81, 15, 64, 3, 154, 186, 63, 102, 80, + 230, 157, 50, 184, 255, 50, 225, 30, 237, 71, + 228, 243, 233, 146, 75, 247, 60, 143, 160, 155, + 150, 71, 73, 186, 139, 233, 109, 148, 117, 30, + 162, 237, 194, 144, 146, 164, 211, 56, 249, 164, + 73, 72, 51, 165, 47, 214, 63, 219, 11, 141, + 170, 9, 192, 209, 191, 161, 184, 166, 171, 26, + 251, 150, 144, 208, 5, 52, 53, 83, 188, 159, + 143, 45, 22, 230, 19, 221, 248, 166, 201, 178, + 204, 100, 249, 116, 114, 23, 236, 118, 187, 0, + 215, 192, 202, 5, 237, 162, 120, 210, 62, 212, + 45, 238, 44, 95, 9, 192, 238, 45, 47, 252, + 252, 191, 142, 59, 83, 186, 151, 120, 5, 125, + 66, 52, 255, 17, 187, 24, 198, 233, 158, 86, + 83, 208, 171, 142, 31, 100, 52, 198, 13, 218, + 131, 166, 99, 201, 82, 191, 111, 165, 167, 82, + 74, 47, 156, 204, 249, 165, 161, 37, 84, 128, + 177, 68, 254, 35, 236, 103, 177, 64, 64, 61, + 81, 146, 64, 236, 168, 125, 130, 111, 151, 245, + 213, 55, 205, 143, 202, 193, 240, 125, 43, 188, + 231, 216, 188, 173, 113, 132, 254, 1, 131, 79, + 197, 19, 4, 249, 170, 140, 188, 232, 209, 250, + 54, 164, 154, 245, 70, 17, 73, 101, 202, 134, + 177, 181, 71, 199, 187, 138, 125, 76, 162, 237, + 189, 50, 31, 202, 234, 142, 198, 197, 125, 90, + 66, 125, 244, 187, 97, 154, 184, 244, 99, 181, + 166, 231, 34, 28, 113, 246, 218, 69, 144, 38, + 230, 96, 85, 59, 236, 73, 61, 151, 237, 179, + 74, 176, 126, 56, 153, 8, 149, 192, 7, 40, + 188, 207, 78, 244, 176, 128, 82, 77, 235, 1, + 253, 30, 183, 64, 3, 213, 107, 109, 252, 6, + 78, 46, 174, 123, 125, 85, 209, 119, 200, 30, + 47, 31, 39, 95, 89, 226, 27, 14, 47, 69, + 233, 214, 48, 190, 214, 73, 119, 36, 126, 248, + 137, 242, 199, 193, 204, 241, 6, 253, 118, 114, + 232, 89, 14, 23, 131, 206, 80, 37, 209, 126, + 123, 52, 253, 131, 255, 229, 147, 247, 23, 34, + 86, 174, 30, 55, 231, 108, 101, 232, 185, 42, + 209, 146, 208, 191, 65, 163, 212, 225, 154, 110, + 9, 209, 43, 175, 168, 84, 146, 208, 20, 131, + 113, 250, 17, 172, 67, 120, 225, 71, 73, 81, + 108, 110, 245, 155, 112, 232, 247, 61, 163, 16, + 68, 203, 234, 56, 142, 245, 134, 33, 121, 187, + 1, 201, 56, 70, 255, 186, 133, 239, 193, 74, + 47, 65, 191, 84, 222, 221, 124, 81, 202, 145, + 87, 126, 250, 21, 144, 86, 233, 188, 43, 101, + 8, 125, 123, 1, 175, 204, 104, 234, 253, 100, + 32, 11, 22, 143, 170, 183, 134, 126, 116, 234, + 33, 48, 205, 41, 49, 116, 206, 65, 78, 174, + 254, 231, 127, 1, 232, 152, 205, 79, 134, 110, + 0, 0}; diff --git a/src/os/host-main.c b/src/os/host-main.c new file mode 100644 index 0000000..28a2468 --- /dev/null +++ b/src/os/host-main.c @@ -0,0 +1,149 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Name: host-main.c +** What: Host environment main entry point +** Note: OS independent +** Author: Carl Sassenrath +** Purpose: +** Provides the outer environment that calls the REBOL lib. +** This module is more or less just an example and includes +** a very simple console prompt. +** +************************************************************************ +** +** WARNING to PROGRAMMERS: +** +** This open source code is strictly managed to maintain +** source consistency according to our standards, not yours. +** +** 1. Keep code clear and simple. +** 2. Document odd code, your reasoning, or gotchas. +** 3. Use our source style for code, indentation, comments, etc. +** 4. It must work on Win32, Linux, OS X, BSD, big/little endian. +** 5. Test your code really well before submitting it. +** +***********************************************************************/ + +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#define OS_LIB_TABLE // include the host-lib dispatch table + +#include "reb-host.h" // standard host include files +#include "host-lib.h" // OS host library (dispatch table) +#include "rebol-lib.h" // REBOL library (function prototypes) +#include "host-init.h" // custom REBOL boot code + +/**********************************************************************/ + +#define PROMPT_STR ">> " +#define RESULT_STR "== " + +REBARGS Main_Args; + +#ifdef TO_WIN32 +HINSTANCE App_Instance = 0; +#endif + +// Host bare-bones stdio functs: +void Open_StdIO(void); +void Put_Str(char *buf); +REBYTE *Get_Str(); + +void Host_Crash(REBYTE *reason) { + OS_Crash("REBOL host failure", reason); +} + + +/*********************************************************************** +** +** MAIN ENTRY POINT +** +** Win32 args: +** inst: current instance of the application (app handle) +** prior: always NULL (use a mutex for single inst of app) +** cmd: command line string (or use GetCommandLine) +** show: how app window is to be shown (e.g. maximize, minimize, etc.) +** +** Win32 return: +** If the function succeeds, terminating when it receives a WM_QUIT +** message, it should return the exit value contained in that +** message's wParam parameter. If the function terminates before +** entering the message loop, it should return zero. +** +** Posix args: as you would expect in C. +** Posix return: ditto. +** +***********************************************************************/ + +#ifdef TO_WIN32 +int WINAPI WinMain(HINSTANCE inst, HINSTANCE prior, LPSTR cmd, int show) +#else +int main(int argc, char **argv) +#endif +{ + REBYTE vers[8]; + REBYTE *line; + REBINT n; + +#ifdef TO_WIN32 // In Win32 get args manually: + int argc; + REBCHR **argv; + // Fetch the win32 unicoded program arguments: + argv = CommandLineToArgvW(GetCommandLineW(), &argc); + App_Instance = inst; +#endif + + Host_Lib = &Host_Lib_Init; + + Parse_Args(argc, argv, &Main_Args); + + vers[0] = 5; // len + Reb_Version(&vers[0]); + + Open_StdIO(); // also sets up interrupt handler + + // Initialize the REBOL library: + if (!Host_Lib) Host_Crash("Missing host lib"); + n = Reb_Init(&Main_Args, Host_Lib); + if (n == 1) Host_Crash("REBOL DLL wrong size"); + if (n == 2) Host_Crash("REBOL DLL wrong version/checksum"); + + // Initialize host bundled source code: + Reb_Do_Binary(Reb_Init_Code, REB_INIT_SIZE, 0, 0); + + // Run REBOL's mezzanine bootstrap: + n = (Main_Args.options & RO_NO_BOOT) ? TRUE : Reb_Start(0); // TRUE on halt + + // Console line input loop (just an example, can be improved): + if ( + !Main_Args.script // no script was provided + || n // script was halted + || Main_Args.options & RO_HALT // --halt option + ){ + while (TRUE) { + Put_Str(PROMPT_STR); + if ((line = Get_Str())) { + Reb_Do_String(line); + Reb_Print_TOS(0, RESULT_STR); + OS_Free(line); + } + else break; // EOS + } + } + + OS_Call_Device(RDI_STDIO, RDC_CLOSE); + + return 0; +} diff --git a/src/os/host-stdio.c b/src/os/host-stdio.c new file mode 100644 index 0000000..3a007b7 --- /dev/null +++ b/src/os/host-stdio.c @@ -0,0 +1,159 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Simple helper functions for host-side standard I/O +** Build: A95 +** Date: 27-Nov-2009 +** File: host-stdio.c +** Author: Carl Sassenrath +** Caution: OS independent +** Purpose: +** Interfaces to the stdio device for standard I/O on the host. +** All stdio within REBOL uses UTF-8 encoding so the functions +** shown here operate on UTF-8 bytes, regardless of the OS. +** The conversion to wide-chars for OSes like Win32 is done in +** the StdIO Device code. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include +#include "reb-host.h" +#include "host-lib.h" + +void Host_Crash(REBYTE *reason); + +// Temporary globals: (either move or remove?!) +REBREQ Std_IO_Req; +static REBYTE *inbuf; +static REBCNT inbuf_len = 32*1024; + +static REBYTE *Get_Next_Line() +{ + REBYTE *bp = inbuf; + REBYTE *out; + REBCNT len; + + // Scan for line terminator or end: + for (bp = inbuf; *bp != CR && *bp != LF && *bp != 0; bp++); + + // If found, copy the line and remove it from buffer: + if (*bp) { + if (*bp == CR && bp[1] == LF) bp++; + len = bp - inbuf; + out = OS_Make(len + 2); + COPY_BYTES(out, inbuf, len+1); + out[len+1] = 0; + MOVE_MEM(inbuf, bp+1, 1+strlen(bp+1)); + return out; + } + + return 0; // more input needed +} + +static int Fetch_Buf() +{ + REBCNT len = strlen(inbuf); + + Std_IO_Req.data = inbuf + len; + Std_IO_Req.length = inbuf_len - len - 1; + Std_IO_Req.actual = 0; + + OS_Do_Device(&Std_IO_Req, RDC_READ); + + // If error, don't crash, just ignore it: + if (Std_IO_Req.error) return 0; //Host_Crash("stdio read"); + + // Terminate (LF) last line? + if (len > 0 && Std_IO_Req.actual == 0) { + inbuf[len++] = LF; + inbuf[len] = 0; + return TRUE; + } + + // Null terminate buffer: + len = Std_IO_Req.actual; + Std_IO_Req.data[len] = 0; + return len > 0; +} + + +/*********************************************************************** +** +*/ void Open_StdIO(void) +/* +** Open REBOL's standard IO device. This same device is used +** by both the host code and the R3 DLL itself. +** +** This must be done before any other initialization is done +** in order to output banners or errors. +** +***********************************************************************/ +{ + CLEARS(&Std_IO_Req); + Std_IO_Req.clen = sizeof(Std_IO_Req); + Std_IO_Req.device = RDI_STDIO; + + OS_Do_Device(&Std_IO_Req, RDC_OPEN); + + if (Std_IO_Req.error) Host_Crash("stdio open"); + + inbuf = OS_Make(inbuf_len); + inbuf[0] = 0; +} + + +/*********************************************************************** +** +*/ REBYTE *Get_Str() +/* +** Get input of a null terminated UTF-8 string. +** Divides the input into lines. +** Buffers multiple lines if needed. +** Returns NULL on end of stream. +** +***********************************************************************/ +{ + REBYTE *line; + + if ((line = Get_Next_Line())) return line; + + if (Fetch_Buf()) return Get_Next_Line(); + + return 0; +} + + +/*********************************************************************** +** +*/ void Put_Str(REBYTE *buf) +/* +** Outputs a null terminated UTF-8 string. +** If buf is larger than StdIO Device allows, error out. +** OS dependent line termination must be done prior to call. +** +***********************************************************************/ +{ + Std_IO_Req.length = strlen(buf); + Std_IO_Req.data = (REBYTE*)buf; + Std_IO_Req.actual = 0; + + OS_Do_Device(&Std_IO_Req, RDC_WRITE); + + if (Std_IO_Req.error) Host_Crash("stdio write"); +} diff --git a/src/os/win32/dev-clipboard.c b/src/os/win32/dev-clipboard.c new file mode 100644 index 0000000..b52751f --- /dev/null +++ b/src/os/win32/dev-clipboard.c @@ -0,0 +1,194 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Device: Clipboard access for Win32 +** Build: A95 +** Date: 27-Nov-2009 +** File: dev-clipboard.c +** Author: Carl Sassenrath +** Purpose: +** Provides a very simple interface to the clipboard for text. +** May be expanded in the future for images, etc. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include + +#include "reb-host.h" +#include "host-lib.h" +#include "sys-net.h" + + +/*********************************************************************** +** +*/ DEVICE_CMD Open_Clipboard(REBREQ *req) +/* +***********************************************************************/ +{ + SET_OPEN(req); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Close_Clipboard(REBREQ *req) +/* +***********************************************************************/ +{ + SET_CLOSED(req); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Read_Clipboard(REBREQ *req) +/* +***********************************************************************/ +{ + HANDLE data; + REBUNI *cp; + REBUNI *bin; + REBINT len; + + req->actual = 0; + + // If there is no clipboard data: + if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) { + req->error = 10; + return DR_ERROR; + } + + if (!OpenClipboard(NULL)) { + req->error = 20; + return DR_ERROR; + } + + // Read the UTF-8 data: + if ((data = GetClipboardData(CF_UNICODETEXT)) == NULL) { + CloseClipboard(); + req->error = 30; + return DR_ERROR; + } + + cp = GlobalLock(data); + if (!cp) { + GlobalUnlock(data); + CloseClipboard(); + req->error = 40; + return DR_ERROR; + } + + len = LEN_STR(cp); // wide chars + bin = OS_Make((len+1) * sizeof(REBCHR)); + COPY_STR(bin, cp, len); + + GlobalUnlock(data); + + CloseClipboard(); + + SET_FLAG(req->flags, RRF_WIDE); + req->data = (REBYTE *)bin; + req->actual = len * sizeof(REBCHR); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Write_Clipboard(REBREQ *req) +/* +** Works for Unicode and ASCII strings. +** Length is number of bytes passed (not number of chars). +** +***********************************************************************/ +{ + HANDLE data; + REBYTE *bin; + REBCNT err; + REBINT len = req->length; // in bytes + + req->actual = 0; + + data = GlobalAlloc(GHND, len + 4); + if (data == NULL) { + req->error = 5; + return DR_ERROR; + } + + // Lock and copy the string: + bin = GlobalLock(data); + if (bin == NULL) { + req->error = 10; + return DR_ERROR; + } + + COPY_MEM(bin, req->data, len); + bin[len] = 0; + GlobalUnlock(data); + + if (!OpenClipboard(NULL)) { + req->error = 20; + return DR_ERROR; + } + + EmptyClipboard(); + + err = !SetClipboardData(GET_FLAG(req->flags, RRF_WIDE) ? CF_UNICODETEXT : CF_TEXT, data); + + CloseClipboard(); + + if (err) { + req->error = 50; + return DR_ERROR; + } + + req->actual = len; + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Poll_Clipboard(REBREQ *req) +/* +***********************************************************************/ +{ + return DR_DONE; +} + + +/*********************************************************************** +** +** Command Dispatch Table (RDC_ enum order) +** +***********************************************************************/ + +static DEV_CMD Dev_Cmds[RDC_MAX] = +{ + 0, + 0, + Open_Clipboard, + Close_Clipboard, + Read_Clipboard, + Write_Clipboard, + Poll_Clipboard, +}; + +DEFINE_DEV(Dev_Clipboard, "Clipboard", 1, Dev_Cmds, RDC_MAX, 0); diff --git a/src/os/win32/dev-event.c b/src/os/win32/dev-event.c new file mode 100644 index 0000000..b582dd6 --- /dev/null +++ b/src/os/win32/dev-event.c @@ -0,0 +1,203 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Device: Event handler for Win32 +** Build: A95 +** Date: 27-Nov-2009 +** File: dev-event.c +** Author: Carl Sassenrath +** Purpose: +** Processes events to pass to REBOL. Note that events are +** used for more than just windowing. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include "reb-host.h" +#include "host-lib.h" + +void Done_Device(int handle, int error); + +// Move or remove globals? !? +HWND Event_Handle = 0; // Used for async DNS +static int Timer_Id = 0; // The timer we are using + +extern HINSTANCE App_Instance; // From Main module. + + +/*********************************************************************** +** +*/ LRESULT CALLBACK REBOL_Event_Proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +/* +** The minimal default event handler. +** +***********************************************************************/ +{ + switch(msg) { + case WM_CLOSE: + DestroyWindow(hwnd); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + // Default processing that we do not care about: + return DefWindowProc(hwnd, msg, wparam, lparam); + } + return 0; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Init_Events(REBREQ *dr) +/* +** Initialize the event device. +** +** Create a hidden window to handle special events, +** such as timers and async DNS. +** +***********************************************************************/ +{ + REBDEV *dev = (REBDEV*)dr; // just to keep compiler happy + WNDCLASSEX wc = {0}; + + // Register event object class: + wc.cbSize = sizeof(wc); + wc.lpszClassName = TEXT("REBOL-Events"); + wc.hInstance = App_Instance; + wc.lpfnWndProc = REBOL_Event_Proc; + if (!RegisterClassEx(&wc)) return DR_ERROR; + + // Create the hidden window: + Event_Handle = CreateWindowEx( + 0, + wc.lpszClassName, + wc.lpszClassName, + 0,0,0,0,0,0, + NULL, App_Instance, NULL + ); + + if (!Event_Handle) return DR_ERROR; + + SET_FLAG(dev->flags, RDF_INIT); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Poll_Events(REBREQ *req) +/* +** Poll for events and process them. +** Returns 1 if event found, else 0. +** +** MS Notes: +** +** "The PeekMessage function normally does not remove WM_PAINT +** messages from the queue. WM_PAINT messages remain in the queue +** until they are processed." +** +***********************************************************************/ +{ + MSG msg; + int flag = DR_DONE; + + // Are there messages to process? + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + flag = DR_PEND; + if (msg.message == WM_TIMER) + break; + if (msg.message == WM_DNS) + Done_Device(msg.wParam, msg.lParam>>16); // error code + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return flag; // different meaning compared to most commands +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Query_Events(REBREQ *req) +/* +** Wait for an event or a timeout sepecified by req->length. +** This is used by WAIT as the main timing method. +** +***********************************************************************/ +{ + MSG msg; + + // Set timer (we assume this is very fast): + Timer_Id = SetTimer(0, Timer_Id, req->length, 0); + + // Wait for message or the timer: + if (GetMessage(&msg, NULL, 0, 0)) { + //printf("Msg: %d\n", msg.message); + if (msg.message == WM_DNS) + Done_Device(msg.wParam, msg.lParam>>16); // error code + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + // Quickly check for other events: + Poll_Events(0); + + //if (Timer_Id) KillTimer(0, Timer_Id); + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Connect_Events(REBREQ *req) +/* +** Simply keeps the request pending for polling purposes. +** Use Abort_Device to remove it. +** +***********************************************************************/ +{ + return DR_PEND; // keep pending +} + + +/*********************************************************************** +** +** Command Dispatch Table (RDC_ enum order) +** +***********************************************************************/ + +static DEV_CMD Dev_Cmds[RDC_MAX] = { + Init_Events, // init device driver resources + 0, // RDC_QUIT, // cleanup device driver resources + 0, // RDC_OPEN, // open device unit (port) + 0, // RDC_CLOSE, // close device unit + 0, // RDC_READ, // read from unit + 0, // RDC_WRITE, // write to unit + Poll_Events, + Connect_Events, + Query_Events, +}; + +DEFINE_DEV(Dev_Event, "OS Events", 1, Dev_Cmds, RDC_MAX, 0); diff --git a/src/os/win32/dev-file.c b/src/os/win32/dev-file.c new file mode 100644 index 0000000..9fa2270 --- /dev/null +++ b/src/os/win32/dev-file.c @@ -0,0 +1,462 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Device: File access for Win32 +** Build: A95 +** Date: 27-Nov-2009 +** File: dev-file.c +** Author: Carl Sassenrath +** Purpose: File open, close, read, write, and other actions. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include +#include + +#include "reb-host.h" +#include "host-lib.h" + +// MSDN V6 missed this define: +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + + +/*********************************************************************** +** +** Local Functions +** +***********************************************************************/ + +static BOOL Seek_File_64(REBREQ *file) +{ + // Performs seek and updates index value. TRUE on scuccess. + // On error, returns FALSE and sets file->error field. + HANDLE h = (HANDLE)file->handle; + DWORD result; + DWORD highint; + + if (file->file.index == -1) { + // Append: + highint = 0; + result = SetFilePointer(h, 0, &highint, FILE_END); + } + else { + // Line below updates indexh if it is affected: + highint = (long)(file->file.index >> 32); + result = SetFilePointer(h, (long)(file->file.index), &highint, FILE_BEGIN); + } + + if (result == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { + file->error = -RFE_NO_SEEK; + return 0; + } + + file->file.index = ((i64)highint << 32) + result; + + return 1; +} + + +/*********************************************************************** +** +*/ static int Read_Directory(REBREQ *dir, REBREQ *file) +/* +** This function will read a file directory, one file entry +** at a time, then close when no more files are found. +** +** Procedure: +** +** This function is passed directory and file arguments. +** The dir arg provides information about the directory to read. +** The file arg is used to return specific file information. +** +** To begin, this function is called with a dir->handle that +** is set to zero and a dir->file.path string for the directory. +** +** The directory is opened and a handle is stored in the dir +** structure for use on subsequent calls. If an error occurred, +** dir->error is set to the error code and -1 is returned. +** The dir->size field can be set to the number of files in the +** dir, if it is known. The dir->file.index field can be used by this +** function to store information between calls. +** +** If the open succeeded, then information about the first file +** is stored in the file argument and the function returns 0. +** On an error, the dir->error is set, the dir is closed, +** dir->handle is nulled, and -1 is returned. +** +** The caller loops until all files have been obtained. This +** action should be uninterrupted. (The caller should not perform +** additional OS or IO operations between calls.) +** +** When no more files are found, the dir is closed, dir->handle +** is nulled, and 1 is returned. No file info is returned. +** (That is, this function is called one extra time. This helps +** for OSes that may deallocate file strings on dir close.) +** +** Note that the dir->file.path can contain wildcards * and ?. The +** processing of these can be done in the OS (if supported) or +** by a separate filter operation during the read. +** +** Store file date info in file->file.index or other fields? +** Store permissions? Ownership? Groups? Or, require that +** to be part of a separate request? +** +***********************************************************************/ +{ + WIN32_FIND_DATA info; + HANDLE h= (HANDLE)(dir->handle); + REBCHR *cp = 0; + + if (!h) { + + // Read first file entry: + h = FindFirstFile(dir->file.path, &info); + if (h == INVALID_HANDLE_VALUE) { + dir->error = -RFE_OPEN_FAIL; + return DR_ERROR; + } + dir->handle = h; + CLR_FLAG(dir->flags, RRF_DONE); + cp = info.cFileName; + + } + + // Skip over the . and .. dir cases: + while (cp == 0 || (cp[0] == '.' && (cp[1] == 0 || cp[1] == '.'))) { + + // Read next file entry, or error: + if (!FindNextFile(h, &info)) { + dir->error = GetLastError(); + FindClose(h); + dir->handle = 0; + if (dir->error != ERROR_NO_MORE_FILES) return DR_ERROR; + dir->error = 0; + SET_FLAG(dir->flags, RRF_DONE); // no more files + return DR_DONE; + } + cp = info.cFileName; + + } + + file->modes = 0; + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) SET_FLAG(file->modes, RFM_DIR); + COPY_STR(file->file.path, info.cFileName, MAX_FILE_NAME); + file->file.size = ((i64)info.nFileSizeHigh << 32) + info.nFileSizeLow; + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Open_File(REBREQ *file) +/* +** Open the specified file with the given modes. +** +** Notes: +** 1. The file path is provided in REBOL format, and must be +** converted to local format before it is used. +** 2. REBOL performs the required access security check before +** calling this function. +** 3. REBOL clears necessary fields of file structure before +** calling (e.g. error and size fields). +** +** !! Confirm that /seek /append works properly. +** +***********************************************************************/ +{ + DWORD attrib = FILE_ATTRIBUTE_NORMAL; + DWORD access = 0; + DWORD create = 0; + HANDLE h; + BY_HANDLE_FILE_INFORMATION info; + + // Set the access, creation, and attribute for file creation: + if (GET_FLAG(file->modes, RFM_READ)) { + access |= GENERIC_READ; + create = OPEN_EXISTING; + } + + if (GET_FLAGS(file->modes, RFM_WRITE, RFM_APPEND)) { + access |= GENERIC_WRITE; + if ( + GET_FLAG(file->modes, RFM_NEW) || + !( + GET_FLAG(file->modes, RFM_READ) || + GET_FLAG(file->modes, RFM_APPEND) || + GET_FLAG(file->modes, RFM_SEEK) + ) + ) create = CREATE_ALWAYS; + else create = OPEN_ALWAYS; + } + + attrib |= GET_FLAG(file->modes, RFM_SEEK) ? FILE_FLAG_RANDOM_ACCESS : FILE_FLAG_SEQUENTIAL_SCAN; + + if (GET_FLAG(file->modes, RFM_READONLY)) + attrib |= FILE_ATTRIBUTE_READONLY; + + if (!access) { + file->error = -RFE_NO_MODES; + goto fail; + } + + // Open the file (yes, this is how windows does it, the nutty kids): + h = CreateFile(file->file.path, access, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, create, attrib, 0); + if (h == INVALID_HANDLE_VALUE) { + file->error = -RFE_OPEN_FAIL; + goto fail; + } + + // Confirm that a seek-mode file is actually seekable: + if (GET_FLAG(file->modes, RFM_SEEK)) { + // Below should work because we are seeking to 0: + if (SetFilePointer(h, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + CloseHandle(h); + file->error = -RFE_BAD_SEEK; + goto fail; + } + } + + // Fetch file size (if fails, then size is assumed zero): + if (GetFileInformationByHandle(h, &info)) { + file->file.size = ((i64)(info.nFileSizeHigh) << 32) + info.nFileSizeLow; + file->file.time.l = info.ftLastWriteTime.dwLowDateTime; + file->file.time.h = info.ftLastWriteTime.dwHighDateTime; + } + + file->handle = (void *)h; + + return DR_DONE; + +fail: + return DR_ERROR; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Close_File(REBREQ *file) +/* +** Closes a previously opened file. +** +***********************************************************************/ +{ + if (file->handle) { + CloseHandle((HANDLE)(file->handle)); + file->handle = 0; + } + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Read_File(REBREQ *file) +/* +***********************************************************************/ +{ + if (GET_FLAG(file->modes, RFM_DIR)) { + return Read_Directory(file, (REBREQ*)file->data); + } + + if (!file->handle) { + file->error = -RFE_NO_HANDLE; + return DR_ERROR; + } + + if (file->modes & ((1 << RFM_SEEK) | (1 << RFM_RESEEK))) { + CLR_FLAG(file->modes, RFM_RESEEK); + if (!Seek_File_64(file)) return DR_ERROR; + } + + if (!ReadFile(file->handle, file->data, file->length, &file->actual, 0)) { + file->error = -RFE_BAD_READ; + return DR_ERROR; + } else { + file->file.index += file->actual; + } + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Write_File(REBREQ *file) +/* +** Bug?: update file->size value after write !? +** +***********************************************************************/ +{ + DWORD result; + DWORD size_high, size_low; + + if (!file->handle) { + file->error = -RFE_NO_HANDLE; + return DR_ERROR; + } + + if (GET_FLAG(file->modes, RFM_APPEND)) { + CLR_FLAG(file->modes, RFM_APPEND); + SetFilePointer(file->handle, 0, 0, FILE_END); + } + + if (file->modes & ((1 << RFM_SEEK) | (1 << RFM_RESEEK) | (1 << RFM_TRUNCATE))) { + CLR_FLAG(file->modes, RFM_RESEEK); + if (!Seek_File_64(file)) return DR_ERROR; + if (GET_FLAG(file->modes, RFM_TRUNCATE)) + SetEndOfFile(file->handle); + } + + if (file->length != 0) { + if (!WriteFile(file->handle, file->data, file->length, &file->actual, 0)) { + result = GetLastError(); + if (result == ERROR_HANDLE_DISK_FULL) file->error = -RFE_DISK_FULL; + else file->error = -RFE_BAD_WRITE; + return DR_ERROR; + } + } + + size_low = GetFileSize(file->handle, &size_high); + if (size_low == 0xffffffff) { + result = GetLastError(); + file->error = -RFE_BAD_WRITE; + return DR_ERROR; + } + + file->file.size = ((i64)size_high << 32) + (i64)size_low; + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Query_File(REBREQ *file) +/* +** Obtain information about a file. Return TRUE on success. +** On error, return FALSE and set file->error code. +** +** Note: time is in local format and must be converted +** +***********************************************************************/ +{ + WIN32_FILE_ATTRIBUTE_DATA info; + + if (!GetFileAttributesEx(file->file.path, GetFileExInfoStandard, &info)) { + file->error = GetLastError(); + return DR_ERROR; + } + + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) SET_FLAG(file->modes, RFM_DIR); + else CLR_FLAG(file->modes, RFM_DIR); + file->file.size = ((i64)info.nFileSizeHigh << 32) + (i64)info.nFileSizeLow; + file->file.time.l = info.ftLastWriteTime.dwLowDateTime; + file->file.time.h = info.ftLastWriteTime.dwHighDateTime; + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Create_File(REBREQ *file) +/* +***********************************************************************/ +{ + if (GET_FLAG(file->modes, RFM_DIR)) { + if (CreateDirectory(file->file.path, 0)) return DR_DONE; + file->error = GetLastError(); + return DR_ERROR; + } else + return Open_File(file); +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Delete_File(REBREQ *file) +/* +** Delete a file or directory. Return TRUE if it was done. +** The file->file.path provides the directory path and name. +** For errors, return FALSE and set file->error to error code. +** +** Note: Dirs must be empty to succeed +** +***********************************************************************/ +{ + if (GET_FLAG(file->modes, RFM_DIR)) { + if (RemoveDirectory(file->file.path)) return DR_DONE; + } else + if (DeleteFile(file->file.path)) return DR_DONE; + + file->error = GetLastError(); + return DR_ERROR; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Rename_File(REBREQ *file) +/* +** Rename a file or directory. +** Note: cannot rename across file volumes. +** +***********************************************************************/ +{ + if (MoveFile((REBCHR*)(file->file.path), (REBCHR*)(file->data))) return DR_DONE; + file->error = GetLastError(); + return DR_ERROR; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Poll_File(REBREQ *file) +/* +***********************************************************************/ +{ + return DR_DONE; // files are synchronous (currently) +} + + +/*********************************************************************** +** +** Command Dispatch Table (RDC_ enum order) +** +***********************************************************************/ + +static DEV_CMD Dev_Cmds[RDC_MAX] = { + 0, + 0, + Open_File, + Close_File, + Read_File, + Write_File, + Poll_File, + 0, // connect + Query_File, + 0, // modify + Create_File, + Delete_File, + Rename_File, +}; + +DEFINE_DEV(Dev_File, "File IO", 1, Dev_Cmds, RDC_MAX, sizeof(REBREQ)); diff --git a/src/os/win32/dev-stdio.c b/src/os/win32/dev-stdio.c new file mode 100644 index 0000000..fae6f37 --- /dev/null +++ b/src/os/win32/dev-stdio.c @@ -0,0 +1,373 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: Device: Standard I/O for Win32 +** Build: A95 +** Date: 27-Nov-2009 +** File: dev-stdio.c +** Author: Carl Sassenrath +** Purpose: +** Provides basic I/O streams support for redirection and +** opening a console window if necessary. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include +#include + +#include +#include + +#include "reb-host.h" +#include "host-lib.h" + +#define BUF_SIZE (16*1024) // MS restrictions apply + +#define SF_DEV_NULL 31 // local flag to mark NULL device + +static HANDLE Std_Out = 0; +static HANDLE Std_Inp = 0; +static HANDLE Std_Echo = 0; +static REBCHR *Std_Buf = 0; // for input and output + +static BOOL Redir_Out = 0; +static BOOL Redir_Inp = 0; + +// Special access: +extern REBDEV *Devices[]; +extern REBOL_API void Reb_Escape(int level); + +//********************************************************************** + +BOOL WINAPI Handle_Break(DWORD dwCtrlType) +{ + // Handle the MS CMD console CTRL-C, BREAK, and other events: + if (dwCtrlType >= CTRL_CLOSE_EVENT) OS_Exit(100); // close button, shutdown, etc. + Reb_Escape(0); + return TRUE; // We handled it +} + +#ifdef DEBUG_METHOD +// Because this file deals with stdio, we must avoid using stdio for debug. +// This funtion is of use wne needed. +static dbgout(char *fmt, int d, char *s) +{ + char buf[255]; + FILE *f = fopen("dbgout.txt", "w"); + sprintf(buf, fmt, d, s); + fwrite(buf, strlen(buf), 1, f); + fclose(f); +} +// example: dbgout("handle: %x %s\n", hdl, name); +#endif + +#ifdef NOT_USED +static void attach_console(void) { + void *h = LoadLibraryW(TEXT("kernel32.dll")); + (BOOL (_stdcall *)(DWORD))GetProcAddress(h, "AttachConsole")(-1); + FreeLibrary(h); +} +#endif + + +/*********************************************************************** +** +*/ DEVICE_CMD Quit_IO(REBREQ *dr) +/* +***********************************************************************/ +{ + REBDEV *dev = (REBDEV*)dr; // just to keep compiler happy above + + //if (GET_FLAG(dev->flags, RDF_OPEN)) FreeConsole(); + CLR_FLAG(dev->flags, RDF_OPEN); + return DR_DONE; +} + +/*********************************************************************** +** +*/ DEVICE_CMD Open_IO(REBREQ *req) +/* +***********************************************************************/ +{ + REBDEV *dev; + REBCHR *title = TEXT("REBOL 3 Alpha"); + HANDLE win; + + dev = Devices[req->device]; + + // Avoid opening the console twice (compare dev and req flags): + if (GET_FLAG(dev->flags, RDF_OPEN)) { + // Device was opened earlier as null, so req must have that flag: + if (GET_FLAG(dev->flags, SF_DEV_NULL)) + SET_FLAG(req->modes, RDM_NULL); + SET_FLAG(req->flags, RRF_OPEN); + return DR_DONE; // Do not do it again + } + + if (!GET_FLAG(req->modes, RDM_NULL)) { + + // Get the raw stdio handles: + Std_Out = GetStdHandle(STD_OUTPUT_HANDLE); + Std_Inp = GetStdHandle(STD_INPUT_HANDLE); + //Std_Err = GetStdHandle(STD_ERROR_HANDLE); + Std_Echo = 0; + + Redir_Out = (GetFileType(Std_Out) != 0); + Redir_Inp = (GetFileType(Std_Inp) != 0); + + // attach_console(); // merges streams, not good + + // If output not redirected, open a console: + if (!Redir_Out) { + if (!AllocConsole()) { + req->error = GetLastError(); + return DR_ERROR; + } + + SetConsoleTitle(title); + + // The goof-balls at MS seem to require this: + // See: http://support.microsoft.com/kb/124103 + Sleep(40); + win = FindWindow(NULL, title); // What if more than one open ?! + if (win) { + SetForegroundWindow(win); + BringWindowToTop(win); + } + + // Get the new stdio handles: + Std_Out = GetStdHandle(STD_OUTPUT_HANDLE); + + if (!Redir_Inp) Std_Inp = GetStdHandle(STD_INPUT_HANDLE); + } + + Std_Buf = OS_Make(BUF_SIZE * sizeof(REBCHR)); + + // Handle stdio CTRL-C interrupt: + SetConsoleCtrlHandler(Handle_Break, TRUE); + } + else + SET_FLAG(dev->flags, SF_DEV_NULL); + + SET_FLAG(req->flags, RRF_OPEN); + SET_FLAG(dev->flags, RDF_OPEN); + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Close_IO(REBREQ *req) +/* + ***********************************************************************/ +{ + REBDEV *dev = Devices[req->device]; + + if (GET_FLAG(dev->flags, RDF_OPEN)) { + OS_Free(Std_Buf); + Std_Buf = 0; + //FreeConsole(); // problem: causes a delay + } + + if (Std_Echo) { + CloseHandle(Std_Echo); + Std_Echo = 0; + } + + CLR_FLAG(req->flags, RRF_OPEN); + //CLR_FLAG(dev->flags, RDF_OPEN); + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Write_IO(REBREQ *req) +/* +** Low level "raw" standard output function. +** +** Allowed to restrict the write to a max OS buffer size. +** +** Returns the number of chars written. +** +***********************************************************************/ +{ + long len; + long total = 0; + BOOL ok = FALSE; + + if (GET_FLAG(req->modes, RDM_NULL)) { + req->actual = req->length; + return DR_DONE; + } + + if (Std_Out) { + + if (Redir_Out) { // Always UTF-8 + ok = WriteFile(Std_Out, req->data, req->length, &total, 0); + } + else { + // Convert UTF-8 buffer to Win32 wide-char format for console. + // Thankfully, MS provides something other than mbstowcs(); + // however, if our buffer overflows, it's an error. There's no + // efficient way at this level to split-up the input data, + // because its UTF-8 with variable char sizes. + len = MultiByteToWideChar(CP_UTF8, 0, req->data, req->length, Std_Buf, BUF_SIZE); + if (len > 0) // no error + ok = WriteConsoleW(Std_Out, Std_Buf, len, &total, 0); + } + + if (!ok) { + req->error = GetLastError(); + return DR_ERROR; + } + + req->actual = req->length; // do not use "total" (can be byte or wide) + + //if (GET_FLAG(req->flags, RRF_FLUSH)) { + // FLUSH(); + //} + } + + if (Std_Echo) { // always UTF-8 + WriteFile(Std_Echo, req->data, req->length, &total, 0); + //FlushFileBuffers(Std_Echo); + } + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Read_IO(REBREQ *req) +/* +** Low level "raw" standard input function. +** +** The request buffer must be long enough to hold result. +** +** Result is NOT terminated (the actual field has length.) +** +***********************************************************************/ +{ + long total = 0; + int len; + BOOL ok; + + if (GET_FLAG(req->modes, RDM_NULL)) { + req->data[0] = 0; + return DR_DONE; + } + + req->actual = 0; + + if (Std_Inp) { + + if (Redir_Inp) { // always UTF-8 + len = MIN(req->length, BUF_SIZE); + ok = ReadFile(Std_Inp, req->data, len, &total, 0); + } + else { + ok = ReadConsoleW(Std_Inp, Std_Buf, BUF_SIZE-1, &total, 0); + if (ok) { + total = WideCharToMultiByte(CP_UTF8, 0, Std_Buf, total, req->data, req->length, 0, 0); + if (!total) ok = FALSE; + } + } + + if (!ok) { + req->error = GetLastError(); + return DR_ERROR; + } + + req->actual = total; + } + + return DR_DONE; +} + + +/*********************************************************************** +** +*/ DEVICE_CMD Open_Echo(REBREQ *req) +/* +** Open a file for low-level console echo (output). +** +***********************************************************************/ +{ + if (Std_Echo) { + CloseHandle(Std_Echo); + Std_Echo = 0; + } + + if (req->file.path) { + Std_Echo = CreateFile(req->file.path, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0); + if (Std_Echo == INVALID_HANDLE_VALUE) { + Std_Echo = 0; + req->error = GetLastError(); + return DR_ERROR; + } + } + + return DR_DONE; +} + + +/*********************************************************************** +** +** Command Dispatch Table (RDC_ enum order) +** +***********************************************************************/ + +static DEV_CMD Dev_Cmds[RDC_MAX] = +{ + 0, // init + Quit_IO, + Open_IO, + Close_IO, + Read_IO, + Write_IO, + 0, // poll + 0, // connect + 0, // query + 0, // modify + Open_Echo, // CREATE used for opening echo file +}; + +DEFINE_DEV(Dev_StdIO, "Standard IO", 1, Dev_Cmds, RDC_MAX, 0); + + + +//*** Old fragments *************************************************** + +#if OLD_CONSOLE_FILE_IO + int cfh; // C file handle + FILE *file; + + cfh = _open_osfhandle((long)Std_Out, _O_TEXT); + file = _fdopen(cfh, "w"); + *stdout = *file; + setvbuf(stdout, NULL, _IONBF, 0); + + cfh = _open_osfhandle((long)Std_Inp, _O_TEXT); + file = _fdopen(cfh, "r"); + *stdin = *file; +#endif diff --git a/src/os/win32/host-lib.c b/src/os/win32/host-lib.c new file mode 100644 index 0000000..a9079c0 --- /dev/null +++ b/src/os/win32/host-lib.c @@ -0,0 +1,648 @@ +/*********************************************************************** +** +** REBOL 3.0 "Invasion" +** Copyright 2009 REBOL Technologies +** All rights reserved. +** +************************************************************************ +** +** Title: OS API function library called by REBOL interpreter +** Build: A95 +** Date: 27-Nov-2009 +** File: host-lib.c +** Author: Carl Sassenrath +** Purpose: +** This module provides the functions that REBOL calls +** to interface to the native (host) operating system. +** REBOL accesses these functions through the structure +** defined in host-lib.h (auto-generated, do not modify). +** +** Flags: compile with -DUNICODE for Win32 wide char API +** +** Special note: +** This module is parsed for function declarations used to +** build prototypes, tables, and other definitions. To change +** function arguments requires a rebuild of the REBOL library. +** +************************************************************************ +** +** NOTE to PROGRAMMERS: +** +** 1. Keep code clear and simple. +** 2. Document unusual code, reasoning, or gotchas. +** 3. Use same style for code, vars, indent(4), comments, etc. +** 4. Keep in mind Linux, OS X, BSD, big/little endian CPUs. +** 5. Test everything, then test it again. +** +***********************************************************************/ + +#include +#include +#include + +#include "reb-host.h" +#include "host-lib.h" + +// Semaphore lock to sync sub-task launch: +static void *Task_Ready; + + +/*********************************************************************** +** +*/ void Convert_Date(SYSTEMTIME *stime, REBOL_DAT *dat, long zone) +/* +** Convert local format of system time into standard date +** and time structure. +** +***********************************************************************/ +{ + dat->year = stime->wYear; + dat->month = stime->wMonth; + dat->day = stime->wDay; + dat->time = stime->wHour * 3600 + stime->wMinute * 60 + stime->wSecond; + dat->nano = 1000000 * stime->wMilliseconds; + dat->zone = zone; +} + +/*********************************************************************** +** +*/ static void Insert_Command_Arg(REBCHR *cmd, REBCHR *arg, REBINT limit) +/* +** Insert an argument into a command line at the %1 position, +** or at the end if there is no %1. (An INSERT action.) +** Do not exceed the specified limit length. +** +** Too bad std Clib does not provide INSERT or REPLACE functions. +** +***********************************************************************/ +{ + #define HOLD_SIZE 2000 + REBCHR *spot; + REBCHR hold[HOLD_SIZE+4]; + + if ((REBINT)LEN_STR(cmd) >= limit) return; // invalid case, ignore it. + + // Find %1: + spot = FIND_STR(cmd, TEXT("%1")); + + if (spot) { + // Save rest of cmd line (such as end quote, -flags, etc.) + COPY_STR(hold, spot+2, HOLD_SIZE); + + // Terminate at the arg location: + spot[0] = 0; + + // Insert the arg: + JOIN_STR(spot, arg, limit - LEN_STR(cmd) - 1); + + // Add back the rest of cmd: + JOIN_STR(spot, hold, limit - LEN_STR(cmd) - 1); + } + else { + JOIN_STR(cmd, TEXT(" "), 1); + JOIN_STR(cmd, arg, limit - LEN_STR(cmd) - 1); + } +} + + +/*********************************************************************** +** +** OS Library Functions +** +***********************************************************************/ + +/*********************************************************************** +** +*/ void *OS_Make(size_t size) +/* +** Allocate memory of given size. +** +** This is necessary because some environments may use their +** own specific memory allocation (e.g. private heaps). +** +***********************************************************************/ +{ + return malloc(size); +} + + +/*********************************************************************** +** +*/ void OS_Free(void *mem) +/* +** Free memory allocated in this OS environment. (See OS_Make) +** +***********************************************************************/ +{ + free(mem); +} + + +/*********************************************************************** +** +*/ void OS_Exit(int code) +/* +** Called in cases where REBOL needs to quit immediately +** without returning from the main() function. +** +***********************************************************************/ +{ + OS_Call_Device(RDI_STDIO, RDC_CLOSE); // close echo + exit(code); +} + + +/*********************************************************************** +** +*/ void OS_Crash(const REBYTE *title, const REBYTE *content) +/* +** Tell user that REBOL has crashed. This function must use +** the most obvious and reliable method of displaying the +** crash message. +** +** If the title is NULL, then REBOL is running in a server mode. +** In that case, we do not want the crash message to appear on +** the screen, because the system may be unattended. +** +** On some systems, the error may be recorded in the system log. +** +***********************************************************************/ +{ + // Echo crash message if echo file is open: + ///PUTE(content); + OS_Call_Device(RDI_STDIO, RDC_CLOSE); // close echo + + // A title tells us we should alert the user: + if (title) { + // OS_Put_Str(title); + // OS_Put_Str(":\n"); + // Use ASCII only (in case we are on non-unicode win32): + MessageBoxA(NULL, content, title, MB_ICONHAND); + } + // OS_Put_Str(content); + exit(100); +} + + +/*********************************************************************** +** +*/ REBCHR *OS_Form_Error(int errnum, REBCHR *str, int len) +/* +** Translate OS error into a string. The str is the string +** buffer and the len is the length of the buffer. +** +***********************************************************************/ +{ + LPVOID lpMsgBuf; + int ok; + + if (!errnum) errnum = GetLastError(); + + ok = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errnum, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + + len--; // termination + + if (!ok) COPY_STR(str, TEXT("unknown error"), len); + else { + COPY_STR(str, lpMsgBuf, len); + LocalFree(lpMsgBuf); + } + return str; +} + + +/*********************************************************************** +** +*/ BOOL OS_Get_Boot_Path(REBCHR *name) +/* +** Used to determine the program file path for REBOL. +** This is the path stored in system->options->boot and +** it is used for finding default boot files. +** +***********************************************************************/ +{ + return (GetModuleFileName(0, name, MAX_FILE_NAME) > 0); +} + + +/*********************************************************************** +** +*/ REBCHR *OS_Get_Locale(int what) +/* +** Used to obtain locale information from the system. +** The returned value must be freed with OS_FREE_MEM. +** +***********************************************************************/ +{ + LCTYPE type; + int len; + REBCHR *data; + LCTYPE types[] = { + LOCALE_SENGLANGUAGE, + LOCALE_SNATIVELANGNAME, + LOCALE_SENGCOUNTRY, + LOCALE_SCOUNTRY, + }; + + type = types[what]; + + len = GetLocaleInfo(0, type, 0, 0); + data = MAKE_STR(len); + len = GetLocaleInfo(0, type, data, len); + + return data; +} + + +/*********************************************************************** +** +*/ REBCHR *OS_Get_Env(REBCHR *var, int mode) +/* +** Get a value from the environment. +** Returns string for success or zero if missing. +** Return string should be copied not stored or changed. +** +***********************************************************************/ +{ +#ifdef UNICODE + return _wgetenv(var); +#else + return getenv(var); +#endif +} + + +/*********************************************************************** +** +*/ int OS_Set_Env(REBCHR *expr, int mode) +/* +** Set a value from the environment. +** Returns 0 for success and <0 for errors. +** +***********************************************************************/ +{ +#ifdef UNICODE + return _wputenv(expr); +#else + return putenv(expr); +#endif +} + + +/*********************************************************************** +** +*/ REBCHR *OS_List_Env(void) +/* +***********************************************************************/ +{ + REBCHR *env = GetEnvironmentStrings(); + REBCNT n, len = 0; + REBCHR *str; + + str = env; + while (n = LEN_STR(str)) { + len += n + 1; + str = env + len; // next + } + len++; + + str = OS_Make(len * sizeof(REBCHR)); + MOVE_MEM(str, env, len * sizeof(REBCHR)); + + FreeEnvironmentStrings(env); + + return str; +} + + +/*********************************************************************** +** +*/ void OS_Get_Time(REBOL_DAT *dat) +/* +** Get the current system date/time in UTC plus zone offset (mins). +** +***********************************************************************/ +{ + SYSTEMTIME stime; + TIME_ZONE_INFORMATION tzone; + + GetSystemTime(&stime); + + if (TIME_ZONE_ID_DAYLIGHT == GetTimeZoneInformation(&tzone)) + tzone.Bias += tzone.DaylightBias; + + Convert_Date(&stime, dat, -tzone.Bias); +} + + +/*********************************************************************** +** +*/ i64 OS_Delta_Time(i64 base, int flags) +/* +** Return time difference in microseconds. If base = 0, then +** return the counter. If base != 0, compute the time difference. +** +** Note: Requires high performance timer. +** Q: If not found, use timeGetTime() instead ?! +** +***********************************************************************/ +{ + LARGE_INTEGER freq; + LARGE_INTEGER time; + + if (!QueryPerformanceCounter(&time)) + OS_Crash("Missing resource", "High performance timer"); + + if (base == 0) return time.QuadPart; // counter (may not be time) + + QueryPerformanceFrequency(&freq); + + return ((time.QuadPart - base) * 1000) / (freq.QuadPart / 1000); +} + + +/*********************************************************************** +** +*/ int OS_Get_Current_Dir(REBCHR **path) +/* +** Return the current directory path as a string and +** its length in chars (not bytes). +** +** The result should be freed after copy/conversion. +** +***********************************************************************/ +{ + int len; + + len = GetCurrentDirectory(0, NULL); // length, incl terminator. + *path = MAKE_STR(len); + GetCurrentDirectory(len, *path); + len--; // less terminator + + return len; // Be sure to call free() after usage +} + + +/*********************************************************************** +** +*/ BOOL OS_Set_Current_Dir(REBCHR *path) +/* +** Set the current directory to local path. Return FALSE +** on failure. +** +***********************************************************************/ +{ + return SetCurrentDirectory(path); +} + + +/*********************************************************************** +** +*/ void OS_File_Time(REBREQ *file, REBOL_DAT *dat) +/* +** Convert file.time to REBOL date/time format. +** Time zone is UTC. +** +***********************************************************************/ +{ + SYSTEMTIME stime; + TIME_ZONE_INFORMATION tzone; + + if (TIME_ZONE_ID_DAYLIGHT == GetTimeZoneInformation(&tzone)) + tzone.Bias += tzone.DaylightBias; + + FileTimeToSystemTime((FILETIME *)(&(file->file.time)), &stime); + Convert_Date(&stime, dat, -tzone.Bias); +} + + +/*********************************************************************** +** +*/ void *OS_Open_Library(REBCHR *path, REBCNT *error) +/* +** Load a DLL library and return the handle to it. +** If zero is returned, error indicates the reason. +** +***********************************************************************/ +{ + void *dll = LoadLibraryW(path); + *error = GetLastError(); + + return dll; +} + + +/*********************************************************************** +** +*/ void OS_Close_Library(void *dll) +/* +** Free a DLL library opened earlier. +** +***********************************************************************/ +{ + FreeLibrary((HINSTANCE)dll); +} + + +/*********************************************************************** +** +*/ void *OS_Find_Function(void *dll, char* funcname) +/* +** Get a DLL function address from its string name. +** +***********************************************************************/ +{ + void *fp = GetProcAddress((HMODULE)dll, funcname); + //DWORD err = GetLastError(); + + return fp; +} + + +/*********************************************************************** +** +*/ REBINT OS_Create_Thread(CFUNC init, void *arg, REBCNT stack_size) +/* +** Creates a new thread for a REBOL task datatype. +** +** NOTE: +** For this to work, the multithreaded library option is +** needed in the C/C++ code generation settings. +** +** The Task_Ready stops return until the new task has been +** initialized (to avoid unknown new thread state). +** +***********************************************************************/ +{ + REBINT thread; + + Task_Ready = CreateEvent(NULL, TRUE, FALSE, TEXT("REBOL_Task_Launch")); + if (!Task_Ready) return -1; + + thread = _beginthread(init, stack_size, arg); + + if (thread) WaitForSingleObject(Task_Ready, 2000); + CloseHandle(Task_Ready); + + return 1; +} + + +/*********************************************************************** +** +*/ void OS_Delete_Thread(void) +/* +** Can be called by a REBOL task to terminate its thread. +** +***********************************************************************/ +{ + _endthread(); +} + + +/*********************************************************************** +** +*/ void OS_Task_Ready(REBINT tid) +/* +** Used for new task startup to resume the thread that +** launched the new task. +** +***********************************************************************/ +{ + SetEvent(Task_Ready); +} + + +/*********************************************************************** +** +*/ int OS_Create_Process(REBCHR *call, int reserved) +/* +** Return zero on error. +** +***********************************************************************/ +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + REBOOL is_NT; + OSVERSIONINFO info; + REBINT result; + + GetVersionEx(&info); + is_NT = info.dwPlatformId >= VER_PLATFORM_WIN32_NT; + + si.cb = sizeof(si); + si.lpReserved = NULL; + si.lpDesktop = NULL; + si.lpTitle = NULL; + si.dwFlags = STARTF_USESHOWWINDOW; + si.dwFlags |= STARTF_USESTDHANDLES; + si.wShowWindow = SW_SHOWNORMAL; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + result = CreateProcess( + NULL, // Executable name + call, // Command to execute + NULL, // Process security attributes + NULL, // Thread security attributes + FALSE, // Inherit handles + CREATE_DEFAULT_ERROR_MODE, // Creation flags + NULL, // Environment + NULL, // Current directory + &si, // Startup information + &pi // Process information + ); + + return result; +} + + +/*********************************************************************** +** +*/ int OS_Browse(REBCHR *url, int reserved) +/* +***********************************************************************/ +{ + #define MAX_BRW_PATH 2044 + long flag; + long len; + long type; + HKEY key; + REBCHR *path; + HWND hWnd = GetFocus(); + + if (RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("http\\shell\\open\\command"), 0, KEY_READ, &key) != ERROR_SUCCESS) + return 0; + + if (!url) url = TEXT(""); + + path = MAKE_STR(MAX_BRW_PATH+4); + len = MAX_BRW_PATH; + + flag = RegQueryValueEx(key, TEXT(""), 0, &type, (LPBYTE)path, &len); + RegCloseKey(key); + if (flag != ERROR_SUCCESS) { + FREE_MEM(path); + return 0; + } + //if (ExpandEnvironmentStrings(&str[0], result, len)) + + Insert_Command_Arg(path, url, MAX_BRW_PATH); + + len = OS_Create_Process(path, 0); + + FREE_MEM(path); + return len; +} + + +/*********************************************************************** +** +*/ BOOL OS_Request_File(REBRFR *fr) +/* +***********************************************************************/ +{ + OPENFILENAME ofn = {0}; + BOOL ret; + //int err; + REBCHR *filters = TEXT("All files\0*.*\0REBOL scripts\0*.r\0Text files\0*.txt\0" ); + + ofn.lStructSize = sizeof(ofn); + + // ofn.hwndOwner = WIN_WIN(win); // Must find a way to set this + + ofn.lpstrTitle = fr->title; + ofn.lpstrInitialDir = fr->dir; + ofn.lpstrFile = fr->files; + ofn.lpstrFilter = fr->filter ? fr->filter : filters; + ofn.nMaxFile = fr->len; + ofn.lpstrFileTitle = 0; + ofn.nMaxFileTitle = 0; + + ofn.Flags = OFN_HIDEREADONLY | OFN_EXPLORER | OFN_NOCHANGEDIR; //|OFN_NONETWORKBUTTON; //; + + if (GET_FLAG(fr->flags, FRF_MULTI)) ofn.Flags |= OFN_ALLOWMULTISELECT; + + if (GET_FLAG(fr->flags, FRF_SAVE)) + ret = GetSaveFileName(&ofn); + else + ret = GetOpenFileName(&ofn); + + //if (!ret) + // err = CommDlgExtendedError(); // CDERR_FINDRESFAILURE + + return ret; +}