From: Chris Hanson Date: Mon, 28 Nov 1994 03:43:02 +0000 (+0000) Subject: Initial revision X-Git-Tag: 20090517-FFI~6938 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=14c30bd8a3ee1752d313e0f1f95f2ebea82db70c;p=mit-scheme.git Initial revision --- diff --git a/v7/src/microcode/os2.c b/v7/src/microcode/os2.c new file mode 100644 index 000000000..c6ab6d8d0 --- /dev/null +++ b/v7/src/microcode/os2.c @@ -0,0 +1,199 @@ +/* -*-C-*- + +$Id: os2.c,v 1.1 1994/11/28 03:42:53 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" + +void * +OS_malloc (unsigned int size) +{ + void * result = (malloc (size)); + if (result == 0) + OS2_error_system_call (ERROR_NOT_ENOUGH_MEMORY, syscall_malloc); + return (result); +} + +void * +OS_realloc (void * ptr, unsigned int size) +{ + void * result = (realloc (ptr, size)); + if (result == 0) + OS2_error_system_call (ERROR_NOT_ENOUGH_MEMORY, syscall_realloc); + return (result); +} + +void +OS_free (void * ptr) +{ + free (ptr); +} + +HMTX +OS2_create_mutex_semaphore (void) +{ + HMTX result; + STD_API_CALL (dos_create_mutex_sem, (0, (&result), 0, 0)); + return (result); +} + +void +OS2_close_mutex_semaphore (HMTX s) +{ + STD_API_CALL (dos_close_mutex_sem, (s)); +} + +void +OS2_request_mutex_semaphore (HMTX s) +{ + STD_API_CALL (dos_request_mutex_sem, (s, SEM_INDEFINITE_WAIT)); +} + +void +OS2_release_mutex_semaphore (HMTX s) +{ + STD_API_CALL (dos_release_mutex_sem, (s)); +} + +HEV +OS2_create_event_semaphore (void) +{ + HEV result; + STD_API_CALL (dos_create_event_sem, (0, (&result), 0, 0)); + return (result); +} + +void +OS2_close_event_semaphore (HEV s) +{ + STD_API_CALL (dos_close_event_sem, (s)); +} + +int +OS2_post_event_semaphore (HEV s) +{ + XTD_API_CALL + (dos_post_event_sem, (s), + { + if (rc == ERROR_ALREADY_POSTED) + return (1); + }); + return (0); +} + +ULONG +OS2_reset_event_semaphore (HEV s) +{ + ULONG post_count; + XTD_API_CALL + (dos_reset_event_sem, (s, (&post_count)), + { + if (rc == ERROR_ALREADY_RESET) + return (0); + }); + return (post_count); +} + +int +OS2_wait_event_semaphore (HEV s, int blockp) +{ + XTD_API_CALL + (dos_wait_event_sem, + (s, (blockp ? SEM_INDEFINITE_WAIT : SEM_IMMEDIATE_RETURN)), + { + if ((rc == ERROR_TIMEOUT) && (!blockp)) + return (0); + }); + return (1); +} + +HQUEUE +OS2_create_queue (ULONG priority) +{ + static unsigned int n = 0; + char buffer [64]; + HQUEUE result; + sprintf (buffer, "\\queues\\scm%d\\%d.que", OS2_scheme_pid, (n++)); + STD_API_CALL (dos_create_queue, ((&result), priority, buffer)); + return (result); +} + +void +OS2_close_queue (HQUEUE q) +{ + STD_API_CALL (dos_close_queue, (q)); +} + +void +OS2_write_queue (HQUEUE q, ULONG type, ULONG length, PVOID data, ULONG priority) +{ + STD_API_CALL (dos_write_queue, (q, type, length, data, priority)); +} + +int +OS2_read_queue (HQUEUE q, ULONG * type, ULONG * length, PVOID * data, HEV s) +{ + REQUESTDATA request; + BYTE priority; + (request.pid) = OS2_scheme_pid; + if (s != NULLHANDLE) + (void) OS2_reset_event_semaphore (s); + XTD_API_CALL + (dos_read_queue, + (q, (&request), length, data, 0, + ((s == NULLHANDLE) ? DCWW_WAIT : DCWW_NOWAIT), (&priority), s), + { + if ((rc == ERROR_QUE_EMPTY) && (s != NULLHANDLE)) + return (0); + }); + (*type) = (request.ulData); + return (1); +} + +ULONG +OS2_system_variable (ULONG index) +{ + ULONG result; + STD_API_CALL + (dos_query_sys_info, (index, index, (&result), (sizeof (result)))); + return (result); +} + +void +OS2_logic_error_1 (const char * description, + const char * file, + unsigned int line) +{ + outf_fatal ("\nFatal error in file \"%s\", line %d:\n%s\nGet a wizard.\n", + description, file, line); + termination_init_error (); +} diff --git a/v7/src/microcode/os2.h b/v7/src/microcode/os2.h new file mode 100644 index 000000000..18b3efadc --- /dev/null +++ b/v7/src/microcode/os2.h @@ -0,0 +1,92 @@ +/* -*-C-*- + +$Id: os2.h,v 1.1 1994/11/28 03:42:53 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +/* OS/2 system include file */ + +#ifndef SCM_OS2_H +#define SCM_OS2_H + +#include "dstack.h" +#include "osscheme.h" +#include "syscall.h" + +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_KBD +#define INCL_VIO +#include +#include +#include +#include +#include +#include +#include + +#include "os2api.h" +#include "os2msg.h" +#include "os2io.h" +#include "os2thrd.h" +#include "os2ctty.h" +#include "os2cthrd.h" + +#define OS2_MAX_FILE_HANDLES() 20 + +#define FILE_ANY \ + (FILE_NORMAL | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED) + +extern HMTX OS2_create_mutex_semaphore (void); +extern void OS2_close_mutex_semaphore (HMTX); +extern void OS2_request_mutex_semaphore (HMTX); +extern void OS2_release_mutex_semaphore (HMTX); + +extern HEV OS2_create_event_semaphore (void); +extern void OS2_close_event_semaphore (HEV); +extern int OS2_post_event_semaphore (HEV); +extern ULONG OS2_reset_event_semaphore (HEV); +extern int OS2_wait_event_semaphore (HEV, int); + +extern HQUEUE OS2_create_queue (ULONG); +extern void OS2_close_queue (HQUEUE); +extern void OS2_write_queue (HQUEUE, ULONG, ULONG, PVOID, ULONG); +extern int OS2_read_queue (HQUEUE, ULONG *, ULONG *, PVOID *, HEV); + +extern ULONG OS2_system_variable (ULONG); + +/* Logic errors are fatal and can't be caught. These are errors that + should never happen, and if one does occur the program cannot + proceed. */ +#define OS2_logic_error(d) OS2_logic_error_1 ((d), __FILE__, __LINE__) +extern void OS2_logic_error_1 (const char *, const char *, unsigned int); + +#endif /* SCM_OS2_H */ diff --git a/v7/src/microcode/os2api.h b/v7/src/microcode/os2api.h new file mode 100644 index 000000000..4bb211392 --- /dev/null +++ b/v7/src/microcode/os2api.h @@ -0,0 +1,209 @@ +/* -*-C-*- + +$Id: os2api.h,v 1.1 1994/11/28 03:42:54 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#ifndef SCM_OS2API_H +#define SCM_OS2API_H + +#define XTD_API_CALL(proc, args, if_error) \ +{ \ + while (1) \ + { \ + APIRET rc = (proc args); \ + if (rc == NO_ERROR) \ + break; \ + if (rc != ERROR_INTERRUPT) \ + { \ + if_error; \ + OS2_error_system_call (rc, syscall_ ## proc); \ + } \ + } \ +} + +#define STD_API_CALL(proc, args) XTD_API_CALL (proc, args, {}) + +#ifdef CLOSED_API_CALLS + +extern APIRET dos_async_timer (ULONG, HSEM, PHTIMER); +extern APIRET dos_close (HFILE); +extern APIRET dos_close_event_sem (HEV); +extern APIRET dos_close_mutex_sem (HMTX); +extern APIRET dos_close_queue (HQUEUE); +extern APIRET dos_create_dir (PSZ, PEAOP2); +extern APIRET dos_create_event_sem (PSZ, PHEV, ULONG, BOOL32); +extern APIRET dos_create_mutex_sem (PSZ, PHMTX, ULONG, BOOL32); +extern APIRET dos_create_pipe (PHFILE, PHFILE, ULONG); +extern APIRET dos_create_queue (PHQUEUE, ULONG, PSZ); +extern APIRET dos_create_thread (PTID, PFNTHREAD, ULONG, ULONG, ULONG); +extern APIRET dos_delete (PSZ); +extern APIRET dos_delete_dir (PSZ); +extern void dos_exit (ULONG, ULONG); +extern APIRET dos_find_close (HDIR); +extern APIRET dos_find_first (PSZ, PHDIR, ULONG, PVOID, ULONG, PULONG, ULONG); +extern APIRET dos_find_next (HDIR, PVOID, ULONG, PULONG); +extern APIRET dos_get_info_blocks (PTIB *, PPIB *); +extern APIRET dos_get_message (PCHAR *, ULONG, PCHAR, ULONG, ULONG, PSZ, PULONG); +extern APIRET dos_kill_thread (TID); +extern APIRET dos_move (PSZ, PSZ); +extern APIRET dos_open (PSZ, PHFILE, PULONG, ULONG, ULONG, ULONG, ULONG, PEAOP2); +extern APIRET dos_post_event_sem (HEV); +extern APIRET dos_query_current_dir (ULONG, PBYTE, PULONG); +extern APIRET dos_query_current_disk (PULONG, PULONG); +extern APIRET dos_query_file_info (HFILE, ULONG, PVOID, ULONG); +extern APIRET dos_query_h_type (HFILE, PULONG, PULONG); +extern APIRET dos_query_n_p_h_state (HPIPE, PULONG); +extern APIRET dos_query_path_info (PSZ, ULONG, PVOID, ULONG); +extern APIRET dos_query_sys_info (ULONG, ULONG, PVOID, ULONG); +extern APIRET dos_read (HFILE, PVOID, ULONG, PULONG); +extern APIRET dos_read_queue (HQUEUE, PREQUESTDATA, PULONG, PPVOID, ULONG, BOOL32, PBYTE, HEV); +extern APIRET dos_release_mutex_sem (HMTX); +extern APIRET dos_request_mutex_sem (HMTX, ULONG); +extern APIRET dos_reset_event_sem (HEV, PULONG); +extern APIRET dos_scan_env (PSZ, PSZ *); +extern APIRET dos_set_current_dir (PSZ); +extern APIRET dos_set_default_disk (ULONG); +extern APIRET dos_set_file_ptr (HFILE, LONG, ULONG, PULONG); +extern APIRET dos_set_file_size (HFILE, ULONG); +extern APIRET dos_set_path_info (PSZ, ULONG, PVOID, ULONG, ULONG); +extern APIRET dos_start_timer (ULONG, HSEM, PHTIMER); +extern APIRET dos_stop_timer (PHTIMER); +extern APIRET dos_wait_event_sem (HEV, ULONG); +extern APIRET dos_write (HFILE, PVOID, ULONG, PULONG); +extern APIRET dos_write_queue (HQUEUE, ULONG, ULONG, PVOID, ULONG); +extern APIRET kbd_char_in (PKBDKEYINFO, USHORT, HKBD); +extern APIRET vio_wrt_tty (PCH, USHORT, HVIO); + +#else /* not CLOSED_API_CALLS */ + +#define dos_async_timer DosAsyncTimer +#define dos_close DosClose +#define dos_close_event_sem DosCloseEventSem +#define dos_close_mutex_sem DosCloseMutexSem +#define dos_close_queue DosCloseQueue +#define dos_create_dir DosCreateDir +#define dos_create_event_sem DosCreateEventSem +#define dos_create_mutex_sem DosCreateMutexSem +#define dos_create_pipe DosCreatePipe +#define dos_create_queue DosCreateQueue +#define dos_create_thread DosCreateThread +#define dos_delete DosDelete +#define dos_delete_dir DosDeleteDir +#define dos_exit DosExit +#define dos_find_close DosFindClose +#define dos_find_first DosFindFirst +#define dos_find_next DosFindNext +#define dos_get_info_blocks DosGetInfoBlocks +#define dos_get_message DosGetMessage +#define dos_kill_thread DosKillThread +#define dos_move DosMove +#define dos_open DosOpen +#define dos_post_event_sem DosPostEventSem +#define dos_query_current_dir DosQueryCurrentDir +#define dos_query_current_disk DosQueryCurrentDisk +#define dos_query_file_info DosQueryFileInfo +#define dos_query_h_type DosQueryHType +#define dos_query_n_p_h_state DosQueryNPHState +#define dos_query_path_info DosQueryPathInfo +#define dos_query_sys_info DosQuerySysInfo +#define dos_read DosRead +#define dos_read_queue DosReadQueue +#define dos_release_mutex_sem DosReleaseMutexSem +#define dos_request_mutex_sem DosRequestMutexSem +#define dos_reset_event_sem DosResetEventSem +#define dos_scan_env DosScanEnv +#define dos_set_current_dir DosSetCurrentDir +#define dos_set_default_disk DosSetDefaultDisk +#define dos_set_file_ptr DosSetFilePtr +#define dos_set_file_size DosSetFileSize +#define dos_set_path_info DosSetPathInfo +#define dos_start_timer DosStartTimer +#define dos_stop_timer DosStopTimer +#define dos_wait_event_sem DosWaitEventSem +#define dos_write DosWrite +#define dos_write_queue DosWriteQueue +#define kbd_char_in KbdCharIn +#define vio_wrt_tty VioWrtTTY + +#define syscall_dos_async_timer syscall_DosAsyncTimer +#define syscall_dos_close syscall_DosClose +#define syscall_dos_close_event_sem syscall_DosCloseEventSem +#define syscall_dos_close_mutex_sem syscall_DosCloseMutexSem +#define syscall_dos_close_queue syscall_DosCloseQueue +#define syscall_dos_create_dir syscall_DosCreateDir +#define syscall_dos_create_event_sem syscall_DosCreateEventSem +#define syscall_dos_create_mutex_sem syscall_DosCreateMutexSem +#define syscall_dos_create_pipe syscall_DosCreatePipe +#define syscall_dos_create_queue syscall_DosCreateQueue +#define syscall_dos_create_thread syscall_DosCreateThread +#define syscall_dos_delete syscall_DosDelete +#define syscall_dos_delete_dir syscall_DosDeleteDir +#define syscall_dos_exit syscall_DosExit +#define syscall_dos_find_close syscall_DosFindClose +#define syscall_dos_find_first syscall_DosFindFirst +#define syscall_dos_find_next syscall_DosFindNext +#define syscall_dos_get_info_blocks syscall_DosGetInfoBlocks +#define syscall_dos_get_message syscall_DosGetMessage +#define syscall_dos_kill_thread syscall_DosKillThread +#define syscall_dos_move syscall_DosMove +#define syscall_dos_open syscall_DosOpen +#define syscall_dos_post_event_sem syscall_DosPostEventSem +#define syscall_dos_query_current_dir syscall_DosQueryCurrentDir +#define syscall_dos_query_current_disk syscall_DosQueryCurrentDisk +#define syscall_dos_query_file_info syscall_DosQueryFileInfo +#define syscall_dos_query_h_type syscall_DosQueryHType +#define syscall_dos_query_n_p_h_state syscall_DosQueryNPHState +#define syscall_dos_query_path_info syscall_DosQueryPathInfo +#define syscall_dos_query_sys_info syscall_DosQuerySysInfo +#define syscall_dos_read syscall_DosRead +#define syscall_dos_read_queue syscall_DosReadQueue +#define syscall_dos_release_mutex_sem syscall_DosReleaseMutexSem +#define syscall_dos_request_mutex_sem syscall_DosRequestMutexSem +#define syscall_dos_reset_event_sem syscall_DosResetEventSem +#define syscall_dos_scan_env syscall_DosScanEnv +#define syscall_dos_set_current_dir syscall_DosSetCurrentDir +#define syscall_dos_set_default_disk syscall_DosSetDefaultDisk +#define syscall_dos_set_file_ptr syscall_DosSetFilePtr +#define syscall_dos_set_file_size syscall_DosSetFileSize +#define syscall_dos_set_path_info syscall_DosSetPathInfo +#define syscall_dos_start_timer syscall_DosStartTimer +#define syscall_dos_stop_timer syscall_DosStopTimer +#define syscall_dos_wait_event_sem syscall_DosWaitEventSem +#define syscall_dos_write syscall_DosWrite +#define syscall_dos_write_queue syscall_DosWriteQueue +#define syscall_kbd_char_in syscall_KbdCharIn +#define syscall_vio_wrt_tty syscall_VioWrtTTY +#define syscall_VIO16WRTTTY syscall_VioWrtTTY + +#endif /* not CLOSED_API_CALLS */ + +#endif /* SCM_OS2API_H */ diff --git a/v7/src/microcode/os2conio.c b/v7/src/microcode/os2conio.c new file mode 100644 index 000000000..c654a83e7 --- /dev/null +++ b/v7/src/microcode/os2conio.c @@ -0,0 +1,490 @@ +/* -*-C-*- + +$Id: os2conio.c,v 1.1 1994/11/28 03:42:54 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" +#ifdef USE_PMIO +#include +#endif + +typedef struct line_buffer_s +{ + msg_t * message; + struct line_buffer_s * next; +} line_buffer_t; + +static void console_thread (void *); +#ifndef USE_PMIO +static int getch (void); +#endif +static void grab_console_lock (void); +static void release_console_lock (void); + +static void init_line_buffer (void); +static line_buffer_t * make_line_buffer (line_buffer_t *); +static void push_line_buffer (void); +static void pop_line_buffer (void); +static line_buffer_t * reverse_line_buffer (void); + +static void process_input_char (char); +static void do_rubout (void); +static void add_to_line (char); +static void do_newline (void); +static void do_self_insert (char); +static void add_char_to_line_buffer (char); +static void finish_line (void); +static void send_char (char); +static void send_readahead (msg_t *); +static void handle_console_interrupt (msg_t *); + +static void console_operator + (Tchannel, chop_t, choparg_t, choparg_t, choparg_t);; +static void flush_input (void); +static void console_input_buffered (Tchannel, int, int *); +static void console_output_cooked (Tchannel, int, int *); + +static void write_char (char, int); +static void write_output (const char *, size_t, int); +static void write_output_1 (const char *, const char *); +static unsigned int char_output_length (char); + +#define LINEFEED '\012' + +static HMTX console_lock; +static int input_buffered_p; +static int output_cooked_p; +static qid_t console_writer_qid; +static channel_context_t * console_context; +static line_buffer_t * line_buffer; + +void +OS2_initialize_console (void) +{ +#ifdef USE_PMIO + pmio_fontspec = "6.System VIO"; + set_width (80); + set_height (40); + start_pmio (); +#endif + console_lock = (OS2_create_mutex_semaphore ()); + input_buffered_p = 1; + output_cooked_p = 1; + console_context = (OS2_make_channel_context ()); + OS2_open_qid ((CHANNEL_CONTEXT_READER_QID (console_context)), + OS2_scheme_tqueue); + console_writer_qid = (CHANNEL_CONTEXT_WRITER_QID (console_context)); + OS2_open_qid (console_writer_qid, (OS2_make_std_tqueue ())); + (void) OS2_beginthread (console_thread, 0, 0x4000); +} + +static void +console_thread (void * arg) +{ + grab_console_lock (); + init_line_buffer (); + release_console_lock (); + (void) OS2_thread_initialize (console_writer_qid); + while (1) + { + int c = (getch ()); + if (c == EOF) + break; + { + int code = (OS2_keyboard_interrupt_handler (c)); + if (code == '\0') + process_input_char (c); + else + { + msg_t * message = (OS2_create_message (mt_console_interrupt)); + (SM_CONSOLE_INTERRUPT_CODE (message)) = code; + OS2_send_message (OS2_interrupt_qid, message); + /* Flush buffers only for certain chars? */ + flush_input (); + } + } + } + OS2_endthread (); +} + +#ifndef USE_PMIO +static int +getch (void) +{ + while (1) + { +#if 1 + KBDKEYINFO info; + XTD_API_CALL + (kbd_char_in, ((&info), IO_WAIT, 0), + { + if (rc == ERROR_KBD_INVALID_HANDLE) + return (EOF); + }); + if ((info . fbStatus) == 0x40) + return (info . chChar); +#else + int c = (_getch ()); + if (c == EOF) + return (EOF); + else if ((c == 0) || (c == 0xe0)) + { + /* Discard extended keycodes. */ + if ((_getch ()) == EOF) + return (EOF); + } + else + return (c); +#endif + } +} +#endif /* not USE_PMIO */ + +static void +grab_console_lock (void) +{ + OS2_request_mutex_semaphore (console_lock); +} + +static void +release_console_lock (void) +{ + OS2_release_mutex_semaphore (console_lock); +} + +static void +init_line_buffer (void) +{ + line_buffer = 0; + push_line_buffer (); +} + +static line_buffer_t * +make_line_buffer (line_buffer_t * next) +{ + line_buffer_t * buffer = (OS_malloc (sizeof (line_buffer_t))); + msg_t * message = (OS2_make_readahead ()); + (SM_READAHEAD_SIZE (message)) = 0; + (buffer -> message) = message; + (buffer -> next) = next; + return (buffer); +} + +static void +push_line_buffer (void) +{ + line_buffer = (make_line_buffer (line_buffer)); +} + +static void +pop_line_buffer (void) +{ + line_buffer_t * buffer = line_buffer; + OS2_destroy_message (buffer -> message); + line_buffer = (buffer -> next); + OS_free (buffer); +} + +static line_buffer_t * +reverse_line_buffer (void) +{ + line_buffer_t * this = line_buffer; + line_buffer_t * prev = 0; + line_buffer_t * next; + line_buffer = 0; + while (1) + { + next = (this -> next); + (this -> next) = prev; + if (next == 0) + break; + prev = this; + this = next; + } + push_line_buffer (); + return (this); +} + +#define LINE_BUFFER_SIZE (SM_READAHEAD_SIZE (line_buffer -> message)) +#define LINE_BUFFER_DATA (SM_READAHEAD_DATA (line_buffer -> message)) + +static void +process_input_char (char c) +{ + if (!input_buffered_p) + send_char (c); + else switch (c) + { + case '\b': + case '\177': + do_rubout (); + break; + case '\r': + do_self_insert (LINEFEED); + finish_line (); + break; + default: + do_self_insert (c); + break; + } +} + +static void +do_self_insert (char c) +{ + add_char_to_line_buffer (c); + write_char (c, 1); +} + +static void +add_char_to_line_buffer (char c) +{ + grab_console_lock (); + if (LINE_BUFFER_SIZE == SM_READAHEAD_MAX) + push_line_buffer (); + (LINE_BUFFER_DATA [LINE_BUFFER_SIZE ++]) = c; + release_console_lock (); +} + +static void +do_rubout (void) +{ + grab_console_lock (); + if (LINE_BUFFER_SIZE == 0) + { + if ((line_buffer -> next) == 0) + { + release_console_lock (); + write_char ('\a', 0); + return; + } + pop_line_buffer (); + } + { + unsigned int n + = (char_output_length (LINE_BUFFER_DATA [-- LINE_BUFFER_SIZE])); + unsigned int i; + release_console_lock (); + for (i = 0; (i < n); i += 1) + write_char ('\b', 0); + for (i = 0; (i < n); i += 1) + write_char (' ', 0); + for (i = 0; (i < n); i += 1) + write_char ('\b', 0); + } +} + +static void +finish_line (void) +{ + line_buffer_t * buffer; + grab_console_lock (); + buffer = (reverse_line_buffer ()); + release_console_lock (); + while (buffer != 0) + { + send_readahead (buffer -> message); + buffer = (buffer -> next); + OS_free (buffer); + } +} + +static void +send_char (char c) +{ + msg_t * message = (OS2_make_readahead ()); + (SM_READAHEAD_SIZE (message)) = 1; + ((SM_READAHEAD_DATA (message)) [0]) = c; + send_readahead (message); +} + +static void +send_readahead (msg_t * message) +{ + OS2_send_message (console_writer_qid, message); + OS2_wait_for_readahead_ack (console_writer_qid); +} + +void +OS2_initialize_console_channel (Tchannel channel) +{ + (CHANNEL_OPERATOR_CONTEXT (channel)) = console_context; + (CHANNEL_OPERATOR (channel)) = console_operator; +} + +static void +console_operator (Tchannel channel, chop_t operation, + choparg_t arg1, choparg_t arg2, choparg_t arg3) +{ + switch (operation) + { + case chop_read: + (* ((long *) arg3)) + = (channel_thread_read (channel, ((char *) arg1), ((size_t) arg2))); + break; + case chop_write: + write_output (((const char *) arg1), ((size_t) arg2), output_cooked_p); + (* ((long *) arg3)) = ((size_t) arg2); + break; + case chop_close: + case chop_output_flush: + case chop_output_drain: + break; + case chop_input_flush: + flush_input (); + break; + case chop_input_buffered: + console_input_buffered (channel, ((int) arg1), ((int *) arg2)); + break; + case chop_output_cooked: + console_output_cooked (channel, ((int) arg1), ((int *) arg2)); + break; + default: + OS2_logic_error ("Unknown operation for console."); + break; + } +} + +static void +flush_input (void) +{ + grab_console_lock (); + while ((line_buffer -> next) != 0) + pop_line_buffer (); + LINE_BUFFER_SIZE = 0; + release_console_lock (); +} + +static void +console_input_buffered (Tchannel channel, int new, int * pold) +{ + if (new < 0) + (* pold) = input_buffered_p; + else + { + int old = input_buffered_p; + input_buffered_p = new; + if (old && (!new)) + { + grab_console_lock (); + finish_line (); + } + } +} + +static void +console_output_cooked (Tchannel channel, int new, int * pold) +{ + if (new < 0) + (* pold) = output_cooked_p; + else + output_cooked_p = new; +} + +static void +write_char (char c, int cooked_p) +{ + write_output ((&c), 1, cooked_p); +} + +static void +write_output (const char * data, size_t size, int cooked_p) +{ + const char * scan = data; + const char * end = (scan + size); + char output_translation [256]; + char * out = output_translation; + char * out_limit = (out + ((sizeof (output_translation)) - 4)); + char c; + if (!cooked_p) + write_output_1 (scan, end); + else + while (1) + { + if ((scan == end) || (out >= out_limit)) + { + write_output_1 (output_translation, out); + if (scan == end) + break; + out = output_translation; + } + c = (*scan++); + if (isprint (c)) + (*out++) = c; + else if (c == LINEFEED) + { + (*out++) = '\r'; + (*out++) = c; + } + else if (c < 0x20) + { + (*out++) = '^'; + (*out++) = ('@' + c); + } + else + { + (*out++) = '\\'; + (*out++) = ('0' + ((c >> 6) & 3)); + (*out++) = ('0' + ((c >> 3) & 7)); + (*out++) = ('0' + (c & 7)); + } + } +} + +static void +write_output_1 (const char * scan, const char * end) +{ +#ifdef USE_PMIO + put_raw ((end - scan), scan); +#else /* not USE_PMIO */ +#if 1 + STD_API_CALL (vio_wrt_tty, (((PCH) scan), (end - scan), 0)); +#else + while (1) + { + ULONG n; + APIRET rc = (dos_write (1, ((void *) scan), (end - scan), (& n))); + if (rc != NO_ERROR) + break; + scan += n; + if (scan == end) + break; + } +#endif +#endif /* not USE_PMIO */ +} + +static unsigned int +char_output_length (char c) +{ + return ((isprint (c)) ? 1 : (c < 0x20) ? 2 : 4); +} diff --git a/v7/src/microcode/os2cthrd.c b/v7/src/microcode/os2cthrd.c new file mode 100644 index 000000000..863534d06 --- /dev/null +++ b/v7/src/microcode/os2cthrd.c @@ -0,0 +1,137 @@ +/* -*-C-*- + +$Id: os2cthrd.c,v 1.1 1994/11/28 03:42:55 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +/* Scheme side of channel thread interface */ + +#include "os2.h" + +void +OS2_initialize_channel_thread_messages (void) +{ + SET_MSG_TYPE_LENGTH (mt_readahead, sm_readahead_t); + SET_MSG_TYPE_LENGTH (mt_readahead_ack, sm_readahead_ack_t); +} + +channel_context_t * +OS2_make_channel_context (void) +{ + channel_context_t * context = (OS_malloc (sizeof (channel_context_t))); + OS2_make_qid_pair ((& (CHANNEL_CONTEXT_READER_QID (context))), + (& (CHANNEL_CONTEXT_WRITER_QID (context)))); + (CHANNEL_CONTEXT_READAHEAD (context)) = 0; + (CHANNEL_CONTEXT_READAHEAD_INDEX (context)) = 0; + (CHANNEL_CONTEXT_EOFP (context)) = 0; + return (context); +} + +long +channel_thread_read (Tchannel channel, char * buffer, size_t size) +{ + channel_context_t * context = (CHANNEL_OPERATOR_CONTEXT (channel)); + qid_t qid = (CHANNEL_CONTEXT_READER_QID (context)); + msg_t * message; + unsigned int index; + unsigned int navail; + if (CHANNEL_CONTEXT_EOFP (context)) + return (0); + message = (CHANNEL_CONTEXT_READAHEAD (context)); + index = (CHANNEL_CONTEXT_READAHEAD_INDEX (context)); + if (message == 0) + { + if (CHANNEL_NONBLOCKING (channel)) + { + message = (OS2_receive_message (qid, 0)); + if (message == 0) + { + (CHANNEL_CONTEXT_READAHEAD (context)) = 0; + return (-1); + } + } + else + message = (OS2_receive_message (qid, 1)); + /* Acknowledge the message so that the readahead thread will + know that it is safe to start reading some more. */ + OS2_send_message (qid, (OS2_make_readahead_ack ())); + if (OS2_error_message_p (message)) + OS2_handle_error_message (message); + if ((MSG_TYPE (message)) != mt_readahead) + OS2_logic_error ("Illegal message from channel thread."); + index = 0; + } + if ((SM_READAHEAD_SIZE (message)) == 0) + { + OS2_destroy_message (message); + (CHANNEL_CONTEXT_READAHEAD (context)) = 0; + (CHANNEL_CONTEXT_EOFP (context)) = 1; + return (0); + } + navail = ((SM_READAHEAD_SIZE (message)) - index); + if (navail <= size) + { + FASTCOPY ((SM_READAHEAD_DATA (message)), buffer, navail); + OS2_destroy_message (message); + (CHANNEL_CONTEXT_READAHEAD (context)) = 0; + return (navail); + } + else + { + FASTCOPY ((SM_READAHEAD_DATA (message)), buffer, size); + (CHANNEL_CONTEXT_READAHEAD (context)) = message; + (CHANNEL_CONTEXT_READAHEAD_INDEX (context)) = (index + size); + return (size); + } +} + +void +OS2_wait_for_readahead_ack (qid_t qid) +{ + /* Wait for an acknowledgement before starting another read. + This regulates the amount of data in the queue. */ + msg_t * message = (OS2_receive_message (qid, 1)); + if ((MSG_TYPE (message)) != mt_readahead_ack) + OS2_logic_error ("Expected readahead_ack message."); + OS2_destroy_message (message); +} + +void +channel_thread_close (Tchannel channel) +{ + channel_context_t * context = (CHANNEL_OPERATOR_CONTEXT (channel)); + /* Closing handle should force input thread to kill itself. */ + STD_API_CALL (dos_close, (CHANNEL_HANDLE (channel))); + if ((CHANNEL_CONTEXT_READAHEAD (context)) != 0) + OS2_destroy_message (CHANNEL_CONTEXT_READAHEAD (context)); + OS2_close_qid (CHANNEL_CONTEXT_READER_QID (context)); + OS_free (context); +} diff --git a/v7/src/microcode/os2cthrd.h b/v7/src/microcode/os2cthrd.h new file mode 100644 index 000000000..23d3470b5 --- /dev/null +++ b/v7/src/microcode/os2cthrd.h @@ -0,0 +1,75 @@ +/* -*-C-*- + +$Id: os2cthrd.h,v 1.1 1994/11/28 03:42:55 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#ifndef SCM_OS2CTHRD_H +#define SCM_OS2CTHRD_H + +#ifndef SM_READAHEAD_MAX +#define SM_READAHEAD_MAX 4096 +#endif + +typedef struct +{ + qid_t reader_qid; + qid_t writer_qid; + msg_t * readahead; + unsigned int readahead_index; + char eofp; +} channel_context_t; +#define CHANNEL_CONTEXT_READER_QID(c) ((c) -> reader_qid) +#define CHANNEL_CONTEXT_WRITER_QID(c) ((c) -> writer_qid) +#define CHANNEL_CONTEXT_READAHEAD(c) ((c) -> readahead) +#define CHANNEL_CONTEXT_READAHEAD_INDEX(c) ((c) -> readahead_index) +#define CHANNEL_CONTEXT_EOFP(c) ((c) -> eofp) + +typedef struct +{ + DECLARE_MSG_HEADER_FIELDS; + ULONG size; + char data [SM_READAHEAD_MAX]; +} sm_readahead_t; +#define SM_READAHEAD_SIZE(m) (((sm_readahead_t *) (m)) -> size) +#define SM_READAHEAD_DATA(m) (((sm_readahead_t *) (m)) -> data) + +#define OS2_make_readahead() OS2_create_message (mt_readahead) +#define OS2_make_readahead_ack() OS2_create_message (mt_readahead_ack) + +typedef msg_t sm_readahead_ack_t; + +extern channel_context_t * OS2_make_channel_context (void); +extern long channel_thread_read (Tchannel, char *, size_t); +extern void OS2_wait_for_readahead_ack (qid_t); +extern void channel_thread_close (Tchannel); + +#endif /* SCM_OS2CTHRD_H */ diff --git a/v7/src/microcode/os2ctty.c b/v7/src/microcode/os2ctty.c new file mode 100644 index 000000000..eb0a01a72 --- /dev/null +++ b/v7/src/microcode/os2ctty.c @@ -0,0 +1,210 @@ +/* -*-C-*- + +$Id: os2ctty.c,v 1.1 1994/11/28 03:42:55 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" +#include "osctty.h" +#include "ossig.h" + +#define CONTROL_B_ENABLE (0x1) +#define CONTROL_G_ENABLE (0x2) +#define CONTROL_U_ENABLE (0x4) +#define CONTROL_X_ENABLE (0x8) +#define INTERACTIVE_INTERRUPT_ENABLE (0x10) +#define TERMINATE_INTERRUPT_ENABLE (0x20) + +#define ALL_ENABLES \ + (CONTROL_B_ENABLE | CONTROL_G_ENABLE | CONTROL_U_ENABLE \ + | CONTROL_X_ENABLE | INTERACTIVE_INTERRUPT_ENABLE \ + | TERMINATE_INTERRUPT_ENABLE) + +#define CONTROL_B '\002' +#define CONTROL_G '\007' +#define CONTROL_U '\025' +#define CONTROL_X '\030' +#define CONTROL_C '\003' + +#define KB_INT_CHARS_SIZE 5 +#define KB_INT_TABLE_SIZE 256 + +static char keyboard_interrupt_characters [KB_INT_CHARS_SIZE]; +static enum interrupt_handler keyboard_interrupt_handlers [KB_INT_CHARS_SIZE]; +static enum interrupt_handler keyboard_interrupt_table [KB_INT_TABLE_SIZE]; +static enum interrupt_handler keyboard_break_interrupt; +static Tinterrupt_enables keyboard_interrupt_enables; + +static void +update_keyboard_interrupt_characters (void) +{ + unsigned int i; + for (i = 0; (i < KB_INT_TABLE_SIZE); i += 1) + (keyboard_interrupt_table[i]) = interrupt_handler_ignore; + for (i = 0; (i < KB_INT_CHARS_SIZE); i += 1) + (keyboard_interrupt_table [keyboard_interrupt_characters [i]]) = + (keyboard_interrupt_handlers[i]); +} + +void +OS2_initialize_keyboard_interrupts (void) +{ + (keyboard_interrupt_characters[0]) = CONTROL_B; + (keyboard_interrupt_handlers[0]) = interrupt_handler_control_b; + (keyboard_interrupt_characters[1]) = CONTROL_G; + (keyboard_interrupt_handlers[1]) = interrupt_handler_control_g; + (keyboard_interrupt_characters[2]) = CONTROL_U; + (keyboard_interrupt_handlers[2]) = interrupt_handler_control_u; + (keyboard_interrupt_characters[3]) = CONTROL_X; + (keyboard_interrupt_handlers[3]) = interrupt_handler_control_x; + (keyboard_interrupt_characters[4]) = CONTROL_C; + (keyboard_interrupt_handlers[4]) = interrupt_handler_interactive; + keyboard_break_interrupt = interrupt_handler_terminate; + update_keyboard_interrupt_characters (); + keyboard_interrupt_enables = ALL_ENABLES; +} + +void +OS_ctty_get_interrupt_enables (Tinterrupt_enables * mask) +{ + (*mask) = keyboard_interrupt_enables; +} + +void +OS_ctty_set_interrupt_enables (Tinterrupt_enables * mask) +{ + keyboard_interrupt_enables = ((*mask) & ALL_ENABLES); +} + +unsigned int +OS_ctty_num_int_chars (void) +{ + return (KB_INT_CHARS_SIZE + 1); +} + +cc_t +OS_tty_map_interrupt_char (cc_t int_char) +{ + return (int_char); +} + +cc_t * +OS_ctty_get_int_chars (void) +{ + static cc_t characters [KB_INT_CHARS_SIZE + 1]; + unsigned int i; + for (i = 0; (i < KB_INT_CHARS_SIZE); i += 1) + (characters[i]) = (keyboard_interrupt_characters[i]); + (characters[i]) = '\0'; /* dummy for control-break */ + return (characters); +} + +void +OS_ctty_set_int_chars (cc_t * characters) +{ + unsigned int i; + for (i = 0; (i < KB_INT_CHARS_SIZE); i += 1) + (keyboard_interrupt_characters[i]) = (characters[i]); + update_keyboard_interrupt_characters (); +} + +cc_t * +OS_ctty_get_int_char_handlers (void) +{ + static cc_t handlers [KB_INT_CHARS_SIZE + 1]; + unsigned int i; + for (i = 0; (i < KB_INT_CHARS_SIZE); i += 1) + (handlers[i]) = ((cc_t) (keyboard_interrupt_handlers[i])); + (handlers[i]) = ((cc_t) keyboard_break_interrupt); + return (handlers); +} + +void +OS_ctty_set_int_char_handlers (cc_t * handlers) +{ + unsigned int i; + for (i = 0; (i < KB_INT_CHARS_SIZE); i += 1) + (keyboard_interrupt_handlers[i]) = + ((enum interrupt_handler) (handlers[i])); + keyboard_break_interrupt = ((enum interrupt_handler) (handlers[i])); + update_keyboard_interrupt_characters (); +} + +static char +check_if_enabled (enum interrupt_handler handler) +{ + unsigned int bitmask; + char result; + switch (handler) + { + case interrupt_handler_control_b: + bitmask = CONTROL_B_ENABLE; + result = 'B'; + break; + case interrupt_handler_control_g: + bitmask = CONTROL_G_ENABLE; + result = 'G'; + break; + case interrupt_handler_control_u: + bitmask = CONTROL_U_ENABLE; + result = 'U'; + break; + case interrupt_handler_control_x: + bitmask = CONTROL_X_ENABLE; + result = 'X'; + break; + case interrupt_handler_interactive: + bitmask = INTERACTIVE_INTERRUPT_ENABLE; + result = '!'; + break; + case interrupt_handler_terminate: + bitmask = TERMINATE_INTERRUPT_ENABLE; + result = '@'; + break; + default: + bitmask = 0; + result = '\0'; + break; + } + return (((keyboard_interrupt_enables & bitmask) == 0) ? '\0' : result); +} + +char +OS2_keyboard_interrupt_handler (char c) +{ + return (check_if_enabled (keyboard_interrupt_table[c])); +} + +char +OS2_keyboard_break_interrupt_handler (void) +{ + return (check_if_enabled (keyboard_break_interrupt)); +} diff --git a/v7/src/microcode/os2ctty.h b/v7/src/microcode/os2ctty.h new file mode 100644 index 000000000..7c666f541 --- /dev/null +++ b/v7/src/microcode/os2ctty.h @@ -0,0 +1,41 @@ +/* -*-C-*- + +$Id: os2ctty.h,v 1.1 1994/11/28 03:42:56 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#ifndef SCM_OS2CTTY_H +#define SCM_OS2CTTY_H + +extern char OS2_keyboard_interrupt_handler (char); +extern char OS2_keyboard_break_interrupt_handler (void); + +#endif /* SCM_OS2CTTY_H */ diff --git a/v7/src/microcode/os2env.c b/v7/src/microcode/os2env.c new file mode 100644 index 000000000..9cabb48ae --- /dev/null +++ b/v7/src/microcode/os2env.c @@ -0,0 +1,301 @@ +/* -*-C-*- + +$Id: os2env.c,v 1.1 1994/11/28 03:42:56 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "scheme.h" +#undef END_OF_CHAIN +#include "os2.h" +#include "osenv.h" +#include +#include + +#ifdef __IBMC__ + +#include + +#else /* not __IBMC__ */ +#ifdef __GCC2__ + +#include +#include + +#endif /* __GCC2__ */ +#endif /* not __IBMC__ */ + +static void initialize_real_time_clock (void); +static double get_real_time_clock (void); + +static void initialize_timer (void); +static void timer_thread (void *); +static void handle_timer_event (msg_t *); + +void +OS2_initialize_environment (void) +{ + initialize_real_time_clock (); + initialize_timer (); +} + +time_t +OS_encoded_time (void) +{ + time_t t = (time (0)); + if (t < 0) + OS2_error_system_call (errno, syscall_time); + return (t); +} + +void +OS_decode_time (time_t t, struct time_structure * buffer) +{ + struct tm * ts = (localtime (&t)); + if (ts == 0) + OS2_error_system_call (errno, syscall_localtime); + (buffer -> year) = ((ts -> tm_year) + 1900); + (buffer -> month) = ((ts -> tm_mon) + 1); + (buffer -> day) = (ts -> tm_mday); + (buffer -> hour) = (ts -> tm_hour); + (buffer -> minute) = (ts -> tm_min); + (buffer -> second) = (ts -> tm_sec); + { + /* In localtime() encoding, 0 is Sunday; in ours, it's Monday. */ + int wday = (ts -> tm_wday); + (buffer -> day_of_week) = ((wday == 0) ? 6 : (wday - 1)); + } +} + +time_t +OS_encode_time (struct time_structure * buffer) +{ + struct tm ts; + (ts . tm_year) = ((buffer -> year) - 1900); + (ts . tm_mon) = ((buffer -> month) - 1); + (ts . tm_mday) = (buffer -> day); + (ts . tm_hour) = (buffer -> hour); + (ts . tm_min) = (buffer -> minute); + (ts . tm_sec) = (buffer -> second); + (ts . tm_isdst) = -1; /* Let mktime figure it out */ + { + time_t t = (mktime (&ts)); + if (t < 0) + OS2_error_system_call (errno, syscall_mktime); + return (t); + } +} + +static double initial_rtc; + +static void +initialize_real_time_clock (void) +{ + initial_rtc = (get_real_time_clock ()); +} + +double +OS_real_time_clock (void) +{ + return ((get_real_time_clock ()) - initial_rtc); +} + +static double +get_real_time_clock (void) +{ +#ifdef __IBMC__ + struct timeb rtc; + _ftime (&rtc); + return ((((double) (rtc . time)) * 1000.0) + ((double) (rtc . millitm))); +#else /* not __IBMC__ */ +#ifdef __GCC2__ + struct tms rtc; + times (&rtc); + return (((double) (rtc . tms_utime)) * (1000.0 / ((double) CLK_TCK))); +#endif /* __GCC2__ */ +#endif /* not __IBMC__ */ +} + +double +OS_process_clock (void) +{ + /* This must not signal an error in normal use. */ + return (OS_real_time_clock ()); +} + +static HEV timer_event; +static int timer_handle_valid; +static HTIMER timer_handle; +static TID timer_tid; + +static void +initialize_timer (void) +{ + timer_event = (OS2_create_event_semaphore ()); + timer_handle_valid = 0; + timer_tid = (OS2_beginthread (timer_thread, 0, 0)); +} + +void +OS2_kill_timer_thread (void) +{ + OS2_kill_thread (timer_tid); +} + +static void +timer_thread (void * arg) +{ + (void) OS2_thread_initialize (QID_NONE); + while (1) + { + ULONG count = (OS2_reset_event_semaphore (timer_event)); + while (count > 0) + { + OS2_send_message (OS2_interrupt_qid, + (OS2_create_message (mt_timer_event))); + count -= 1; + } + (void) OS2_wait_event_semaphore (timer_event, 1); + } +} + +void +OS_real_timer_set (clock_t first, clock_t interval) +{ + /* **** No support for (first != interval), but runtime system never + does that anyway. */ + OS_real_timer_clear (); + if (interval != 0) + { + STD_API_CALL (dos_start_timer, (interval, + ((HSEM) (&timer_event)), + (&timer_handle))); + timer_handle_valid = 1; + } + else if (first != 0) + { + STD_API_CALL (dos_async_timer, (first, + ((HSEM) (&timer_event)), + (&timer_handle))); + timer_handle_valid = 1; + } +} + +void +OS_real_timer_clear (void) +{ + if (timer_handle_valid) + { + STD_API_CALL (dos_stop_timer, (timer_handle)); + timer_handle_valid = 0; + } + (void) OS2_reset_event_semaphore (timer_event); +} + +void +OS_process_timer_set (clock_t first, clock_t interval) +{ + OS2_error_unimplemented_primitive (); +} + +void +OS_process_timer_clear (void) +{ +} + +void +OS_profile_timer_set (clock_t first, clock_t interval) +{ + OS2_error_unimplemented_primitive (); +} + +void +OS_profile_timer_clear (void) +{ +} + +static size_t current_dir_path_size = 0; +static char * current_dir_path = 0; + +const char * +OS_working_dir_pathname (void) +{ + ULONG drive_number; + { + ULONG drive_map; + STD_API_CALL (dos_query_current_disk, ((&drive_number), (&drive_map))); + } + if ((current_dir_path_size == 0) || (current_dir_path == 0)) + { + current_dir_path_size = 1024; + current_dir_path = (OS_malloc (current_dir_path_size)); + } + while (1) + { + ULONG size = (current_dir_path_size - 3); + { + APIRET rc = + (dos_query_current_dir + (drive_number, (current_dir_path + 3), (&size))); + if (rc == NO_ERROR) + break; + if (rc != ERROR_BUFFER_OVERFLOW) + OS2_error_system_call (rc, syscall_dos_query_current_dir); + } + do + current_dir_path_size *= 2; + while ((current_dir_path_size - 3) < size); + OS_free (current_dir_path); + current_dir_path = (OS_malloc (current_dir_path_size)); + } + (current_dir_path[0]) = ('a' + drive_number - 1); + (current_dir_path[1]) = ':'; + (current_dir_path[2]) = '\\'; + return (current_dir_path); +} + +void +OS_set_working_dir_pathname (const char * name) +{ + extern char * OS2_remove_trailing_backslash (const char *); + unsigned int length; + name = (OS2_remove_trailing_backslash (name)); + /* **** Documentation doesn't clarify whether DosSetCurrentDir will + handle the drive prefix correctly or not. */ + length = (strlen (name)); + if ((length >= 2) && ((name[1]) == ':')) + { + STD_API_CALL + (dos_set_default_disk, + ((name[0]) - ((islower (name[0])) ? 'a' : 'A') + 1)); + name += 2; + } + STD_API_CALL (dos_set_current_dir, ((char *) name)); +} diff --git a/v7/src/microcode/os2file.c b/v7/src/microcode/os2file.c new file mode 100644 index 000000000..495a2c5f9 --- /dev/null +++ b/v7/src/microcode/os2file.c @@ -0,0 +1,179 @@ +/* -*-C-*- + +$Id: os2file.c,v 1.1 1994/11/28 03:42:57 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" +#include "osfile.h" + +static ULONG set_file_pointer (Tchannel, ULONG, LONG); + +#define OS2_OPEN_MODE(m) \ + ((((m) & CHANNEL_READ) == 0) \ + ? (OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE) \ + : (((m) & CHANNEL_WRITE) == 0) \ + ? (OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE) \ + : (OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE)) + +static Tchannel +open_file (const char * filename, ULONG attr, ULONG flags, unsigned int mode) +{ + HFILE handle; + ULONG action; + STD_API_CALL + (dos_open, (((char *) filename), (&handle), (&action), 0, attr, flags, + (OS2_OPEN_MODE (mode)), 0)); + return (OS2_make_channel (handle, mode)); +} + +Tchannel +OS_open_input_file (const char * filename) +{ + return + (open_file (filename, + FILE_NORMAL, + (OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW), + CHANNEL_READ)); +} + +Tchannel +OS_open_output_file (const char * filename) +{ + return + (open_file (filename, + FILE_NORMAL, + (OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW), + CHANNEL_WRITE)); +} + +Tchannel +OS_open_io_file (const char * filename) +{ + return + (open_file (filename, + FILE_NORMAL, + (OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW), + (CHANNEL_READ | CHANNEL_WRITE))); +} + +Tchannel +OS_open_append_file (const char * filename) +{ + Tchannel channel = + (open_file (filename, + FILE_NORMAL, + (OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW), + CHANNEL_WRITE)); + transaction_begin (); + OS_channel_close_on_abort (channel); + (void) set_file_pointer (channel, FILE_END, 0); + transaction_commit (); + return (channel); +} + +static Tchannel +open_file_noerror (const char * filename, ULONG attr, ULONG flags, + unsigned int mode) +{ + HFILE handle; + ULONG action; + if ((dos_open (((char *) filename), (&handle), (&action), 0, attr, flags, + (OS2_OPEN_MODE (mode)), 0)) + != NO_ERROR) + return (NO_CHANNEL); + { + Tchannel channel = (OS2_make_channel (handle, mode)); + if ((CHANNEL_TYPE (channel)) == channel_type_file) + return (channel); + OS_channel_close_noerror (channel); + return (NO_CHANNEL); + } +} + +Tchannel +OS_open_load_file (const char * filename) +{ + return + (open_file_noerror + (filename, + FILE_NORMAL, + (OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW), + CHANNEL_READ)); +} + +Tchannel +OS_open_dump_file (const char * filename) +{ + return + (open_file_noerror + (filename, + FILE_NORMAL, + (OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW), + CHANNEL_WRITE)); +} + +off_t +OS_file_length (Tchannel channel) +{ + FILESTATUS3 buffer; + if ((CHANNEL_TYPE (channel)) != channel_type_file) + OS2_error_system_call (ERROR_INVALID_HANDLE, syscall_dos_query_file_info); + STD_API_CALL + (dos_query_file_info, + ((CHANNEL_HANDLE (channel)), FIL_STANDARD, + (&buffer), (sizeof (buffer)))); + return (buffer.cbFile); +} + +off_t +OS_file_position (Tchannel channel) +{ + return (set_file_pointer (channel, FILE_CURRENT, 0)); +} + +void +OS_file_set_position (Tchannel channel, off_t position) +{ + if ((set_file_pointer (channel, FILE_BEGIN, position)) != position) + OS2_error_anonymous (); +} + +static ULONG +set_file_pointer (Tchannel channel, ULONG type, LONG distance) +{ + ULONG fp; + if ((CHANNEL_TYPE (channel)) != channel_type_file) + OS2_error_system_call (ERROR_INVALID_HANDLE, syscall_dos_set_file_ptr); + STD_API_CALL + (dos_set_file_ptr, ((CHANNEL_HANDLE (channel)), distance, type, (&fp))); + return (fp); +} diff --git a/v7/src/microcode/os2fs.c b/v7/src/microcode/os2fs.c new file mode 100644 index 000000000..659233b7c --- /dev/null +++ b/v7/src/microcode/os2fs.c @@ -0,0 +1,377 @@ +/* -*-C-*- + +$Id: os2fs.c,v 1.1 1994/11/28 03:42:57 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" +#include "osfs.h" + +#ifdef __GCC2__ +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif + +static const char * make_pathname (const char *, const char *); +static const char * filename_extension (const char *); +extern char * OS2_remove_trailing_backslash (const char *); + +FILESTATUS3 * +OS2_read_file_status (const char * filename) +{ + static FILESTATUS3 info; + XTD_API_CALL + (dos_query_path_info, + ((OS2_remove_trailing_backslash (filename)), + FIL_STANDARD, (&info), (sizeof (info))), + { + if ((rc == ERROR_FILE_NOT_FOUND) + || (rc == ERROR_PATH_NOT_FOUND) + /* ERROR_ACCESS_DENIED can occur if the file is a symbolic + link on a unix system mounted via NFS, and if the + symbolic link points to a nonexistent file. */ + || (rc == ERROR_ACCESS_DENIED)) + return (0); + }); + return (&info); +} + +void +OS2_write_file_status (const char * filename, FILESTATUS3 * info) +{ + STD_API_CALL + (dos_set_path_info, + ((OS2_remove_trailing_backslash (filename)), + FIL_STANDARD, info, (sizeof (FILESTATUS3)), 0)); +} + +enum file_existence +OS_file_existence_test (const char * filename) +{ + return ((OS2_read_file_status (filename)) + ? file_does_exist + : file_doesnt_exist); +} + +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 + +int +OS_file_access (const char * filename, unsigned int mode) +{ + FILESTATUS3 * info = (OS2_read_file_status (filename)); + if (!info) + return (0); + if (((mode & W_OK) != 0) && (((info -> attrFile) & FILE_READONLY) != 0)) + return (0); + if ((mode & X_OK) != 0) + { + if (((info -> attrFile) & FILE_DIRECTORY) != 0) + return (0); + { + const char * extension = (filename_extension (filename)); + if (! (((stricmp (extension, ".exe")) == 0) + || ((stricmp (extension, ".com")) == 0) + || ((stricmp (extension, ".cmd")) == 0) + || ((stricmp (extension, ".bat")) == 0))) + return (0); + } + } + return (1); +} + +int +OS_file_directory_p (const char * filename) +{ + FILESTATUS3 * info = (OS2_read_file_status (filename)); + return ((info == 0) ? 0 : (((info -> attrFile) & FILE_DIRECTORY) != 0)); +} + +const char * +OS_file_soft_link_p (const char * filename) +{ + return (0); +} + +void +OS_file_remove (const char * filename) +{ + { + FILESTATUS3 * info = (OS2_read_file_status (filename)); + if (info == 0) + return; + if (((info -> attrFile) & FILE_READONLY) != 0) + { + (info -> attrFile) &=~ FILE_READONLY; + STD_API_CALL + (dos_set_path_info, + (((char *) filename), FIL_STANDARD, info, (sizeof (*info)), 0)); + } + } + STD_API_CALL (dos_delete, ((char *) filename)); +} + +void +OS_file_remove_link (const char * filename) +{ + OS_file_remove (filename); +} + +void +OS_file_rename (const char * from_name, const char * to_name) +{ + STD_API_CALL (dos_move, (((char *) from_name), ((char *) to_name))); +} + +void +OS_file_link_hard (const char * from_name, const char * to_name) +{ + OS2_error_unimplemented_primitive (); +} + +void +OS_file_link_soft (const char * from_name, const char * to_name) +{ + OS2_error_unimplemented_primitive (); +} + +void +OS_directory_make (const char * directory_name) +{ + STD_API_CALL + (dos_create_dir, ((OS2_remove_trailing_backslash (directory_name)), 0)); +} + +void +OS_directory_delete (const char * directory_name) +{ + STD_API_CALL + (dos_delete_dir, (OS2_remove_trailing_backslash (directory_name))); +} + +typedef struct +{ + const char * search_pattern; + HDIR handle; + FILEFINDBUF3 info; + ULONG count; +} dir_search_state; + +static dir_search_state * dir_search_states; +static unsigned int n_dir_search_states; + +void +OS2_initialize_directory_reader (void) +{ + dir_search_states = 0; + n_dir_search_states = 0; +} + +static unsigned int +allocate_dir_search_state (const char * search_pattern) +{ + if (n_dir_search_states == 0) + { + dir_search_state * states = + ((dir_search_state *) (OS_malloc ((sizeof (dir_search_state)) * 4))); + dir_search_states = states; + n_dir_search_states = 4; + { + dir_search_state * scan = dir_search_states; + dir_search_state * end = (scan + n_dir_search_states); + ((scan++) -> search_pattern) = search_pattern; + while (scan < end) + ((scan++) -> search_pattern) = 0; + } + return (0); + } + { + dir_search_state * scan = dir_search_states; + dir_search_state * end = (scan + n_dir_search_states); + while (scan < end) + if (((scan++) -> search_pattern) == 0) + { + ((--scan) -> search_pattern) = search_pattern; + return (scan - dir_search_states); + } + } + { + unsigned int result = n_dir_search_states; + unsigned int n_states = (2 * n_dir_search_states); + dir_search_state * states = + ((dir_search_state *) + (OS_realloc (((void *) dir_search_states), + ((sizeof (dir_search_state)) * n_states)))); + { + dir_search_state * scan = (states + result); + dir_search_state * end = (states + n_states); + ((scan++) -> search_pattern) = search_pattern; + while (scan < end) + ((scan++) -> search_pattern) = 0; + } + dir_search_states = states; + n_dir_search_states = n_states; + return (result); + } +} + +#define REFERENCE_DIR_SEARCH_STATE(index) (& (dir_search_states[(index)])) +#define DEALLOCATE_DIR_SEARCH_STATE(state) \ +{ \ + if ((state -> search_pattern) != 0) \ + { \ + OS_free ((void *) (state -> search_pattern)); \ + (state -> search_pattern) = 0; \ + } \ +} + +int +OS_directory_valid_p (long index) +{ + return + ((0 <= index) + && (index < n_dir_search_states) + && (((REFERENCE_DIR_SEARCH_STATE (index)) -> search_pattern) != 0)); +} + +unsigned int +OS_directory_open (const char * search_pattern) +{ + unsigned int index = (allocate_dir_search_state (search_pattern)); + dir_search_state * s = (REFERENCE_DIR_SEARCH_STATE (index)); + (s -> handle) = HDIR_CREATE; + (s -> count) = 1; + XTD_API_CALL + (dos_find_first, + (((char *) (s -> search_pattern)), (& (s -> handle)), FILE_ANY, + (& (s -> info)), (sizeof (s -> info)), (& (s -> count)), FIL_STANDARD), + { + if (rc == ERROR_NO_MORE_FILES) + { + (s -> count) = 0; + goto done; + } + }); + done: + return (index); +} + +static void +dir_find_next (dir_search_state * s) +{ + (s -> count) = 1; + XTD_API_CALL + (dos_find_next, + ((s -> handle), (& (s -> info)), (sizeof (s -> info)), (& (s -> count))), + { + if (rc == ERROR_NO_MORE_FILES) + { + (s -> count) = 0; + return; + } + }); +} + +static const char * +dir_current_name (dir_search_state * s) +{ + static char result [CCHMAXPATH]; + strcpy (result, ((s -> info) . achName)); + dir_find_next (s); + return (result); +} + +const char * +OS_directory_read (unsigned int index) +{ + dir_search_state * s = (REFERENCE_DIR_SEARCH_STATE (index)); + return (((s -> count) == 0) ? 0 : (dir_current_name (s))); +} + +const char * +OS_directory_read_matching (unsigned int index, const char * prefix) +{ + dir_search_state * s = (REFERENCE_DIR_SEARCH_STATE (index)); + unsigned int n = (strlen (prefix)); + while (1) + { + if ((s -> count) == 0) + return (0); + if ((strnicmp (((s -> info) . achName), prefix, n)) == 0) + return (dir_current_name (s)); + dir_find_next (s); + } +} + +void +OS_directory_close (unsigned int index) +{ + dir_search_state * s = (REFERENCE_DIR_SEARCH_STATE (index)); + STD_API_CALL (dos_find_close, (s -> handle)); + DEALLOCATE_DIR_SEARCH_STATE (s); +} + +static const char * +filename_extension (const char * filename) +{ + const char * start; + const char * period; + start = (strrchr (filename, '\\')); + start = ((start == 0) ? filename : (start + 1)); + period = (strrchr (start, '.')); + return ((period == 0) ? (filename + (strlen (filename))) : period); +} + +static const char * +make_pathname (const char * directory, const char * name) +{ + unsigned int dirlen = (strlen (directory)); + unsigned int namlen = (strlen (name)); + char * result = (OS_malloc (dirlen + namlen + 2)); + strcpy (result, directory); + if ((dirlen > 0) && ((result [dirlen - 1]) != '\\')) + strcat (result, "\\"); + strcat (result, name); + return (result); +} + +char * +OS2_remove_trailing_backslash (const char * filename) +{ + static char result [CCHMAXPATH]; + unsigned int len = (strlen (filename)); + if ((len == 0) || ((filename [len - 1]) != '\\')) + return ((char *) filename); + FASTCOPY (filename, result, (len - 1)); + (result [len - 1]) = '\0'; + return (result); +} diff --git a/v7/src/microcode/os2io.c b/v7/src/microcode/os2io.c new file mode 100644 index 000000000..158432682 --- /dev/null +++ b/v7/src/microcode/os2io.c @@ -0,0 +1,316 @@ +/* -*-C-*- + +$Id: os2io.c,v 1.1 1994/11/28 03:42:57 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" + +extern void add_reload_cleanup (void (*) (void)); +extern void OS2_initialize_console_channel (Tchannel); +extern void OS2_initialize_pipe_channel (Tchannel); + +static enum channel_type handle_channel_type (LHANDLE); + +size_t OS_channel_table_size; +struct channel * OS2_channel_table; +Tchannel * OS2_channel_pointer_table; +const int OS_have_select_p = 0; + +void +OS2_initialize_channels (void) +{ + OS_channel_table_size = (OS2_MAX_FILE_HANDLES ()); + OS2_channel_table = + (OS_malloc (OS_channel_table_size * (sizeof (struct channel)))); + OS2_channel_pointer_table = + (OS_malloc (OS_channel_table_size * (sizeof (Tchannel)))); + { + Tchannel channel; + for (channel = 0; (channel < OS_channel_table_size); channel += 1) + { + (CHANNEL_OPEN (channel)) = 0; + (OS2_channel_pointer_table [channel]) = channel; + } + } + add_reload_cleanup (OS2_channel_close_all_noerror); + SET_MSG_TYPE_LENGTH (mt_readahead, sm_readahead_t); + SET_MSG_TYPE_LENGTH (mt_readahead_ack, sm_readahead_ack_t); +} + +void +OS2_reset_channels (void) +{ + OS_free (OS2_channel_table); + OS2_channel_table = 0; + OS_channel_table_size = 0; +} + +void +OS2_channel_operation (Tchannel channel, chop_t operation, + choparg_t arg1, choparg_t arg2, choparg_t arg3) +{ + ((* (CHANNEL_OPERATOR (channel))) (channel, operation, arg1, arg2, arg3)); +} + +Tchannel +OS2_make_channel (LHANDLE handle, unsigned int mode) +{ + Tchannel channel = 0; + enum channel_type type; + transaction_begin (); + OS2_handle_close_on_abort (handle); + while (1) + { + if (channel == OS_channel_table_size) + OS2_error_out_of_channels (); + if (! (CHANNEL_OPEN (channel))) + break; + channel += 1; + } + type = (handle_channel_type (handle)); + (CHANNEL_HANDLE (channel)) = handle; + (CHANNEL_TYPE (channel)) = type; + (CHANNEL_OPEN (channel)) = 1; + (CHANNEL_INTERNAL (channel)) = 0; + (CHANNEL_NONBLOCKING (channel)) = 0; + (CHANNEL_INPUTP (channel)) = ((mode & CHANNEL_READ) != 0); + (CHANNEL_OUTPUTP (channel)) = ((mode & CHANNEL_WRITE) != 0); + (CHANNEL_OPERATOR (channel)) = 0; + switch (type) + { + case channel_type_console: + OS2_initialize_console_channel (channel); + break; + case channel_type_unnamed_pipe: + OS2_initialize_pipe_channel (channel); + break; + } + transaction_commit (); + return (channel); +} + +static enum channel_type +handle_channel_type (LHANDLE handle) +{ + /* **** For now, limit channel types to those that we know how to + handle in a reasonable way. Later we can add other types if + needed. However, we probably won't need other types since pipes + and files are sufficient to do nearly anything, and the console + will be flushed when the PM support is installed. */ + ULONG type; + ULONG flags; + if ((dos_query_h_type (handle, (&type), (&flags))) == NO_ERROR) + switch (type & 0xff) + { + case FHT_DISKFILE: + return (channel_type_file); + case FHT_CHRDEV: + if ((flags & 0x3) != 0) + return (channel_type_console); + else if ((flags & 0x4) != 0) + /* return (channel_type_null); */ + break; + else if ((flags & 0x8) != 0) + /* return (channel_type_clock); */ + break; + else + /* return (channel_type_character_device); */ + break; + case FHT_PIPE: + { + APIRET rc = (dos_query_n_p_h_state (handle, (&flags))); + if ((rc == NO_ERROR) || (rc == ERROR_PIPE_NOT_CONNECTED)) + /* return (channel_type_named_pipe); */ + break; + else + return (channel_type_unnamed_pipe); + } + } + OS2_error_anonymous (); + return (channel_type_unknown); +} + +void +OS_channel_close (Tchannel channel) +{ + if (! (CHANNEL_INTERNAL (channel))) + { + if (CHANNEL_ABSTRACT_P (channel)) + OS2_channel_operation (channel, chop_close, 0, 0, 0); + else + STD_API_CALL (dos_close, (CHANNEL_HANDLE (channel))); + (CHANNEL_OPEN (channel)) = 0; + } +} + +void +OS2_channel_close_all_noerror (void) +{ + Tchannel channel; + for (channel = 0; (channel < OS_channel_table_size); channel += 1) + if (CHANNEL_OPEN (channel)) + OS_channel_close_noerror (channel); +} + +void +OS_channel_close_noerror (Tchannel channel) +{ + transaction_begin (); + OS2_ignore_errors (); + OS_channel_close (channel); + transaction_commit (); +} + +static void +OS_channel_close_on_abort_1 (void * cp) +{ + OS_channel_close_noerror (* ((Tchannel *) cp)); +} + +void +OS_channel_close_on_abort (Tchannel channel) +{ + Tchannel * cp = (dstack_alloc (sizeof (Tchannel))); + (*cp) = (channel); + transaction_record_action (tat_abort, OS_channel_close_on_abort_1, cp); +} + +static void +OS2_handle_close_on_abort_1 (void * hp) +{ + (void) dos_close (* ((LHANDLE *) hp)); +} + +void +OS2_handle_close_on_abort (LHANDLE h) +{ + LHANDLE * hp = (dstack_alloc (sizeof (LHANDLE))); + (*hp) = h; + transaction_record_action (tat_abort, OS2_handle_close_on_abort_1, hp); +} + +int +OS_channel_open_p (Tchannel channel) +{ + return (CHANNEL_OPEN (channel)); +} + +enum channel_type +OS_channel_type (Tchannel channel) +{ + return (CHANNEL_TYPE (channel)); +} + +long +OS_channel_read (Tchannel channel, void * buffer, size_t nbytes) +{ + long n; + if (nbytes == 0) + return (0); + if (CHANNEL_ABSTRACT_P (channel)) + OS2_channel_operation (channel, chop_read, + ((choparg_t) buffer), + ((choparg_t) nbytes), + ((choparg_t) (& n))); + else + STD_API_CALL + (dos_read, ((CHANNEL_HANDLE (channel)), buffer, nbytes, + ((ULONG *) (& n)))); + return (n); +} + +long +OS_channel_write (Tchannel channel, const void * buffer, size_t nbytes) +{ + long n; + if (nbytes == 0) + return (0); + if (CHANNEL_ABSTRACT_P (channel)) + OS2_channel_operation (channel, + chop_write, + ((choparg_t) buffer), + ((choparg_t) nbytes), + ((choparg_t) (& n))); + else + STD_API_CALL + (dos_write, ((CHANNEL_HANDLE (channel)), ((void *) buffer), nbytes, + ((ULONG *) (& n)))); + return (n); +} + +int +OS_channel_nonblocking_p (Tchannel channel) +{ + return (CHANNEL_NONBLOCKING (channel)); +} + +void +OS_channel_nonblocking (Tchannel channel) +{ + (CHANNEL_NONBLOCKING (channel)) = 1; +} + +void +OS_channel_blocking (Tchannel channel) +{ + (CHANNEL_NONBLOCKING (channel)) = 0; +} + +size_t +OS_channel_read_load_file (Tchannel channel, void * buffer, size_t nbytes) +{ + ULONG nread; + if ((dos_read ((CHANNEL_HANDLE (channel)), buffer, nbytes, (&nread))) != 0) + return (0); + return (nread); +} + +size_t +OS_channel_write_dump_file (Tchannel channel, + const void * buffer, + size_t nbytes) +{ + ULONG nwrite; + if ((dos_write + ((CHANNEL_HANDLE (channel)), ((void *) buffer), nbytes, (&nwrite))) + != 0) + return (0); + return (nwrite); +} + +void +OS_channel_write_string (Tchannel channel, const char * string) +{ + unsigned long length = (strlen (string)); + if ((OS_channel_write (channel, string, length)) != length) + OS2_error_anonymous (); +} diff --git a/v7/src/microcode/os2io.h b/v7/src/microcode/os2io.h new file mode 100644 index 000000000..8e39d163a --- /dev/null +++ b/v7/src/microcode/os2io.h @@ -0,0 +1,100 @@ +/* -*-C-*- + +$Id: os2io.h,v 1.1 1994/11/28 03:42:58 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#ifndef SCM_OS2IO_H +#define SCM_OS2IO_H + +#include "osio.h" + +typedef enum +{ + chop_close, + chop_read, + chop_write, + chop_input_buffered, + chop_input_flush, + chop_output_cooked, + chop_output_flush, + chop_output_drain +} chop_t; + +typedef void * choparg_t; +typedef void (* channel_op_t) + (Tchannel, chop_t, choparg_t, choparg_t, choparg_t); + +struct channel +{ + LHANDLE handle; + channel_op_t operator; + void * operator_context; + enum channel_type type; + unsigned int open : 1; + unsigned int internal : 1; + unsigned int nonblocking : 1; + unsigned int inputp : 1; + unsigned int outputp : 1; +}; + +#define _CHANNEL(c) (OS2_channel_table [(c)]) +#define CHANNEL_POINTER(c) (& (OS2_channel_pointer_table [(c)])) +#define CHANNEL_HANDLE(c) ((_CHANNEL (c)) . handle) +#define CHANNEL_OPERATOR(c) ((_CHANNEL (c)) . operator) +#define CHANNEL_OPERATOR_CONTEXT(c) ((_CHANNEL (c)) . operator_context) +#define CHANNEL_TYPE(c) ((_CHANNEL (c)) . type) +#define CHANNEL_OPEN(c) ((_CHANNEL (c)) . open) +#define CHANNEL_INTERNAL(c) ((_CHANNEL (c)) . internal) +#define CHANNEL_NONBLOCKING(c) ((_CHANNEL (c)) . nonblocking) +#define CHANNEL_INPUTP(c) ((_CHANNEL (c)) . inputp) +#define CHANNEL_OUTPUTP(c) ((_CHANNEL (c)) . outputp) + +#define CHANNEL_ABSTRACT_P(c) ((CHANNEL_OPERATOR (c)) != 0) + +#define channel_type_console channel_type_os2_console +#define channel_type_unnamed_pipe channel_type_os2_unnamed_pipe +#define channel_type_named_pipe channel_type_os2_named_pipe + +/* Channel modes: */ +#define CHANNEL_READ 1 +#define CHANNEL_WRITE 2 + +extern struct channel * OS2_channel_table; +extern Tchannel * OS2_channel_pointer_table; +extern Tchannel OS2_make_channel (LHANDLE, unsigned int); +extern void OS2_channel_close_all_noerror (void); +extern void OS_channel_close_on_abort (Tchannel); +extern void OS2_handle_close_on_abort (LHANDLE); +extern void OS2_channel_operation + (Tchannel, chop_t, choparg_t, choparg_t, choparg_t); + +#endif /* SCM_OS2IO_H */ diff --git a/v7/src/microcode/os2msg.c b/v7/src/microcode/os2msg.c new file mode 100644 index 000000000..990a80cc8 --- /dev/null +++ b/v7/src/microcode/os2msg.c @@ -0,0 +1,506 @@ +/* -*-C-*- + +$Id: os2msg.c,v 1.1 1994/11/28 03:42:58 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +/* Master Message Queue */ + +#include "os2.h" + +static qid_t allocate_qid (void); +static void OS2_initialize_message_lengths (void); +static void read_and_dispatch_nonblocking (tqueue_t *); +static void read_and_dispatch_one_blocking (tqueue_t *); +static void write_subqueue (msg_t *); +static msg_t * read_subqueue (qid_t); +static int subqueue_emptyp (qid_t); +static int read_tqueue (tqueue_t *, int); +static void write_tqueue (tqueue_t *, msg_t *); +static int read_std_tqueue (tqueue_t *, int); +static void write_std_tqueue (tqueue_t *, msg_t *); +static tqueue_t * make_scm_tqueue (void); +static int read_scm_tqueue (tqueue_t *, int); +static void write_scm_tqueue (tqueue_t *, msg_t *); +static void process_interrupt_messages (void); +static int read_pm_tqueue (tqueue_t *, int); +static void write_pm_tqueue (tqueue_t *, msg_t *); + +typedef struct msg_list_s +{ + msg_t * message; + struct msg_list_s * next; +} msg_list_t; + +typedef struct +{ + unsigned int allocatedp : 1; /* queue allocated? */ + unsigned int openp : 1; /* queue open? */ + qid_t twin; /* other end of connection */ + tqueue_t * tqueue; /* thread queue for reception */ + msg_list_t * subqueue_head; /* head of receiving subqueue */ + msg_list_t * subqueue_tail; /* tail of receiving subqueue */ +} iqid_t; + +static iqid_t queue_array [QID_MAX + 1]; +static HMTX qid_lock; + +tqueue_t * OS2_scheme_tqueue; +static qid_t OS2_interrupt_qid_local; +qid_t OS2_interrupt_qid; + +#define _QID(q) (queue_array [(q)]) +#define QID_ALLOCATEDP(q) ((_QID (q)) . allocatedp) +#define QID_TWIN(q) ((_QID (q)) . twin) +#define QID_TQUEUE(q) ((_QID (q)) . tqueue) +#define QID_SUBQUEUE_HEAD(q) ((_QID (q)) . subqueue_head) +#define QID_SUBQUEUE_TAIL(q) ((_QID (q)) . subqueue_tail) + +#define MSG_QUEUE_TYPE(m) 0 +#define MSG_QUEUE_PRIORITY(m) 0 + +void +OS2_initialize_message_queues (void) +{ + { + qid_t qid = 0; + while (1) + { + (QID_ALLOCATEDP (qid)) = 0; + (QID_TQUEUE (qid)) = 0; + (QID_TWIN (qid)) = QID_NONE; + (QID_SUBQUEUE_HEAD (qid)) = 0; + (QID_SUBQUEUE_TAIL (qid)) = 0; + if (qid == QID_MAX) + break; + qid += 1; + } + } + OS2_initialize_message_lengths (); + SET_MSG_TYPE_LENGTH (mt_console_interrupt, sm_console_interrupt_t); + SET_MSG_TYPE_LENGTH (mt_timer_event, sm_timer_event_t); + qid_lock = (OS2_create_mutex_semaphore ()); + OS2_scheme_tqueue = (make_scm_tqueue ()); + OS2_make_qid_pair ((&OS2_interrupt_qid_local), (&OS2_interrupt_qid)); + OS2_open_qid (OS2_interrupt_qid_local, OS2_scheme_tqueue); +} + +void +OS2_make_qid_pair (qid_t * pq1, qid_t * pq2) +{ + qid_t q1 = (allocate_qid ()); + qid_t q2 = (allocate_qid ()); + (QID_TWIN (q1)) = q2; + (QID_TWIN (q2)) = q1; + (*pq1) = q1; + (*pq2) = q2; +} + +static qid_t +allocate_qid (void) +{ + unsigned int qid = 0; + OS2_request_mutex_semaphore (qid_lock); + while (1) + { + if ((QID_ALLOCATEDP (qid)) == 0) + break; + if (qid == QID_MAX) + OS2_logic_error ("No more QIDs available."); + qid += 1; + } + (QID_ALLOCATEDP (qid)) = 1; + (QID_TQUEUE (qid)) = 0; + (QID_TWIN (qid)) = QID_NONE; + (QID_SUBQUEUE_HEAD (qid)) = 0; + (QID_SUBQUEUE_TAIL (qid)) = 0; + OS2_release_mutex_semaphore (qid_lock); + return (qid); +} + +void +OS2_open_qid (qid_t qid, tqueue_t * tqueue) +{ + if ((QID_TQUEUE (qid)) != 0) + OS2_logic_error ("Reopening already open QID."); + if (tqueue == 0) + OS2_logic_error ("Null tqueue passed to OS2_open_qid."); + (QID_TQUEUE (qid)) = tqueue; +} + +int +OS2_qid_openp (qid_t qid) +{ + return ((QID_TQUEUE (qid)) != 0); +} + +void +OS2_close_qid (qid_t qid) +{ + { + msg_list_t * elt = (QID_SUBQUEUE_HEAD (qid)); + while (elt != 0) + { + msg_list_t * next = (elt -> next); + OS_free (elt); + elt = next; + } + } + (QID_SUBQUEUE_HEAD (qid)) = 0; + (QID_SUBQUEUE_TAIL (qid)) = 0; + (QID_TQUEUE (qid)) = 0; + OS2_request_mutex_semaphore (qid_lock); + { + qid_t twin = (QID_TWIN (qid)); + if (twin != QID_NONE) + { + (QID_TWIN (twin)) = QID_NONE; + (QID_TWIN (qid)) = QID_NONE; + } + } + (QID_ALLOCATEDP (qid)) = 0; + OS2_release_mutex_semaphore (qid_lock); +} + +/* Message Lengths */ + +#define MESSAGE_LENGTH(t) (message_lengths [(unsigned int) (t)]) +static msg_length_t message_lengths [MSG_TYPE_SUP]; + +static void +OS2_initialize_message_lengths (void) +{ + unsigned int type = 0; + while (1) + { + (MESSAGE_LENGTH (type)) = 0; + if (type == MSG_TYPE_MAX) + break; + type += 1; + } +} + +msg_length_t +OS2_message_type_length (msg_type_t type) +{ + msg_length_t length = (MESSAGE_LENGTH (type)); + if (length == 0) + OS2_logic_error ("Message type has unknown length."); + return (length); +} + +void +OS2_set_message_type_length (msg_type_t type, msg_length_t length) +{ + (MESSAGE_LENGTH (type)) = length; +} + +/* Message Transmission and Reception */ + +msg_t * +OS2_create_message (msg_type_t type) +{ + /* Do allocation carefully to prevent infinite loop when signalling + "out of memory" condition. */ + msg_t * message = + (malloc ((unsigned long) (OS2_message_type_length (type)))); + if (message == 0) + if ((type == mt_syscall_error) + && ((SM_SYSCALL_ERROR_CODE (message)) == ERROR_NOT_ENOUGH_MEMORY) + && ((SM_SYSCALL_ERROR_NAME (message)) == syscall_malloc)) + OS2_logic_error ("Unable to allocate memory for error message."); + else + OS2_error_system_call (ERROR_NOT_ENOUGH_MEMORY, syscall_malloc); + (_MSG_TYPE (message)) = ((unsigned char) type); + return (message); +} + +void +OS2_destroy_message (msg_t * message) +{ + OS_free ((void *) message); +} + +void +OS2_send_message (qid_t qid, msg_t * message) +{ + qid_t twin = (QID_TWIN (qid)); + tqueue_t * tqueue = (QID_TQUEUE (twin)); + if (tqueue == 0) + OS2_logic_error ("Write to closed QID."); + (MSG_SENDER (message)) = twin; + write_tqueue (tqueue, message); +} + +msg_t * +OS2_receive_message (qid_t qid, int blockp) +{ + tqueue_t * tqueue = (QID_TQUEUE (qid)); + msg_t * message; + while (1) + { + read_and_dispatch_nonblocking (tqueue); + if ((TQUEUE_TYPE (tqueue)) == tqt_scm) + { + process_interrupt_messages (); + deliver_pending_interrupts (); + } + message = (read_subqueue (qid)); + if ((!blockp) || (message != 0)) + break; + read_and_dispatch_one_blocking (tqueue); + } + return (message); +} + +static void +read_and_dispatch_nonblocking (tqueue_t * tqueue) +{ + while (read_tqueue (tqueue, 0)) + ; +} + +static void +read_and_dispatch_one_blocking (tqueue_t * tqueue) +{ + (void) read_tqueue (tqueue, 1); +} + +static void +write_subqueue (msg_t * message) +{ + qid_t qid = (MSG_SENDER (message)); + msg_list_t * tail = (QID_SUBQUEUE_TAIL (qid)); + msg_list_t * elt = (OS_malloc (sizeof (struct msg_list_s))); + (elt -> message) = message; + (elt -> next) = 0; + if (tail == 0) + (QID_SUBQUEUE_HEAD (qid)) = elt; + else + (tail -> next) = elt; + (QID_SUBQUEUE_TAIL (qid)) = elt; +} + +static msg_t * +read_subqueue (qid_t qid) +{ + msg_list_t * head = (QID_SUBQUEUE_HEAD (qid)); + if (head == 0) + return (0); + { + msg_t * message = (head -> message); + (QID_SUBQUEUE_HEAD (qid)) = (head -> next); + if ((head -> next) == 0) + (QID_SUBQUEUE_TAIL (qid)) = 0; + OS_free (head); + return (message); + } +} + +static int +subqueue_emptyp (qid_t qid) +{ + return ((QID_SUBQUEUE_HEAD (qid)) == 0); +} + +static int +read_tqueue (tqueue_t * tqueue, int blockp) +{ + switch (TQUEUE_TYPE (tqueue)) + { + case tqt_std: + return (read_std_tqueue (tqueue, blockp)); + case tqt_scm: + return (read_scm_tqueue (tqueue, blockp)); + case tqt_pm: + return (read_pm_tqueue (tqueue, blockp)); + } +} + +static void +write_tqueue (tqueue_t * tqueue, msg_t * message) +{ + switch (TQUEUE_TYPE (tqueue)) + { + case tqt_std: + write_std_tqueue (tqueue, message); + break; + case tqt_scm: + write_scm_tqueue (tqueue, message); + break; + case tqt_pm: + write_pm_tqueue (tqueue, message); + break; + } +} + +typedef struct +{ + tqueue_type_t type; + HQUEUE queue; /* queue */ + HEV event; /* associated event semaphore */ +} std_tqueue_t; +#define STD_TQUEUE_QUEUE(q) (((std_tqueue_t *) (q)) -> queue) +#define STD_TQUEUE_EVENT(q) (((std_tqueue_t *) (q)) -> event) + +tqueue_t * +OS2_make_std_tqueue (void) +{ + tqueue_t * tqueue = (OS_malloc (sizeof (std_tqueue_t))); + (TQUEUE_TYPE (tqueue)) = tqt_std; + (STD_TQUEUE_QUEUE (tqueue)) = (OS2_create_queue (QUE_FIFO)); + (STD_TQUEUE_EVENT (tqueue)) = (OS2_create_event_semaphore ()); + return (tqueue); +} + +static int +read_std_tqueue (tqueue_t * tqueue, int blockp) +{ + ULONG type; + ULONG length; + PVOID data; + msg_t * message; + const char * s = "Non-message read from message queue."; + + if (!OS2_read_queue ((STD_TQUEUE_QUEUE (tqueue)), + (&type), + (&length), + (&data), + (blockp ? NULLHANDLE : (STD_TQUEUE_EVENT (tqueue))))) + return (0); + if (length < (sizeof (msg_t))) + OS2_logic_error (s); + message = ((msg_t *) data); + if ((type != 0) || (length != (MSG_LENGTH (message)))) + OS2_logic_error (s); + write_subqueue (message); + return (1); +} + +static void +write_std_tqueue (tqueue_t * tqueue, msg_t * message) +{ + OS2_write_queue ((STD_TQUEUE_QUEUE (tqueue)), + 0, + (MSG_LENGTH (message)), + ((PVOID) message), + 0); +} + +static tqueue_t * +make_scm_tqueue (void) +{ + tqueue_t * tqueue = (OS2_make_std_tqueue ()); + (TQUEUE_TYPE (tqueue)) = tqt_scm; + return (tqueue); +} + +static int +read_scm_tqueue (tqueue_t * tqueue, int blockp) +{ + /* The handling of the interrupt bit is a little tricky. We clear + the bit, then handle any events, and finally clear the bit again. + If the bit is set during the second clear, we must loop since + another event might have been queued in the window between the + last read and the second clear -- and since we cleared the bit no + one else is going to look at the queue until another event comes + along. + + This code serves two purposes. First, this is the only way to + reliably clear the interrupt bit to avoid having an event stuck + in the queue and the Scheme thread not bothering to look. + Second, if we arrive at this read-dispatch loop by some means + other than the attention-interrupt mechanism, this will clear the + bit and thus avoid ever invoking the mechanism. */ + int result = 0; + (void) test_and_clear_attention_interrupt (); + do + if (read_std_tqueue (tqueue, blockp)) + { + result = 1; + /* If blockp was set, after we have read one message we read + any remaining messages in non-blocking mode. */ + blockp = 0; + } + while (test_and_clear_attention_interrupt ()); + return (result); +} + +static void +write_scm_tqueue (tqueue_t * tqueue, msg_t * message) +{ + write_std_tqueue (tqueue, message); + request_attention_interrupt (); +} + +void +OS2_handle_attention_interrupt (void) +{ + read_and_dispatch_nonblocking (QID_TQUEUE (OS2_interrupt_qid_local)); + process_interrupt_messages (); +} + +static void +process_interrupt_messages (void) +{ + /* Reads all of the interrupts out of the interrupt queue, and sets + the corresponding bits in the interrupt word. */ + while (1) + { + msg_t * message = (read_subqueue (OS2_interrupt_qid_local)); + if (message == 0) + break; + switch (MSG_TYPE (message)) + { + case mt_console_interrupt: + tty_set_next_interrupt_char (SM_CONSOLE_INTERRUPT_CODE (message)); + break; + case mt_timer_event: + request_timer_interrupt (); + break; + default: + OS2_logic_error ("Illegal message type in interrupt queue."); + break; + } + OS2_destroy_message (message); + } +} + +static int +read_pm_tqueue (tqueue_t * tqueue, int blockp) +{ + return (0); +} + +static void +write_pm_tqueue (tqueue_t * tqueue, msg_t * message) +{ +} diff --git a/v7/src/microcode/os2msg.h b/v7/src/microcode/os2msg.h new file mode 100644 index 000000000..ac02bae56 --- /dev/null +++ b/v7/src/microcode/os2msg.h @@ -0,0 +1,120 @@ +/* -*-C-*- + +$Id: os2msg.h,v 1.1 1994/11/28 03:42:59 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#ifndef SCM_OS2MSG_H +#define SCM_OS2MSG_H + +typedef enum +{ + mt_readahead, + mt_readahead_ack, + mt_console_interrupt, + mt_error, + mt_kill_request, + mt_syscall_error, + mt_timer_event, + mt_supremum +} msg_type_t; +#define MSG_TYPE_SUP ((unsigned int) mt_supremum) +#define MSG_TYPE_MAX (MSG_TYPE_SUP - 1) + +typedef unsigned char qid_t; +#define QID_MAX (UCHAR_MAX - 1) +#define QID_NONE UCHAR_MAX + +typedef unsigned short msg_length_t; +#define MSG_LENGTH_MAX USHRT_MAX + +/* Fields of message header: + type: small integer classifying the type of message + sender: qid identifying the message sender (used for replies) + */ + +#define DECLARE_MSG_HEADER_FIELDS \ + unsigned char type; \ + qid_t sender + +typedef struct +{ + DECLARE_MSG_HEADER_FIELDS; +} msg_t; + +#define _MSG(m) ((msg_t *) (m)) +#define _MSG_TYPE(m) ((_MSG (m)) -> type) +#define MSG_TYPE(m) ((msg_type_t) (_MSG_TYPE (m))) +#define MSG_SENDER(m) ((_MSG (m)) -> sender) + +typedef enum +{ + tqt_std, + tqt_scm, + tqt_pm +} tqueue_type_t; + +typedef struct +{ + tqueue_type_t type; +} tqueue_t; +#define TQUEUE_TYPE(q) (((tqueue_t *) (q)) -> type) + +extern tqueue_t * OS2_scheme_tqueue; +extern qid_t OS2_interrupt_qid; + +extern void OS2_make_qid_pair (qid_t *, qid_t *); +extern void OS2_open_qid (qid_t, tqueue_t *); +extern int OS2_qid_openp (qid_t); +extern void OS2_close_qid (qid_t); +extern msg_length_t OS2_message_type_length (msg_type_t); +extern void OS2_set_message_type_length (msg_type_t, msg_length_t); +extern msg_t * OS2_create_message (msg_type_t); +extern void OS2_destroy_message (msg_t *); +extern void OS2_send_message (qid_t, msg_t *); +extern msg_t * OS2_receive_message (qid_t, int); +extern tqueue_t * OS2_make_std_tqueue (void); + +#define MSG_LENGTH(m) (OS2_message_type_length (MSG_TYPE (m))) + +#define SET_MSG_TYPE_LENGTH(t, s) \ + OS2_set_message_type_length ((t), (sizeof (s))) + +typedef struct +{ + DECLARE_MSG_HEADER_FIELDS; + int code; +} sm_console_interrupt_t; +#define SM_CONSOLE_INTERRUPT_CODE(m) (((sm_console_interrupt_t *) (m)) -> code) + +typedef msg_t sm_timer_event_t; + +#endif /* SCM_OS2MSG_H */ diff --git a/v7/src/microcode/os2pipe.c b/v7/src/microcode/os2pipe.c new file mode 100644 index 000000000..50bfa22ea --- /dev/null +++ b/v7/src/microcode/os2pipe.c @@ -0,0 +1,125 @@ +/* -*-C-*- + +$Id: os2pipe.c,v 1.1 1994/11/28 03:42:59 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" + +static void input_pipe_operator + (Tchannel, chop_t, choparg_t, choparg_t, choparg_t); +static void input_pipe_thread (void *); + +void +OS_make_pipe (Tchannel * readerp, Tchannel * writerp) +{ + HFILE hread; + HFILE hwrite; + STD_API_CALL (dos_create_pipe, ((&hread), (&hwrite), 4096)); + transaction_begin (); + OS2_handle_close_on_abort (hwrite); + (*readerp) = (OS2_make_channel (hread, CHANNEL_READ)); + transaction_commit (); + transaction_begin (); + OS_channel_close_on_abort (*readerp); + (*writerp) = (OS2_make_channel (hwrite, CHANNEL_WRITE)); + transaction_commit (); +} + +void +OS2_initialize_pipe_channel (Tchannel channel) +{ + if (CHANNEL_INPUTP (channel)) + { + channel_context_t * context = (OS2_make_channel_context ()); + (CHANNEL_OPERATOR_CONTEXT (channel)) = context; + OS2_open_qid ((CHANNEL_CONTEXT_READER_QID (context)), OS2_scheme_tqueue); + (void) OS2_beginthread + (input_pipe_thread, (CHANNEL_POINTER (channel)), 0); + (CHANNEL_OPERATOR (channel)) = input_pipe_operator; + } +} + +static void +input_pipe_operator (Tchannel channel, chop_t operation, + choparg_t arg1, choparg_t arg2, choparg_t arg3) +{ + switch (operation) + { + case chop_read: + (* ((long *) arg3)) + = (channel_thread_read (channel, ((char *) arg1), ((size_t) arg2))); + break; + case chop_close: + channel_thread_close (channel); + break; + default: + OS2_logic_error ("Unknown operation for input pipe."); + break; + } +} + +static void +input_pipe_thread (void * arg) +{ + Tchannel channel = (* ((Tchannel *) arg)); + LHANDLE handle = (CHANNEL_HANDLE (channel)); + channel_context_t * context = (CHANNEL_OPERATOR_CONTEXT (channel)); + qid_t qid = (CHANNEL_CONTEXT_WRITER_QID (context)); + OS2_open_qid (qid, (OS2_make_std_tqueue ())); + (void) OS2_thread_initialize (qid); + while (1) + { + msg_t * message = (OS2_make_readahead ()); + APIRET rc + = (dos_read (handle, + (SM_READAHEAD_DATA (message)), + (sizeof (SM_READAHEAD_DATA (message))), + (& (SM_READAHEAD_SIZE (message))))); + int eofp; + if (rc == NO_ERROR) + eofp = ((SM_READAHEAD_SIZE (message)) == 0); + else + { + OS2_destroy_message (message); + if (rc == ERROR_INVALID_HANDLE) + /* Handle was closed on us -- no need to do anything else. */ + break; + message = (OS2_make_syscall_error (rc, syscall_dos_read)); + eofp = (rc == ERROR_BROKEN_PIPE); + } + OS2_send_message (qid, message); + if (eofp) + break; + OS2_wait_for_readahead_ack (qid); + } + OS2_endthread (); +} diff --git a/v7/src/microcode/os2term.c b/v7/src/microcode/os2term.c new file mode 100644 index 000000000..c22a2dd1c --- /dev/null +++ b/v7/src/microcode/os2term.c @@ -0,0 +1,163 @@ +/* -*-C-*- + +$Id: os2term.c,v 1.1 1994/11/28 03:43:00 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" + +unsigned int +OS_terminal_get_ispeed (Tchannel channel) +{ + return (9600); +} + +unsigned int +OS_terminal_get_ospeed (Tchannel channel) +{ + return (9600); +} + +void +OS_terminal_set_ispeed (Tchannel channel, unsigned int baud) +{ +} + +void +OS_terminal_set_ospeed (Tchannel channel, unsigned int baud) +{ +} + +unsigned int +arg_baud_index (unsigned int argument) +{ + return (arg_nonnegative_integer (argument)); +} + +unsigned int +OS_baud_index_to_rate (unsigned int index) +{ + return (index); +} + +int +OS_baud_rate_to_index (unsigned int rate) +{ + return (rate); +} + +unsigned int +OS_terminal_state_size (void) +{ + return (0); +} + +void +OS_terminal_get_state (Tchannel channel, PTR statep) +{ +} + +void +OS_terminal_set_state (Tchannel channel, PTR statep) +{ +} + +int +OS_terminal_cooked_output_p (Tchannel channel) +{ + int flag; + OS2_channel_operation (channel, chop_output_cooked, + ((choparg_t) (-1)), ((choparg_t) (&flag)), 0); + return (flag); +} + +void +OS_terminal_raw_output (Tchannel channel) +{ + OS2_channel_operation (channel, chop_output_cooked, ((choparg_t) 0), 0, 0); +} + +void +OS_terminal_cooked_output (Tchannel channel) +{ + OS2_channel_operation (channel, chop_output_cooked, ((choparg_t) 1), 0, 0); +} + +int +OS_terminal_buffered_p (Tchannel channel) +{ + int flag; + OS2_channel_operation (channel, chop_input_buffered, + ((choparg_t) (-1)), ((choparg_t) (&flag)), 0); + return (flag); +} + +void +OS_terminal_buffered (Tchannel channel) +{ + OS2_channel_operation (channel, chop_input_buffered, ((choparg_t) 0), 0, 0); +} + +void +OS_terminal_nonbuffered (Tchannel channel) +{ + OS2_channel_operation (channel, chop_input_buffered, ((choparg_t) 1), 0, 0); +} + +void +OS_terminal_flush_input (Tchannel channel) +{ + OS2_channel_operation (channel, chop_input_flush, 0, 0, 0); +} + +void +OS_terminal_flush_output (Tchannel channel) +{ + OS2_channel_operation (channel, chop_output_flush, 0, 0, 0); +} + +void +OS_terminal_drain_output (Tchannel channel) +{ + OS2_channel_operation (channel, chop_output_drain, 0, 0, 0); +} + +int +OS_job_control_p (void) +{ + return (0); +} + +int +OS_have_ptys_p (void) +{ + return (0); +} diff --git a/v7/src/microcode/os2thrd.c b/v7/src/microcode/os2thrd.c new file mode 100644 index 000000000..d62f2f5e9 --- /dev/null +++ b/v7/src/microcode/os2thrd.c @@ -0,0 +1,250 @@ +/* -*-C-*- + +$Id: os2thrd.c,v 1.1 1994/11/28 03:43:00 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" +#include "prims.h" +#include "errors.h" + +TID +OS2_beginthread (thread_procedure_t procedure, + void * argument, + unsigned int stack_size) +{ + ULONG ss + = ((stack_size < 0x2000) + ? 0x2000 + : ((stack_size + 0xfff) & (~0xfff))); +#ifdef __IBMC__ + int result = (_beginthread (procedure, 0, ss, argument)); + if (result < 0) + OS2_error_system_call (ERROR_MAX_THRDS_REACHED, syscall_beginthread); + return (result); +#else /* not __IBMC__ */ + TID tid; + STD_API_CALL (dos_create_thread, + ((&tid), ((PFNTHREAD) procedure), ((ULONG) argument), 0, ss)); + return (tid); +#endif /* not __IBMC__ */ +} + +void +OS2_endthread (void) +{ +#ifdef __IBMC__ + _endthread (); +#else + dos_exit (EXIT_THREAD, 0); +#endif +} + +void +OS2_kill_thread (TID tid) +{ + STD_API_CALL (dos_kill_thread, (tid)); +} + +#ifndef __IBMC__ +#define MAX_TID 999 +static thread_store_t * thread_store_array [MAX_TID + 1]; + +thread_store_t ** +OS2_threadstore (void) +{ + PTIB ptib; + PPIB ppib; + TID tid; + STD_API_CALL (dos_get_info_blocks, ((&ptib), (&ppib))); + tid = (ptib -> tib_ptib2 -> tib2_ultid); + if (tid > MAX_TID) + OS2_logic_error ("Unexpectedly large TID."); + return (& (thread_store_array [tid])); +} +#endif + +PID OS2_scheme_pid; +TID OS2_scheme_tid; + +static void thread_initialize_1 (qid_t); +static int thread_initialize_error_hook (void); +static void restore_errors (void *); +static void signal_error (msg_t *); +static void ignore_error (msg_t *); +static void send_error (msg_t *); + +void +OS2_initialize_scheme_thread (void) +{ + SET_MSG_TYPE_LENGTH (mt_syscall_error, sm_syscall_error_t); + SET_MSG_TYPE_LENGTH (mt_error, sm_error_t); + SET_MSG_TYPE_LENGTH (mt_kill_request, sm_kill_request_t); + { + PTIB ptib; + PPIB ppib; + STD_API_CALL (dos_get_info_blocks, ((&ptib), (&ppib))); + OS2_scheme_pid = (ppib -> pib_ulpid); + OS2_scheme_tid = (ptib -> tib_ptib2 -> tib2_ultid); + } + thread_initialize_1 (QID_NONE); + (THREAD_ERROR_HOOK ()) = signal_error; +} + +int +OS2_thread_initialize (qid_t error_qid) +{ + thread_initialize_1 (error_qid); + return (thread_initialize_error_hook ()); +} + +static void +thread_initialize_1 (qid_t error_qid) +{ + (* (OS2_threadstore ())) = (OS_malloc (sizeof (thread_store_t))); + (THREAD_ERROR_QUEUE ()) = error_qid; +} + +static int +thread_initialize_error_hook (void) +{ + (THREAD_ERROR_HOOK ()) = send_error; + return (setjmp (THREAD_ERROR_RESTART ())); +} + +int +OS2_error_message_p (msg_t * message) +{ + msg_type_t type = (MSG_TYPE (message)); + return ((type == mt_syscall_error) || (type == mt_error)); +} + +void +OS2_handle_error_message (msg_t * message) +{ + (* (THREAD_ERROR_HOOK ())) (message); +} + +void +OS2_ignore_errors (void) +{ + error_hook_t * hp = (dstack_alloc (sizeof (error_hook_t))); + (*hp) = (THREAD_ERROR_HOOK ()); + transaction_record_action (tat_always, restore_errors, hp); + (THREAD_ERROR_HOOK ()) = ignore_error; +} + +static void +restore_errors (void * hp) +{ + (THREAD_ERROR_HOOK ()) = (* ((error_hook_t *) hp)); +} + +void +OS2_error_system_call (int code, enum syscall_names name) +{ + OS2_handle_error_message (OS2_make_syscall_error (code, name)); +} + +void +OS2_error_anonymous (void) +{ + OS2_handle_error_message (OS2_make_error (ERR_EXTERNAL_RETURN)); +} + +void +OS2_error_unimplemented_primitive (void) +{ + OS2_handle_error_message (OS2_make_error (ERR_UNDEFINED_PRIMITIVE)); +} + +void +OS2_error_out_of_channels (void) +{ + OS2_handle_error_message (OS2_make_error (ERR_OUT_OF_FILE_HANDLES)); +} + +static void +signal_error (msg_t * message) +{ + switch (MSG_TYPE (message)) + { + case mt_syscall_error: + { + int code = (SM_SYSCALL_ERROR_CODE (message)); + enum syscall_names name = (SM_SYSCALL_ERROR_NAME (message)); + OS2_destroy_message (message); + error_system_call (code, name); + } + break; + case mt_error: + { + long code = (SM_ERROR_CODE (message)); + OS2_destroy_message (message); + signal_error_from_primitive (code); + } + break; + default: + OS2_logic_error ("Non-error message passed to signal_error."); + break; + } +} + +static void +ignore_error (msg_t * message) +{ +} + +static void +send_error (msg_t * message) +{ + if ((THREAD_ERROR_QUEUE ()) == QID_NONE) + OS2_logic_error ("send_error called when no error queue defined."); + OS2_send_message ((THREAD_ERROR_QUEUE ()), message); + longjmp ((THREAD_ERROR_RESTART ()), 1); +} + +msg_t * +OS2_make_syscall_error (int code, enum syscall_names name) +{ + msg_t * message = (OS2_create_message (mt_syscall_error)); + (SM_SYSCALL_ERROR_CODE (message)) = code; + (SM_SYSCALL_ERROR_NAME (message)) = name; + return (message); +} + +msg_t * +OS2_make_error (long code) +{ + msg_t * message = (OS2_create_message (mt_error)); + (SM_ERROR_CODE (message)) = code; + return (message); +} diff --git a/v7/src/microcode/os2thrd.h b/v7/src/microcode/os2thrd.h new file mode 100644 index 000000000..a8af33d58 --- /dev/null +++ b/v7/src/microcode/os2thrd.h @@ -0,0 +1,94 @@ +/* -*-C-*- + +$Id: os2thrd.h,v 1.1 1994/11/28 03:43:01 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#ifndef SCM_OS2THRD_H +#define SCM_OS2THRD_H + +typedef void (* thread_procedure_t) (void *); +typedef void (* error_hook_t) (msg_t *); + +typedef struct +{ + error_hook_t error_hook; + jmp_buf error_restart; + qid_t error_queue; +} thread_store_t; +#define THREAD_ERROR_HOOK() ((* (OS2_threadstore ())) -> error_hook) +#define THREAD_ERROR_RESTART() ((* (OS2_threadstore ())) -> error_restart) +#define THREAD_ERROR_QUEUE() ((* (OS2_threadstore ())) -> error_queue) + +typedef struct +{ + DECLARE_MSG_HEADER_FIELDS; + int code; + enum syscall_names name; +} sm_syscall_error_t; +#define SM_SYSCALL_ERROR_CODE(m) (((sm_syscall_error_t *) (m)) -> code) +#define SM_SYSCALL_ERROR_NAME(m) (((sm_syscall_error_t *) (m)) -> name) + +typedef struct +{ + DECLARE_MSG_HEADER_FIELDS; + long code; +} sm_error_t; +#define SM_ERROR_CODE(m) (((sm_error_t *) (m)) -> code) + +typedef msg_t sm_kill_request_t; +#define OS2_make_kill_request() OS2_create_message (mt_kill_request) + +extern TID OS2_beginthread (thread_procedure_t, void *, unsigned int); +extern void OS2_endthread (void); +extern void OS2_kill_thread (TID); + +#ifdef __IBMC__ +#define OS2_threadstore() ((thread_store_t **) (_threadstore ())) +#else +extern thread_store_t ** OS2_threadstore (void); +#endif + +extern PID OS2_scheme_pid; +extern TID OS2_scheme_tid; + +extern int OS2_thread_initialize (qid_t); +extern int OS2_error_message_p (msg_t *); +extern void OS2_handle_error_message (msg_t *); +extern void OS2_ignore_errors (void); +extern void OS2_error_system_call (int, enum syscall_names); +extern void OS2_error_anonymous (void); +extern void OS2_error_unimplemented_primitive (void); +extern void OS2_error_out_of_channels (void); +extern msg_t * OS2_make_syscall_error (int, enum syscall_names); +extern msg_t * OS2_make_error (long); + +#endif /* SCM_OS2THRD_H */ diff --git a/v7/src/microcode/os2top.c b/v7/src/microcode/os2top.c new file mode 100644 index 000000000..40c76a4cf --- /dev/null +++ b/v7/src/microcode/os2top.c @@ -0,0 +1,1557 @@ +/* -*-C-*- + +$Id: os2top.c,v 1.1 1994/11/28 03:43:01 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" +#include "ostop.h" +#include "option.h" + +extern void OS2_initialize_channels (void); +extern void OS2_initialize_channel_thread_messages (void); +extern void OS2_initialize_console (void); +extern void OS2_initialize_directory_reader (void); +extern void OS2_initialize_environment (void); +extern void OS2_initialize_keyboard_interrupts (void); +extern void OS2_initialize_message_queues (void); +extern void OS2_initialize_scheme_thread (void); +extern void OS2_initialize_tty (void); + +extern const char * OS_Name; +extern const char * OS_Variant; + +static const char * OS2_version_string (void); +static void initialize_locks (void); + +int +OS_under_emacs_p (void) +{ + return (option_emacs_subprocess); +} + +void +OS_initialize (void) +{ + transaction_initialize (); + initialize_locks (); + OS2_initialize_message_queues (); + OS2_initialize_scheme_thread (); + OS2_initialize_channels (); + OS2_initialize_channel_thread_messages (); + OS2_initialize_keyboard_interrupts (); + OS2_initialize_console (); + OS2_initialize_environment (); + OS2_initialize_directory_reader (); + OS2_initialize_tty (); + OS_Name = "OS/2"; + { + const char * version = (OS2_version_string ()); + OS_Variant = (OS_malloc ((strlen (OS_Name)) + (strlen (version)) + 2)); + sprintf (((char *) OS_Variant), "%s %s", OS_Name, version); + } + outf_console ("MIT Scheme running under %s\n", OS_Variant); + outf_flush_console (); +} + +static const char * +OS2_version_string (void) +{ + ULONG major = (OS2_system_variable (QSV_VERSION_MAJOR)); + ULONG minor = (OS2_system_variable (QSV_VERSION_MINOR)); + char revision = (OS2_system_variable (QSV_VERSION_REVISION)); + static char result [64]; + char sminor [16]; + char srev [2]; + if ((major == 20) && (minor == 30)) + { + major = 30; + minor = 0; + } + if ((minor < 10) && (minor != 0)) + sprintf (sminor, "0%d", minor); + else + sprintf (sminor, "%d", + (((minor < 100) && ((minor % 10) == 0)) ? (minor / 10) : minor)); + if (revision == '\0') + sprintf (srev, ""); + else + sprintf (srev, "%c", revision); + sprintf (result, "%d.%s%s", (major / 10), sminor, srev); + return (result); +} + +void +OS2_exit_scheme (int value) +{ + extern void OS2_kill_timer_thread (void); + OS2_kill_timer_thread (); + OS2_channel_close_all_noerror (); + exit (value); +} + +void +OS_reset (void) +{ + execute_reload_cleanups (); +} + +void +OS_quit (int code, int abnormal_p) +{ + outf_flush_console (); + OS_restore_external_state (); +} + +void +OS_save_external_state (void) +{ +} + +void +OS_save_internal_state (void) +{ +} + +void +OS_restore_internal_state (void) +{ +} + +void +OS_restore_external_state (void) +{ +} + +void +preserve_signal_mask (void) +{ +} + +void +block_signals (void) +{ +} + +void +unblock_signals (void) +{ +} + +void +OS_restartable_exit (void) +{ +} + +long +OS_set_trap_state (long arg) +{ + return (arg); +} + +#ifdef __IBMC__ +void +bcopy (const char * from, char * to, unsigned int n) +{ + FASTCOPY (from, to, n); +} +#endif + +static HMTX interrupt_registers_lock; + +static void +initialize_locks (void) +{ + interrupt_registers_lock = (OS2_create_mutex_semaphore ()); +} + +void +OS_grab_interrupt_registers (void) +{ + OS2_request_mutex_semaphore (interrupt_registers_lock); +} + +void +OS_release_interrupt_registers (void) +{ + OS2_release_mutex_semaphore (interrupt_registers_lock); +} + +/* Machine-generated procedure, do not edit: */ +enum syserr_names +OS_error_code_to_syserr (int code) +{ + switch (code) + { + case ERROR_INVALID_FUNCTION: return (syserr_invalid_function); + case ERROR_FILE_NOT_FOUND: return (syserr_file_not_found); + case ERROR_PATH_NOT_FOUND: return (syserr_path_not_found); + case ERROR_TOO_MANY_OPEN_FILES: return (syserr_too_many_open_files); + case ERROR_ACCESS_DENIED: return (syserr_access_denied); + case ERROR_INVALID_HANDLE: return (syserr_invalid_handle); + case ERROR_ARENA_TRASHED: return (syserr_arena_trashed); + case ERROR_NOT_ENOUGH_MEMORY: return (syserr_not_enough_memory); + case ERROR_INVALID_BLOCK: return (syserr_invalid_block); + case ERROR_BAD_ENVIRONMENT: return (syserr_bad_environment); + case ERROR_BAD_FORMAT: return (syserr_bad_format); + case ERROR_INVALID_ACCESS: return (syserr_invalid_access); + case ERROR_INVALID_DATA: return (syserr_invalid_data); + case ERROR_INVALID_DRIVE: return (syserr_invalid_drive); + case ERROR_CURRENT_DIRECTORY: return (syserr_current_directory); + case ERROR_NOT_SAME_DEVICE: return (syserr_not_same_device); + case ERROR_NO_MORE_FILES: return (syserr_no_more_files); + case ERROR_WRITE_PROTECT: return (syserr_write_protect); + case ERROR_BAD_UNIT: return (syserr_bad_unit); + case ERROR_NOT_READY: return (syserr_not_ready); + case ERROR_BAD_COMMAND: return (syserr_bad_command); + case ERROR_CRC: return (syserr_crc); + case ERROR_BAD_LENGTH: return (syserr_bad_length); + case ERROR_SEEK: return (syserr_seek); + case ERROR_NOT_DOS_DISK: return (syserr_not_dos_disk); + case ERROR_SECTOR_NOT_FOUND: return (syserr_sector_not_found); + case ERROR_OUT_OF_PAPER: return (syserr_out_of_paper); + case ERROR_WRITE_FAULT: return (syserr_write_fault); + case ERROR_READ_FAULT: return (syserr_read_fault); + case ERROR_GEN_FAILURE: return (syserr_gen_failure); + case ERROR_SHARING_VIOLATION: return (syserr_sharing_violation); + case ERROR_LOCK_VIOLATION: return (syserr_lock_violation); + case ERROR_WRONG_DISK: return (syserr_wrong_disk); + case ERROR_FCB_UNAVAILABLE: return (syserr_fcb_unavailable); + case ERROR_SHARING_BUFFER_EXCEEDED: return (syserr_sharing_buffer_exceeded); + case ERROR_CODE_PAGE_MISMATCHED: return (syserr_code_page_mismatched); + case ERROR_HANDLE_EOF: return (syserr_handle_eof); + case ERROR_HANDLE_DISK_FULL: return (syserr_handle_disk_full); + case ERROR_NOT_SUPPORTED: return (syserr_not_supported); + case ERROR_REM_NOT_LIST: return (syserr_rem_not_list); + case ERROR_DUP_NAME: return (syserr_dup_name); + case ERROR_BAD_NETPATH: return (syserr_bad_netpath); + case ERROR_NETWORK_BUSY: return (syserr_network_busy); + case ERROR_DEV_NOT_EXIST: return (syserr_dev_not_exist); + case ERROR_TOO_MANY_CMDS: return (syserr_too_many_cmds); + case ERROR_ADAP_HDW_ERR: return (syserr_adap_hdw_err); + case ERROR_BAD_NET_RESP: return (syserr_bad_net_resp); + case ERROR_UNEXP_NET_ERR: return (syserr_unexp_net_err); + case ERROR_BAD_REM_ADAP: return (syserr_bad_rem_adap); + case ERROR_PRINTQ_FULL: return (syserr_printq_full); + case ERROR_NO_SPOOL_SPACE: return (syserr_no_spool_space); + case ERROR_PRINT_CANCELLED: return (syserr_print_cancelled); + case ERROR_NETNAME_DELETED: return (syserr_netname_deleted); + case ERROR_NETWORK_ACCESS_DENIED: return (syserr_network_access_denied); + case ERROR_BAD_DEV_TYPE: return (syserr_bad_dev_type); + case ERROR_BAD_NET_NAME: return (syserr_bad_net_name); + case ERROR_TOO_MANY_NAMES: return (syserr_too_many_names); + case ERROR_TOO_MANY_SESS: return (syserr_too_many_sess); + case ERROR_SHARING_PAUSED: return (syserr_sharing_paused); + case ERROR_REQ_NOT_ACCEP: return (syserr_req_not_accep); + case ERROR_REDIR_PAUSED: return (syserr_redir_paused); + case ERROR_SBCS_ATT_WRITE_PROT: return (syserr_sbcs_att_write_prot); + case ERROR_SBCS_GENERAL_FAILURE: return (syserr_sbcs_general_failure); + case ERROR_XGA_OUT_MEMORY: return (syserr_xga_out_memory); + case ERROR_FILE_EXISTS: return (syserr_file_exists); + case ERROR_DUP_FCB: return (syserr_dup_fcb); + case ERROR_CANNOT_MAKE: return (syserr_cannot_make); + case ERROR_FAIL_I24: return (syserr_fail_i24); + case ERROR_OUT_OF_STRUCTURES: return (syserr_out_of_structures); + case ERROR_ALREADY_ASSIGNED: return (syserr_already_assigned); + case ERROR_INVALID_PASSWORD: return (syserr_invalid_password); + case ERROR_INVALID_PARAMETER: return (syserr_invalid_parameter); + case ERROR_NET_WRITE_FAULT: return (syserr_net_write_fault); + case ERROR_NO_PROC_SLOTS: return (syserr_no_proc_slots); + case ERROR_NOT_FROZEN: return (syserr_not_frozen); + case ERR_TSTOVFL: return (syserr_tstovfl); + case ERR_TSTDUP: return (syserr_tstdup); + case ERROR_NO_ITEMS: return (syserr_no_items); + case ERROR_INTERRUPT: return (syserr_interrupt); + case ERROR_DEVICE_IN_USE: return (syserr_device_in_use); + case ERROR_TOO_MANY_SEMAPHORES: return (syserr_too_many_semaphores); + case ERROR_EXCL_SEM_ALREADY_OWNED: return (syserr_excl_sem_already_owned); + case ERROR_SEM_IS_SET: return (syserr_sem_is_set); + case ERROR_TOO_MANY_SEM_REQUESTS: return (syserr_too_many_sem_requests); + case ERROR_INVALID_AT_INTERRUPT_TIME: return (syserr_invalid_at_interrupt_time); + case ERROR_SEM_OWNER_DIED: return (syserr_sem_owner_died); + case ERROR_SEM_USER_LIMIT: return (syserr_sem_user_limit); + case ERROR_DISK_CHANGE: return (syserr_disk_change); + case ERROR_DRIVE_LOCKED: return (syserr_drive_locked); + case ERROR_BROKEN_PIPE: return (syserr_broken_pipe); + case ERROR_OPEN_FAILED: return (syserr_open_failed); + case ERROR_BUFFER_OVERFLOW: return (syserr_buffer_overflow); + case ERROR_DISK_FULL: return (syserr_disk_full); + case ERROR_NO_MORE_SEARCH_HANDLES: return (syserr_no_more_search_handles); + case ERROR_INVALID_TARGET_HANDLE: return (syserr_invalid_target_handle); + case ERROR_PROTECTION_VIOLATION: return (syserr_protection_violation); + case ERROR_VIOKBD_REQUEST: return (syserr_viokbd_request); + case ERROR_INVALID_CATEGORY: return (syserr_invalid_category); + case ERROR_INVALID_VERIFY_SWITCH: return (syserr_invalid_verify_switch); + case ERROR_BAD_DRIVER_LEVEL: return (syserr_bad_driver_level); + case ERROR_CALL_NOT_IMPLEMENTED: return (syserr_call_not_implemented); + case ERROR_SEM_TIMEOUT: return (syserr_sem_timeout); + case ERROR_INSUFFICIENT_BUFFER: return (syserr_insufficient_buffer); + case ERROR_INVALID_NAME: return (syserr_invalid_name); + case ERROR_INVALID_LEVEL: return (syserr_invalid_level); + case ERROR_NO_VOLUME_LABEL: return (syserr_no_volume_label); + case ERROR_MOD_NOT_FOUND: return (syserr_mod_not_found); + case ERROR_PROC_NOT_FOUND: return (syserr_proc_not_found); + case ERROR_WAIT_NO_CHILDREN: return (syserr_wait_no_children); + case ERROR_CHILD_NOT_COMPLETE: return (syserr_child_not_complete); + case ERROR_DIRECT_ACCESS_HANDLE: return (syserr_direct_access_handle); + case ERROR_NEGATIVE_SEEK: return (syserr_negative_seek); + case ERROR_SEEK_ON_DEVICE: return (syserr_seek_on_device); + case ERROR_IS_JOIN_TARGET: return (syserr_is_join_target); + case ERROR_IS_JOINED: return (syserr_is_joined); + case ERROR_IS_SUBSTED: return (syserr_is_substed); + case ERROR_NOT_JOINED: return (syserr_not_joined); + case ERROR_NOT_SUBSTED: return (syserr_not_substed); + case ERROR_JOIN_TO_JOIN: return (syserr_join_to_join); + case ERROR_SUBST_TO_SUBST: return (syserr_subst_to_subst); + case ERROR_JOIN_TO_SUBST: return (syserr_join_to_subst); + case ERROR_SUBST_TO_JOIN: return (syserr_subst_to_join); + case ERROR_BUSY_DRIVE: return (syserr_busy_drive); + case ERROR_SAME_DRIVE: return (syserr_same_drive); + case ERROR_DIR_NOT_ROOT: return (syserr_dir_not_root); + case ERROR_DIR_NOT_EMPTY: return (syserr_dir_not_empty); + case ERROR_IS_SUBST_PATH: return (syserr_is_subst_path); + case ERROR_IS_JOIN_PATH: return (syserr_is_join_path); + case ERROR_PATH_BUSY: return (syserr_path_busy); + case ERROR_IS_SUBST_TARGET: return (syserr_is_subst_target); + case ERROR_SYSTEM_TRACE: return (syserr_system_trace); + case ERROR_INVALID_EVENT_COUNT: return (syserr_invalid_event_count); + case ERROR_TOO_MANY_MUXWAITERS: return (syserr_too_many_muxwaiters); + case ERROR_INVALID_LIST_FORMAT: return (syserr_invalid_list_format); + case ERROR_LABEL_TOO_LONG: return (syserr_label_too_long); + case ERROR_TOO_MANY_TCBS: return (syserr_too_many_tcbs); + case ERROR_SIGNAL_REFUSED: return (syserr_signal_refused); + case ERROR_DISCARDED: return (syserr_discarded); + case ERROR_NOT_LOCKED: return (syserr_not_locked); + case ERROR_BAD_THREADID_ADDR: return (syserr_bad_threadid_addr); + case ERROR_BAD_ARGUMENTS: return (syserr_bad_arguments); + case ERROR_BAD_PATHNAME: return (syserr_bad_pathname); + case ERROR_SIGNAL_PENDING: return (syserr_signal_pending); + case ERROR_UNCERTAIN_MEDIA: return (syserr_uncertain_media); + case ERROR_MAX_THRDS_REACHED: return (syserr_max_thrds_reached); + case ERROR_MONITORS_NOT_SUPPORTED: return (syserr_monitors_not_supported); + case ERROR_UNC_DRIVER_NOT_INSTALLED: return (syserr_unc_driver_not_installed); + case ERROR_LOCK_FAILED: return (syserr_lock_failed); + case ERROR_SWAPIO_FAILED: return (syserr_swapio_failed); + case ERROR_SWAPIN_FAILED: return (syserr_swapin_failed); + case ERROR_BUSY: return (syserr_busy); + case ERROR_CANCEL_VIOLATION: return (syserr_cancel_violation); + case ERROR_ATOMIC_LOCK_NOT_SUPPORTED: return (syserr_atomic_lock_not_supported); + case ERROR_READ_LOCKS_NOT_SUPPORTED: return (syserr_read_locks_not_supported); + case ERROR_INVALID_SEGMENT_NUMBER: return (syserr_invalid_segment_number); + case ERROR_INVALID_CALLGATE: return (syserr_invalid_callgate); + case ERROR_INVALID_ORDINAL: return (syserr_invalid_ordinal); + case ERROR_ALREADY_EXISTS: return (syserr_already_exists); + case ERROR_NO_CHILD_PROCESS: return (syserr_no_child_process); + case ERROR_CHILD_ALIVE_NOWAIT: return (syserr_child_alive_nowait); + case ERROR_INVALID_FLAG_NUMBER: return (syserr_invalid_flag_number); + case ERROR_SEM_NOT_FOUND: return (syserr_sem_not_found); + case ERROR_INVALID_STARTING_CODESEG: return (syserr_invalid_starting_codeseg); + case ERROR_INVALID_STACKSEG: return (syserr_invalid_stackseg); + case ERROR_INVALID_MODULETYPE: return (syserr_invalid_moduletype); + case ERROR_INVALID_EXE_SIGNATURE: return (syserr_invalid_exe_signature); + case ERROR_EXE_MARKED_INVALID: return (syserr_exe_marked_invalid); + case ERROR_BAD_EXE_FORMAT: return (syserr_bad_exe_format); + case ERROR_ITERATED_DATA_EXCEEDS_64k: return (syserr_iterated_data_exceeds_64k); + case ERROR_INVALID_MINALLOCSIZE: return (syserr_invalid_minallocsize); + case ERROR_DYNLINK_FROM_INVALID_RING: return (syserr_dynlink_from_invalid_ring); + case ERROR_IOPL_NOT_ENABLED: return (syserr_iopl_not_enabled); + case ERROR_INVALID_SEGDPL: return (syserr_invalid_segdpl); + case ERROR_AUTODATASEG_EXCEEDS_64k: return (syserr_autodataseg_exceeds_64k); + case ERROR_RING2SEG_MUST_BE_MOVABLE: return (syserr_ring2seg_must_be_movable); + case ERROR_RELOC_CHAIN_XEEDS_SEGLIM: return (syserr_reloc_chain_xeeds_seglim); + case ERROR_INFLOOP_IN_RELOC_CHAIN: return (syserr_infloop_in_reloc_chain); + case ERROR_ENVVAR_NOT_FOUND: return (syserr_envvar_not_found); + case ERROR_NOT_CURRENT_CTRY: return (syserr_not_current_ctry); + case ERROR_NO_SIGNAL_SENT: return (syserr_no_signal_sent); + case ERROR_FILENAME_EXCED_RANGE: return (syserr_filename_exced_range); + case ERROR_RING2_STACK_IN_USE: return (syserr_ring2_stack_in_use); + case ERROR_META_EXPANSION_TOO_LONG: return (syserr_meta_expansion_too_long); + case ERROR_INVALID_SIGNAL_NUMBER: return (syserr_invalid_signal_number); + case ERROR_THREAD_1_INACTIVE: return (syserr_thread_1_inactive); + case ERROR_INFO_NOT_AVAIL: return (syserr_info_not_avail); + case ERROR_LOCKED: return (syserr_locked); + case ERROR_BAD_DYNALINK: return (syserr_bad_dynalink); + case ERROR_TOO_MANY_MODULES: return (syserr_too_many_modules); + case ERROR_NESTING_NOT_ALLOWED: return (syserr_nesting_not_allowed); + case ERROR_CANNOT_SHRINK: return (syserr_cannot_shrink); + case ERROR_ZOMBIE_PROCESS: return (syserr_zombie_process); + case ERROR_STACK_IN_HIGH_MEMORY: return (syserr_stack_in_high_memory); + case ERROR_INVALID_EXITROUTINE_RING: return (syserr_invalid_exitroutine_ring); + case ERROR_GETBUF_FAILED: return (syserr_getbuf_failed); + case ERROR_FLUSHBUF_FAILED: return (syserr_flushbuf_failed); + case ERROR_TRANSFER_TOO_LONG: return (syserr_transfer_too_long); + case ERROR_FORCENOSWAP_FAILED: return (syserr_forcenoswap_failed); + case ERROR_SMG_NO_TARGET_WINDOW: return (syserr_smg_no_target_window); + case ERROR_NO_CHILDREN: return (syserr_no_children); + case ERROR_INVALID_SCREEN_GROUP: return (syserr_invalid_screen_group); + case ERROR_BAD_PIPE: return (syserr_bad_pipe); + case ERROR_PIPE_BUSY: return (syserr_pipe_busy); + case ERROR_NO_DATA: return (syserr_no_data); + case ERROR_PIPE_NOT_CONNECTED: return (syserr_pipe_not_connected); + case ERROR_MORE_DATA: return (syserr_more_data); + case ERROR_VC_DISCONNECTED: return (syserr_vc_disconnected); + case ERROR_CIRCULARITY_REQUESTED: return (syserr_circularity_requested); + case ERROR_DIRECTORY_IN_CDS: return (syserr_directory_in_cds); + case ERROR_INVALID_FSD_NAME: return (syserr_invalid_fsd_name); + case ERROR_INVALID_PATH: return (syserr_invalid_path); + case ERROR_INVALID_EA_NAME: return (syserr_invalid_ea_name); + case ERROR_EA_LIST_INCONSISTENT: return (syserr_ea_list_inconsistent); + case ERROR_EA_LIST_TOO_LONG: return (syserr_ea_list_too_long); + case ERROR_NO_META_MATCH: return (syserr_no_meta_match); + case ERROR_FINDNOTIFY_TIMEOUT: return (syserr_findnotify_timeout); + case ERROR_NO_MORE_ITEMS: return (syserr_no_more_items); + case ERROR_SEARCH_STRUC_REUSED: return (syserr_search_struc_reused); + case ERROR_CHAR_NOT_FOUND: return (syserr_char_not_found); + case ERROR_TOO_MUCH_STACK: return (syserr_too_much_stack); + case ERROR_INVALID_ATTR: return (syserr_invalid_attr); + case ERROR_INVALID_STARTING_RING: return (syserr_invalid_starting_ring); + case ERROR_INVALID_DLL_INIT_RING: return (syserr_invalid_dll_init_ring); + case ERROR_CANNOT_COPY: return (syserr_cannot_copy); + case ERROR_DIRECTORY: return (syserr_directory); + case ERROR_OPLOCKED_FILE: return (syserr_oplocked_file); + case ERROR_OPLOCK_THREAD_EXISTS: return (syserr_oplock_thread_exists); + case ERROR_VOLUME_CHANGED: return (syserr_volume_changed); + case ERROR_FINDNOTIFY_HANDLE_IN_USE: return (syserr_findnotify_handle_in_use); + case ERROR_FINDNOTIFY_HANDLE_CLOSED: return (syserr_findnotify_handle_closed); + case ERROR_NOTIFY_OBJECT_REMOVED: return (syserr_notify_object_removed); + case ERROR_ALREADY_SHUTDOWN: return (syserr_already_shutdown); + case ERROR_EAS_DIDNT_FIT: return (syserr_eas_didnt_fit); + case ERROR_EA_FILE_CORRUPT: return (syserr_ea_file_corrupt); + case ERROR_EA_TABLE_FULL: return (syserr_ea_table_full); + case ERROR_INVALID_EA_HANDLE: return (syserr_invalid_ea_handle); + case ERROR_NO_CLUSTER: return (syserr_no_cluster); + case ERROR_CREATE_EA_FILE: return (syserr_create_ea_file); + case ERROR_CANNOT_OPEN_EA_FILE: return (syserr_cannot_open_ea_file); + case ERROR_EAS_NOT_SUPPORTED: return (syserr_eas_not_supported); + case ERROR_NEED_EAS_FOUND: return (syserr_need_eas_found); + case ERROR_DUPLICATE_HANDLE: return (syserr_duplicate_handle); + case ERROR_DUPLICATE_NAME: return (syserr_duplicate_name); + case ERROR_EMPTY_MUXWAIT: return (syserr_empty_muxwait); + case ERROR_MUTEX_OWNED: return (syserr_mutex_owned); + case ERROR_NOT_OWNER: return (syserr_not_owner); + case ERROR_PARAM_TOO_SMALL: return (syserr_param_too_small); + case ERROR_TOO_MANY_HANDLES: return (syserr_too_many_handles); + case ERROR_TOO_MANY_OPENS: return (syserr_too_many_opens); + case ERROR_WRONG_TYPE: return (syserr_wrong_type); + case ERROR_UNUSED_CODE: return (syserr_unused_code); + case ERROR_THREAD_NOT_TERMINATED: return (syserr_thread_not_terminated); + case ERROR_INIT_ROUTINE_FAILED: return (syserr_init_routine_failed); + case ERROR_MODULE_IN_USE: return (syserr_module_in_use); + case ERROR_NOT_ENOUGH_WATCHPOINTS: return (syserr_not_enough_watchpoints); + case ERROR_TOO_MANY_POSTS: return (syserr_too_many_posts); + case ERROR_ALREADY_POSTED: return (syserr_already_posted); + case ERROR_ALREADY_RESET: return (syserr_already_reset); + case ERROR_SEM_BUSY: return (syserr_sem_busy); + case ERROR_INVALID_PROCID: return (syserr_invalid_procid); + case ERROR_INVALID_PDELTA: return (syserr_invalid_pdelta); + case ERROR_NOT_DESCENDANT: return (syserr_not_descendant); + case ERROR_NOT_SESSION_MANAGER: return (syserr_not_session_manager); + case ERROR_INVALID_PCLASS: return (syserr_invalid_pclass); + case ERROR_INVALID_SCOPE: return (syserr_invalid_scope); + case ERROR_INVALID_THREADID: return (syserr_invalid_threadid); + case ERROR_DOSSUB_SHRINK: return (syserr_dossub_shrink); + case ERROR_DOSSUB_NOMEM: return (syserr_dossub_nomem); + case ERROR_DOSSUB_OVERLAP: return (syserr_dossub_overlap); + case ERROR_DOSSUB_BADSIZE: return (syserr_dossub_badsize); + case ERROR_DOSSUB_BADFLAG: return (syserr_dossub_badflag); + case ERROR_DOSSUB_BADSELECTOR: return (syserr_dossub_badselector); + case ERROR_MR_MSG_TOO_LONG: return (syserr_mr_msg_too_long); + case ERROR_MR_MID_NOT_FOUND: return (syserr_mr_mid_not_found); + case ERROR_MR_UN_ACC_MSGF: return (syserr_mr_un_acc_msgf); + case ERROR_MR_INV_MSGF_FORMAT: return (syserr_mr_inv_msgf_format); + case ERROR_MR_INV_IVCOUNT: return (syserr_mr_inv_ivcount); + case ERROR_MR_UN_PERFORM: return (syserr_mr_un_perform); + case ERROR_TS_WAKEUP: return (syserr_ts_wakeup); + case ERROR_TS_SEMHANDLE: return (syserr_ts_semhandle); + case ERROR_TS_NOTIMER: return (syserr_ts_notimer); + case ERROR_TS_HANDLE: return (syserr_ts_handle); + case ERROR_TS_DATETIME: return (syserr_ts_datetime); + case ERROR_SYS_INTERNAL: return (syserr_sys_internal); + case ERROR_QUE_CURRENT_NAME: return (syserr_que_current_name); + case ERROR_QUE_PROC_NOT_OWNED: return (syserr_que_proc_not_owned); + case ERROR_QUE_PROC_OWNED: return (syserr_que_proc_owned); + case ERROR_QUE_DUPLICATE: return (syserr_que_duplicate); + case ERROR_QUE_ELEMENT_NOT_EXIST: return (syserr_que_element_not_exist); + case ERROR_QUE_NO_MEMORY: return (syserr_que_no_memory); + case ERROR_QUE_INVALID_NAME: return (syserr_que_invalid_name); + case ERROR_QUE_INVALID_PRIORITY: return (syserr_que_invalid_priority); + case ERROR_QUE_INVALID_HANDLE: return (syserr_que_invalid_handle); + case ERROR_QUE_LINK_NOT_FOUND: return (syserr_que_link_not_found); + case ERROR_QUE_MEMORY_ERROR: return (syserr_que_memory_error); + case ERROR_QUE_PREV_AT_END: return (syserr_que_prev_at_end); + case ERROR_QUE_PROC_NO_ACCESS: return (syserr_que_proc_no_access); + case ERROR_QUE_EMPTY: return (syserr_que_empty); + case ERROR_QUE_NAME_NOT_EXIST: return (syserr_que_name_not_exist); + case ERROR_QUE_NOT_INITIALIZED: return (syserr_que_not_initialized); + case ERROR_QUE_UNABLE_TO_ACCESS: return (syserr_que_unable_to_access); + case ERROR_QUE_UNABLE_TO_ADD: return (syserr_que_unable_to_add); + case ERROR_QUE_UNABLE_TO_INIT: return (syserr_que_unable_to_init); + case ERROR_VIO_INVALID_MASK: return (syserr_vio_invalid_mask); + case ERROR_VIO_PTR: return (syserr_vio_ptr); + case ERROR_VIO_APTR: return (syserr_vio_aptr); + case ERROR_VIO_RPTR: return (syserr_vio_rptr); + case ERROR_VIO_CPTR: return (syserr_vio_cptr); + case ERROR_VIO_LPTR: return (syserr_vio_lptr); + case ERROR_VIO_MODE: return (syserr_vio_mode); + case ERROR_VIO_WIDTH: return (syserr_vio_width); + case ERROR_VIO_ATTR: return (syserr_vio_attr); + case ERROR_VIO_ROW: return (syserr_vio_row); + case ERROR_VIO_COL: return (syserr_vio_col); + case ERROR_VIO_TOPROW: return (syserr_vio_toprow); + case ERROR_VIO_BOTROW: return (syserr_vio_botrow); + case ERROR_VIO_RIGHTCOL: return (syserr_vio_rightcol); + case ERROR_VIO_LEFTCOL: return (syserr_vio_leftcol); + case ERROR_SCS_CALL: return (syserr_scs_call); + case ERROR_SCS_VALUE: return (syserr_scs_value); + case ERROR_VIO_WAIT_FLAG: return (syserr_vio_wait_flag); + case ERROR_VIO_UNLOCK: return (syserr_vio_unlock); + case ERROR_SGS_NOT_SESSION_MGR: return (syserr_sgs_not_session_mgr); + case ERROR_SMG_INVALID_SESSION_ID: return (syserr_smg_invalid_session_id); + case ERROR_SMG_NO_SESSIONS: return (syserr_smg_no_sessions); + case ERROR_SMG_SESSION_NOT_FOUND: return (syserr_smg_session_not_found); + case ERROR_SMG_SET_TITLE: return (syserr_smg_set_title); + case ERROR_KBD_PARAMETER: return (syserr_kbd_parameter); + case ERROR_KBD_NO_DEVICE: return (syserr_kbd_no_device); + case ERROR_KBD_INVALID_IOWAIT: return (syserr_kbd_invalid_iowait); + case ERROR_KBD_INVALID_LENGTH: return (syserr_kbd_invalid_length); + case ERROR_KBD_INVALID_ECHO_MASK: return (syserr_kbd_invalid_echo_mask); + case ERROR_KBD_INVALID_INPUT_MASK: return (syserr_kbd_invalid_input_mask); + case ERROR_MON_INVALID_PARMS: return (syserr_mon_invalid_parms); + case ERROR_MON_INVALID_DEVNAME: return (syserr_mon_invalid_devname); + case ERROR_MON_INVALID_HANDLE: return (syserr_mon_invalid_handle); + case ERROR_MON_BUFFER_TOO_SMALL: return (syserr_mon_buffer_too_small); + case ERROR_MON_BUFFER_EMPTY: return (syserr_mon_buffer_empty); + case ERROR_MON_DATA_TOO_LARGE: return (syserr_mon_data_too_large); + case ERROR_MOUSE_NO_DEVICE: return (syserr_mouse_no_device); + case ERROR_MOUSE_INV_HANDLE: return (syserr_mouse_inv_handle); + case ERROR_MOUSE_INV_PARMS: return (syserr_mouse_inv_parms); + case ERROR_MOUSE_CANT_RESET: return (syserr_mouse_cant_reset); + case ERROR_MOUSE_DISPLAY_PARMS: return (syserr_mouse_display_parms); + case ERROR_MOUSE_INV_MODULE: return (syserr_mouse_inv_module); + case ERROR_MOUSE_INV_ENTRY_PT: return (syserr_mouse_inv_entry_pt); + case ERROR_MOUSE_INV_MASK: return (syserr_mouse_inv_mask); + case NO_ERROR_MOUSE_NO_DATA: return (syserr_mouse_no_data); + case NO_ERROR_MOUSE_PTR_DRAWN: return (syserr_mouse_ptr_drawn); + case ERROR_INVALID_FREQUENCY: return (syserr_invalid_frequency); + case ERROR_NLS_NO_COUNTRY_FILE: return (syserr_nls_no_country_file); + case ERROR_NLS_OPEN_FAILED: return (syserr_nls_open_failed); + case ERROR_NO_COUNTRY_OR_CODEPAGE: return (syserr_no_country_or_codepage); + case ERROR_NLS_TABLE_TRUNCATED: return (syserr_nls_table_truncated); + case ERROR_NLS_BAD_TYPE: return (syserr_nls_bad_type); + case ERROR_NLS_TYPE_NOT_FOUND: return (syserr_nls_type_not_found); + case ERROR_VIO_SMG_ONLY: return (syserr_vio_smg_only); + case ERROR_VIO_INVALID_ASCIIZ: return (syserr_vio_invalid_asciiz); + case ERROR_VIO_DEREGISTER: return (syserr_vio_deregister); + case ERROR_VIO_NO_POPUP: return (syserr_vio_no_popup); + case ERROR_VIO_EXISTING_POPUP: return (syserr_vio_existing_popup); + case ERROR_KBD_SMG_ONLY: return (syserr_kbd_smg_only); + case ERROR_KBD_INVALID_ASCIIZ: return (syserr_kbd_invalid_asciiz); + case ERROR_KBD_INVALID_MASK: return (syserr_kbd_invalid_mask); + case ERROR_KBD_REGISTER: return (syserr_kbd_register); + case ERROR_KBD_DEREGISTER: return (syserr_kbd_deregister); + case ERROR_MOUSE_SMG_ONLY: return (syserr_mouse_smg_only); + case ERROR_MOUSE_INVALID_ASCIIZ: return (syserr_mouse_invalid_asciiz); + case ERROR_MOUSE_INVALID_MASK: return (syserr_mouse_invalid_mask); + case ERROR_MOUSE_REGISTER: return (syserr_mouse_register); + case ERROR_MOUSE_DEREGISTER: return (syserr_mouse_deregister); + case ERROR_SMG_BAD_ACTION: return (syserr_smg_bad_action); + case ERROR_SMG_INVALID_CALL: return (syserr_smg_invalid_call); + case ERROR_SCS_SG_NOTFOUND: return (syserr_scs_sg_notfound); + case ERROR_SCS_NOT_SHELL: return (syserr_scs_not_shell); + case ERROR_VIO_INVALID_PARMS: return (syserr_vio_invalid_parms); + case ERROR_VIO_FUNCTION_OWNED: return (syserr_vio_function_owned); + case ERROR_VIO_RETURN: return (syserr_vio_return); + case ERROR_SCS_INVALID_FUNCTION: return (syserr_scs_invalid_function); + case ERROR_SCS_NOT_SESSION_MGR: return (syserr_scs_not_session_mgr); + case ERROR_VIO_REGISTER: return (syserr_vio_register); + case ERROR_VIO_NO_MODE_THREAD: return (syserr_vio_no_mode_thread); + case ERROR_VIO_NO_SAVE_RESTORE_THD: return (syserr_vio_no_save_restore_thd); + case ERROR_VIO_IN_BG: return (syserr_vio_in_bg); + case ERROR_VIO_ILLEGAL_DURING_POPUP: return (syserr_vio_illegal_during_popup); + case ERROR_SMG_NOT_BASESHELL: return (syserr_smg_not_baseshell); + case ERROR_SMG_BAD_STATUSREQ: return (syserr_smg_bad_statusreq); + case ERROR_QUE_INVALID_WAIT: return (syserr_que_invalid_wait); + case ERROR_VIO_LOCK: return (syserr_vio_lock); + case ERROR_MOUSE_INVALID_IOWAIT: return (syserr_mouse_invalid_iowait); + case ERROR_VIO_INVALID_HANDLE: return (syserr_vio_invalid_handle); + case ERROR_VIO_ILLEGAL_DURING_LOCK: return (syserr_vio_illegal_during_lock); + case ERROR_VIO_INVALID_LENGTH: return (syserr_vio_invalid_length); + case ERROR_KBD_INVALID_HANDLE: return (syserr_kbd_invalid_handle); + case ERROR_KBD_NO_MORE_HANDLE: return (syserr_kbd_no_more_handle); + case ERROR_KBD_CANNOT_CREATE_KCB: return (syserr_kbd_cannot_create_kcb); + case ERROR_KBD_CODEPAGE_LOAD_INCOMPL: return (syserr_kbd_codepage_load_incompl); + case ERROR_KBD_INVALID_CODEPAGE_ID: return (syserr_kbd_invalid_codepage_id); + case ERROR_KBD_NO_CODEPAGE_SUPPORT: return (syserr_kbd_no_codepage_support); + case ERROR_KBD_FOCUS_REQUIRED: return (syserr_kbd_focus_required); + case ERROR_KBD_FOCUS_ALREADY_ACTIVE: return (syserr_kbd_focus_already_active); + case ERROR_KBD_KEYBOARD_BUSY: return (syserr_kbd_keyboard_busy); + case ERROR_KBD_INVALID_CODEPAGE: return (syserr_kbd_invalid_codepage); + case ERROR_KBD_UNABLE_TO_FOCUS: return (syserr_kbd_unable_to_focus); + case ERROR_SMG_SESSION_NON_SELECT: return (syserr_smg_session_non_select); + case ERROR_SMG_SESSION_NOT_FOREGRND: return (syserr_smg_session_not_foregrnd); + case ERROR_SMG_SESSION_NOT_PARENT: return (syserr_smg_session_not_parent); + case ERROR_SMG_INVALID_START_MODE: return (syserr_smg_invalid_start_mode); + case ERROR_SMG_INVALID_RELATED_OPT: return (syserr_smg_invalid_related_opt); + case ERROR_SMG_INVALID_BOND_OPTION: return (syserr_smg_invalid_bond_option); + case ERROR_SMG_INVALID_SELECT_OPT: return (syserr_smg_invalid_select_opt); + case ERROR_SMG_START_IN_BACKGROUND: return (syserr_smg_start_in_background); + case ERROR_SMG_INVALID_STOP_OPTION: return (syserr_smg_invalid_stop_option); + case ERROR_SMG_BAD_RESERVE: return (syserr_smg_bad_reserve); + case ERROR_SMG_PROCESS_NOT_PARENT: return (syserr_smg_process_not_parent); + case ERROR_SMG_INVALID_DATA_LENGTH: return (syserr_smg_invalid_data_length); + case ERROR_SMG_NOT_BOUND: return (syserr_smg_not_bound); + case ERROR_SMG_RETRY_SUB_ALLOC: return (syserr_smg_retry_sub_alloc); + case ERROR_KBD_DETACHED: return (syserr_kbd_detached); + case ERROR_VIO_DETACHED: return (syserr_vio_detached); + case ERROR_MOU_DETACHED: return (syserr_mou_detached); + case ERROR_VIO_FONT: return (syserr_vio_font); + case ERROR_VIO_USER_FONT: return (syserr_vio_user_font); + case ERROR_VIO_BAD_CP: return (syserr_vio_bad_cp); + case ERROR_VIO_NO_CP: return (syserr_vio_no_cp); + case ERROR_VIO_NA_CP: return (syserr_vio_na_cp); + case ERROR_INVALID_CODE_PAGE: return (syserr_invalid_code_page); + case ERROR_CPLIST_TOO_SMALL: return (syserr_cplist_too_small); + case ERROR_CP_NOT_MOVED: return (syserr_cp_not_moved); + case ERROR_MODE_SWITCH_INIT: return (syserr_mode_switch_init); + case ERROR_CODE_PAGE_NOT_FOUND: return (syserr_code_page_not_found); + case ERROR_UNEXPECTED_SLOT_RETURNED: return (syserr_unexpected_slot_returned); + case ERROR_SMG_INVALID_TRACE_OPTION: return (syserr_smg_invalid_trace_option); + case ERROR_VIO_INTERNAL_RESOURCE: return (syserr_vio_internal_resource); + case ERROR_VIO_SHELL_INIT: return (syserr_vio_shell_init); + case ERROR_SMG_NO_HARD_ERRORS: return (syserr_smg_no_hard_errors); + case ERROR_CP_SWITCH_INCOMPLETE: return (syserr_cp_switch_incomplete); + case ERROR_VIO_TRANSPARENT_POPUP: return (syserr_vio_transparent_popup); + case ERROR_CRITSEC_OVERFLOW: return (syserr_critsec_overflow); + case ERROR_CRITSEC_UNDERFLOW: return (syserr_critsec_underflow); + case ERROR_VIO_BAD_RESERVE: return (syserr_vio_bad_reserve); + case ERROR_INVALID_ADDRESS: return (syserr_invalid_address); + case ERROR_ZERO_SELECTORS_REQUESTED: return (syserr_zero_selectors_requested); + case ERROR_NOT_ENOUGH_SELECTORS_AVA: return (syserr_not_enough_selectors_ava); + case ERROR_INVALID_SELECTOR: return (syserr_invalid_selector); + case ERROR_SMG_INVALID_PROGRAM_TYPE: return (syserr_smg_invalid_program_type); + case ERROR_SMG_INVALID_PGM_CONTROL: return (syserr_smg_invalid_pgm_control); + case ERROR_SMG_INVALID_INHERIT_OPT: return (syserr_smg_invalid_inherit_opt); + case ERROR_VIO_EXTENDED_SG: return (syserr_vio_extended_sg); + case ERROR_VIO_NOT_PRES_MGR_SG: return (syserr_vio_not_pres_mgr_sg); + case ERROR_VIO_SHIELD_OWNED: return (syserr_vio_shield_owned); + case ERROR_VIO_NO_MORE_HANDLES: return (syserr_vio_no_more_handles); + case ERROR_VIO_SEE_ERROR_LOG: return (syserr_vio_see_error_log); + case ERROR_VIO_ASSOCIATED_DC: return (syserr_vio_associated_dc); + case ERROR_KBD_NO_CONSOLE: return (syserr_kbd_no_console); + case ERROR_MOUSE_NO_CONSOLE: return (syserr_mouse_no_console); + case ERROR_MOUSE_INVALID_HANDLE: return (syserr_mouse_invalid_handle); + case ERROR_SMG_INVALID_DEBUG_PARMS: return (syserr_smg_invalid_debug_parms); + case ERROR_KBD_EXTENDED_SG: return (syserr_kbd_extended_sg); + case ERROR_MOU_EXTENDED_SG: return (syserr_mou_extended_sg); + case ERROR_SMG_INVALID_ICON_FILE: return (syserr_smg_invalid_icon_file); + case ERROR_TRC_PID_NON_EXISTENT: return (syserr_trc_pid_non_existent); + case ERROR_TRC_COUNT_ACTIVE: return (syserr_trc_count_active); + case ERROR_TRC_SUSPENDED_BY_COUNT: return (syserr_trc_suspended_by_count); + case ERROR_TRC_COUNT_INACTIVE: return (syserr_trc_count_inactive); + case ERROR_TRC_COUNT_REACHED: return (syserr_trc_count_reached); + case ERROR_NO_MC_TRACE: return (syserr_no_mc_trace); + case ERROR_MC_TRACE: return (syserr_mc_trace); + case ERROR_TRC_COUNT_ZERO: return (syserr_trc_count_zero); + case ERROR_SMG_TOO_MANY_DDS: return (syserr_smg_too_many_dds); + case ERROR_SMG_INVALID_NOTIFICATION: return (syserr_smg_invalid_notification); + case ERROR_LF_INVALID_FUNCTION: return (syserr_lf_invalid_function); + case ERROR_LF_NOT_AVAIL: return (syserr_lf_not_avail); + case ERROR_LF_SUSPENDED: return (syserr_lf_suspended); + case ERROR_LF_BUF_TOO_SMALL: return (syserr_lf_buf_too_small); + case ERROR_LF_BUFFER_FULL: return (syserr_lf_buffer_full); + case ERROR_LF_INVALID_RECORD: return (syserr_lf_invalid_record); + case ERROR_LF_INVALID_SERVICE: return (syserr_lf_invalid_service); + case ERROR_LF_GENERAL_FAILURE: return (syserr_lf_general_failure); + case ERROR_LF_INVALID_ID: return (syserr_lf_invalid_id); + case ERROR_LF_INVALID_HANDLE: return (syserr_lf_invalid_handle); + case ERROR_LF_NO_ID_AVAIL: return (syserr_lf_no_id_avail); + case ERROR_LF_TEMPLATE_AREA_FULL: return (syserr_lf_template_area_full); + case ERROR_LF_ID_IN_USE: return (syserr_lf_id_in_use); + case ERROR_MOU_NOT_INITIALIZED: return (syserr_mou_not_initialized); + case ERROR_MOUINITREAL_DONE: return (syserr_mouinitreal_done); + case ERROR_DOSSUB_CORRUPTED: return (syserr_dossub_corrupted); + case ERROR_MOUSE_CALLER_NOT_SUBSYS: return (syserr_mouse_caller_not_subsys); + case ERROR_ARITHMETIC_OVERFLOW: return (syserr_arithmetic_overflow); + case ERROR_TMR_NO_DEVICE: return (syserr_tmr_no_device); + case ERROR_TMR_INVALID_TIME: return (syserr_tmr_invalid_time); + case ERROR_PVW_INVALID_ENTITY: return (syserr_pvw_invalid_entity); + case ERROR_PVW_INVALID_ENTITY_TYPE: return (syserr_pvw_invalid_entity_type); + case ERROR_PVW_INVALID_SPEC: return (syserr_pvw_invalid_spec); + case ERROR_PVW_INVALID_RANGE_TYPE: return (syserr_pvw_invalid_range_type); + case ERROR_PVW_INVALID_COUNTER_BLK: return (syserr_pvw_invalid_counter_blk); + case ERROR_PVW_INVALID_TEXT_BLK: return (syserr_pvw_invalid_text_blk); + case ERROR_PRF_NOT_INITIALIZED: return (syserr_prf_not_initialized); + case ERROR_PRF_ALREADY_INITIALIZED: return (syserr_prf_already_initialized); + case ERROR_PRF_NOT_STARTED: return (syserr_prf_not_started); + case ERROR_PRF_ALREADY_STARTED: return (syserr_prf_already_started); + case ERROR_PRF_TIMER_OUT_OF_RANGE: return (syserr_prf_timer_out_of_range); + case ERROR_PRF_TIMER_RESET: return (syserr_prf_timer_reset); + case ERROR_VDD_LOCK_USEAGE_DENIED: return (syserr_vdd_lock_useage_denied); + case ERROR_TIMEOUT: return (syserr_timeout); + case ERROR_VDM_DOWN: return (syserr_vdm_down); + case ERROR_VDM_LIMIT: return (syserr_vdm_limit); + case ERROR_VDD_NOT_FOUND: return (syserr_vdd_not_found); + case ERROR_INVALID_CALLER: return (syserr_invalid_caller); + case ERROR_PID_MISMATCH: return (syserr_pid_mismatch); + case ERROR_INVALID_VDD_HANDLE: return (syserr_invalid_vdd_handle); + case ERROR_VLPT_NO_SPOOLER: return (syserr_vlpt_no_spooler); + case ERROR_VCOM_DEVICE_BUSY: return (syserr_vcom_device_busy); + case ERROR_VLPT_DEVICE_BUSY: return (syserr_vlpt_device_busy); + case ERROR_NESTING_TOO_DEEP: return (syserr_nesting_too_deep); + case ERROR_VDD_MISSING: return (syserr_vdd_missing); + case ERROR_BIDI_INVALID_LENGTH: return (syserr_bidi_invalid_length); + case ERROR_BIDI_INVALID_INCREMENT: return (syserr_bidi_invalid_increment); + case ERROR_BIDI_INVALID_COMBINATION: return (syserr_bidi_invalid_combination); + case ERROR_BIDI_INVALID_RESERVED: return (syserr_bidi_invalid_reserved); + case ERROR_BIDI_INVALID_EFFECT: return (syserr_bidi_invalid_effect); + case ERROR_BIDI_INVALID_CSDREC: return (syserr_bidi_invalid_csdrec); + case ERROR_BIDI_INVALID_CSDSTATE: return (syserr_bidi_invalid_csdstate); + case ERROR_BIDI_INVALID_LEVEL: return (syserr_bidi_invalid_level); + case ERROR_BIDI_INVALID_TYPE_SUPPORT: return (syserr_bidi_invalid_type_support); + case ERROR_BIDI_INVALID_ORIENTATION: return (syserr_bidi_invalid_orientation); + case ERROR_BIDI_INVALID_NUM_SHAPE: return (syserr_bidi_invalid_num_shape); + case ERROR_BIDI_INVALID_CSD: return (syserr_bidi_invalid_csd); + case ERROR_BIDI_NO_SUPPORT: return (syserr_bidi_no_support); + case NO_ERROR_BIDI_RW_INCOMPLETE: return (syserr_bidi_rw_incomplete); + case ERROR_IMP_INVALID_PARM: return (syserr_imp_invalid_parm); + case ERROR_IMP_INVALID_LENGTH: return (syserr_imp_invalid_length); + case MSG_HPFS_DISK_ERROR_WARN: return (syserr_hpfs_disk_error_warn); + case ERROR_MON_BAD_BUFFER: return (syserr_mon_bad_buffer); + case ERROR_MODULE_CORRUPTED: return (syserr_module_corrupted); + case ERROR_SM_OUTOF_SWAPFILE: return (syserr_sm_outof_swapfile); + case ERROR_LF_TIMEOUT: return (syserr_lf_timeout); + case ERROR_LF_SUSPEND_SUCCESS: return (syserr_lf_suspend_success); + case ERROR_LF_RESUME_SUCCESS: return (syserr_lf_resume_success); + case ERROR_LF_REDIRECT_SUCCESS: return (syserr_lf_redirect_success); + case ERROR_LF_REDIRECT_FAILURE: return (syserr_lf_redirect_failure); + case ERROR_SWAPPER_NOT_ACTIVE: return (syserr_swapper_not_active); + case ERROR_INVALID_SWAPID: return (syserr_invalid_swapid); + case ERROR_IOERR_SWAP_FILE: return (syserr_ioerr_swap_file); + case ERROR_SWAP_TABLE_FULL: return (syserr_swap_table_full); + case ERROR_SWAP_FILE_FULL: return (syserr_swap_file_full); + case ERROR_CANT_INIT_SWAPPER: return (syserr_cant_init_swapper); + case ERROR_SWAPPER_ALREADY_INIT: return (syserr_swapper_already_init); + case ERROR_PMM_INSUFFICIENT_MEMORY: return (syserr_pmm_insufficient_memory); + case ERROR_PMM_INVALID_FLAGS: return (syserr_pmm_invalid_flags); + case ERROR_PMM_INVALID_ADDRESS: return (syserr_pmm_invalid_address); + case ERROR_PMM_LOCK_FAILED: return (syserr_pmm_lock_failed); + case ERROR_PMM_UNLOCK_FAILED: return (syserr_pmm_unlock_failed); + case ERROR_PMM_MOVE_INCOMPLETE: return (syserr_pmm_move_incomplete); + case ERROR_UCOM_DRIVE_RENAMED: return (syserr_ucom_drive_renamed); + case ERROR_UCOM_FILENAME_TRUNCATED: return (syserr_ucom_filename_truncated); + case ERROR_UCOM_BUFFER_LENGTH: return (syserr_ucom_buffer_length); + case ERROR_MON_CHAIN_HANDLE: return (syserr_mon_chain_handle); + case ERROR_MON_NOT_REGISTERED: return (syserr_mon_not_registered); + case ERROR_SMG_ALREADY_TOP: return (syserr_smg_already_top); + case ERROR_PMM_ARENA_MODIFIED: return (syserr_pmm_arena_modified); + case ERROR_SMG_PRINTER_OPEN: return (syserr_smg_printer_open); + case ERROR_PMM_SET_FLAGS_FAILED: return (syserr_pmm_set_flags_failed); + case ERROR_INVALID_DOS_DD: return (syserr_invalid_dos_dd); + case ERROR_BLOCKED: return (syserr_blocked); + case ERROR_NOBLOCK: return (syserr_noblock); + case ERROR_INSTANCE_SHARED: return (syserr_instance_shared); + case ERROR_NO_OBJECT: return (syserr_no_object); + case ERROR_PARTIAL_ATTACH: return (syserr_partial_attach); + case ERROR_INCACHE: return (syserr_incache); + case ERROR_SWAP_IO_PROBLEMS: return (syserr_swap_io_problems); + case ERROR_CROSSES_OBJECT_BOUNDARY: return (syserr_crosses_object_boundary); + case ERROR_LONGLOCK: return (syserr_longlock); + case ERROR_SHORTLOCK: return (syserr_shortlock); + case ERROR_UVIRTLOCK: return (syserr_uvirtlock); + case ERROR_ALIASLOCK: return (syserr_aliaslock); + case ERROR_ALIAS: return (syserr_alias); + case ERROR_NO_MORE_HANDLES: return (syserr_no_more_handles); + case ERROR_SCAN_TERMINATED: return (syserr_scan_terminated); + case ERROR_TERMINATOR_NOT_FOUND: return (syserr_terminator_not_found); + case ERROR_NOT_DIRECT_CHILD: return (syserr_not_direct_child); + case ERROR_DELAY_FREE: return (syserr_delay_free); + case ERROR_GUARDPAGE: return (syserr_guardpage); + case ERROR_SWAPERROR: return (syserr_swaperror); + case ERROR_LDRERROR: return (syserr_ldrerror); + case ERROR_NOMEMORY: return (syserr_nomemory); + case ERROR_NOACCESS: return (syserr_noaccess); + case ERROR_NO_DLL_TERM: return (syserr_no_dll_term); + case ERROR_CPSIO_CODE_PAGE_INVALID: return (syserr_cpsio_code_page_invalid); + case ERROR_CPSIO_NO_SPOOLER: return (syserr_cpsio_no_spooler); + case ERROR_CPSIO_FONT_ID_INVALID: return (syserr_cpsio_font_id_invalid); + case ERROR_CPSIO_INTERNAL_ERROR: return (syserr_cpsio_internal_error); + case ERROR_CPSIO_INVALID_PTR_NAME: return (syserr_cpsio_invalid_ptr_name); + case ERROR_CPSIO_NOT_ACTIVE: return (syserr_cpsio_not_active); + case ERROR_CPSIO_PID_FULL: return (syserr_cpsio_pid_full); + case ERROR_CPSIO_PID_NOT_FOUND: return (syserr_cpsio_pid_not_found); + case ERROR_CPSIO_READ_CTL_SEQ: return (syserr_cpsio_read_ctl_seq); + case ERROR_CPSIO_READ_FNT_DEF: return (syserr_cpsio_read_fnt_def); + case ERROR_CPSIO_WRITE_ERROR: return (syserr_cpsio_write_error); + case ERROR_CPSIO_WRITE_FULL_ERROR: return (syserr_cpsio_write_full_error); + case ERROR_CPSIO_WRITE_HANDLE_BAD: return (syserr_cpsio_write_handle_bad); + case ERROR_CPSIO_SWIT_LOAD: return (syserr_cpsio_swit_load); + case ERROR_CPSIO_INV_COMMAND: return (syserr_cpsio_inv_command); + case ERROR_CPSIO_NO_FONT_SWIT: return (syserr_cpsio_no_font_swit); + case ERROR_ENTRY_IS_CALLGATE: return (syserr_entry_is_callgate); + default: return (syserr_unknown); + } +} + +#ifdef __GCC2__ +/* Grumble... stupid linking bug. */ +#define dos_error_message(rc) 0 +#else /* not __GCC2__ */ + +static const char * +dos_error_message (APIRET rc) +{ + unsigned int blength_increment = 64; + unsigned int blength = blength_increment; + char * buffer = (malloc (blength)); + ULONG mlength; + + if (buffer == 0) + return (0); + while (1) + { + if ((dos_get_message + (0, 0, buffer, blength, rc, "OSO001.MSG", (&mlength))) + != NO_ERROR) + { + free (buffer); + return (0); + } + if (mlength < blength) + { + while ((mlength > 0) && (isspace (buffer [mlength - 1]))) + mlength -= 1; + buffer = (realloc (buffer, (mlength + 1))); + if (buffer != 0) + (buffer[mlength]) = '\0'; + return (buffer); + } + blength += blength_increment; + buffer = (realloc (buffer, (blength))); + if (buffer == 0) + return (0); + } +} + +#endif /* not __GCC2__ */ + +const char * +OS_error_code_to_message (unsigned int syserr) +{ + static const char * last_message = 0; + if (last_message != 0) + free ((void *) last_message); + last_message = (dos_error_message (syserr)); + return (last_message); +} + +static char * syscall_names_table [] = +{ + "dos-async-timer", + "dos-close", + "dos-close-event-sem", + "dos-close-mutex-sem", + "dos-close-queue", + "dos-create-dir", + "dos-create-event-sem", + "dos-create-mutex-sem", + "dos-create-pipe", + "dos-create-queue", + "dos-create-thread", + "dos-delete", + "dos-delete-dir", + "dos-exit", + "dos-find-close", + "dos-find-first", + "dos-find-next", + "dos-get-info-blocks", + "dos-get-message", + "dos-kill-thread", + "dos-move", + "dos-open", + "dos-post-event-sem", + "dos-query-current-dir", + "dos-query-current-disk", + "dos-query-file-info", + "dos-query-h-type", + "dos-query-n-p-h-state", + "dos-query-path-info", + "dos-query-sys-info", + "dos-read", + "dos-read-queue", + "dos-release-mutex-sem", + "dos-request-mutex-sem", + "dos-reset-event-sem", + "dos-scan-env", + "dos-set-current-dir", + "dos-set-default-disk", + "dos-set-file-ptr", + "dos-set-file-size", + "dos-set-path-info", + "dos-start-timer", + "dos-stop-timer", + "dos-wait-event-sem", + "dos-write", + "dos-write-queue", + "beginthread", + "kbd-char-in", + "localtime", + "malloc", + "mktime", + "realloc", + "time", + "vio-wrt-tty" +}; + +void +OS_syscall_names (unsigned int * length, unsigned char *** names) +{ + (*length) = ((sizeof (syscall_names_table)) / (sizeof (char *))); + (*names) = ((unsigned char **) syscall_names_table); +} + +/* Machine-generated table, do not edit: */ +static char * syserr_names_table [] = +{ + "INVALID-FUNCTION", + "FILE-NOT-FOUND", + "PATH-NOT-FOUND", + "TOO-MANY-OPEN-FILES", + "ACCESS-DENIED", + "INVALID-HANDLE", + "ARENA-TRASHED", + "NOT-ENOUGH-MEMORY", + "INVALID-BLOCK", + "BAD-ENVIRONMENT", + "BAD-FORMAT", + "INVALID-ACCESS", + "INVALID-DATA", + "INVALID-DRIVE", + "CURRENT-DIRECTORY", + "NOT-SAME-DEVICE", + "NO-MORE-FILES", + "WRITE-PROTECT", + "BAD-UNIT", + "NOT-READY", + "BAD-COMMAND", + "CRC", + "BAD-LENGTH", + "SEEK", + "NOT-DOS-DISK", + "SECTOR-NOT-FOUND", + "OUT-OF-PAPER", + "WRITE-FAULT", + "READ-FAULT", + "GEN-FAILURE", + "SHARING-VIOLATION", + "LOCK-VIOLATION", + "WRONG-DISK", + "FCB-UNAVAILABLE", + "SHARING-BUFFER-EXCEEDED", + "CODE-PAGE-MISMATCHED", + "HANDLE-EOF", + "HANDLE-DISK-FULL", + "NOT-SUPPORTED", + "REM-NOT-LIST", + "DUP-NAME", + "BAD-NETPATH", + "NETWORK-BUSY", + "DEV-NOT-EXIST", + "TOO-MANY-CMDS", + "ADAP-HDW-ERR", + "BAD-NET-RESP", + "UNEXP-NET-ERR", + "BAD-REM-ADAP", + "PRINTQ-FULL", + "NO-SPOOL-SPACE", + "PRINT-CANCELLED", + "NETNAME-DELETED", + "NETWORK-ACCESS-DENIED", + "BAD-DEV-TYPE", + "BAD-NET-NAME", + "TOO-MANY-NAMES", + "TOO-MANY-SESS", + "SHARING-PAUSED", + "REQ-NOT-ACCEP", + "REDIR-PAUSED", + "SBCS-ATT-WRITE-PROT", + "SBCS-GENERAL-FAILURE", + "XGA-OUT-MEMORY", + "FILE-EXISTS", + "DUP-FCB", + "CANNOT-MAKE", + "FAIL-I24", + "OUT-OF-STRUCTURES", + "ALREADY-ASSIGNED", + "INVALID-PASSWORD", + "INVALID-PARAMETER", + "NET-WRITE-FAULT", + "NO-PROC-SLOTS", + "NOT-FROZEN", + "SYS-COMP-NOT-LOADED", + "TSTOVFL", + "TSTDUP", + "NO-ITEMS", + "INTERRUPT", + "DEVICE-IN-USE", + "TOO-MANY-SEMAPHORES", + "EXCL-SEM-ALREADY-OWNED", + "SEM-IS-SET", + "TOO-MANY-SEM-REQUESTS", + "INVALID-AT-INTERRUPT-TIME", + "SEM-OWNER-DIED", + "SEM-USER-LIMIT", + "DISK-CHANGE", + "DRIVE-LOCKED", + "BROKEN-PIPE", + "OPEN-FAILED", + "BUFFER-OVERFLOW", + "DISK-FULL", + "NO-MORE-SEARCH-HANDLES", + "INVALID-TARGET-HANDLE", + "PROTECTION-VIOLATION", + "VIOKBD-REQUEST", + "INVALID-CATEGORY", + "INVALID-VERIFY-SWITCH", + "BAD-DRIVER-LEVEL", + "CALL-NOT-IMPLEMENTED", + "SEM-TIMEOUT", + "INSUFFICIENT-BUFFER", + "INVALID-NAME", + "INVALID-LEVEL", + "NO-VOLUME-LABEL", + "MOD-NOT-FOUND", + "PROC-NOT-FOUND", + "WAIT-NO-CHILDREN", + "CHILD-NOT-COMPLETE", + "DIRECT-ACCESS-HANDLE", + "NEGATIVE-SEEK", + "SEEK-ON-DEVICE", + "IS-JOIN-TARGET", + "IS-JOINED", + "IS-SUBSTED", + "NOT-JOINED", + "NOT-SUBSTED", + "JOIN-TO-JOIN", + "SUBST-TO-SUBST", + "JOIN-TO-SUBST", + "SUBST-TO-JOIN", + "BUSY-DRIVE", + "SAME-DRIVE", + "DIR-NOT-ROOT", + "DIR-NOT-EMPTY", + "IS-SUBST-PATH", + "IS-JOIN-PATH", + "PATH-BUSY", + "IS-SUBST-TARGET", + "SYSTEM-TRACE", + "INVALID-EVENT-COUNT", + "TOO-MANY-MUXWAITERS", + "INVALID-LIST-FORMAT", + "LABEL-TOO-LONG", + "TOO-MANY-TCBS", + "SIGNAL-REFUSED", + "DISCARDED", + "NOT-LOCKED", + "BAD-THREADID-ADDR", + "BAD-ARGUMENTS", + "BAD-PATHNAME", + "SIGNAL-PENDING", + "UNCERTAIN-MEDIA", + "MAX-THRDS-REACHED", + "MONITORS-NOT-SUPPORTED", + "UNC-DRIVER-NOT-INSTALLED", + "LOCK-FAILED", + "SWAPIO-FAILED", + "SWAPIN-FAILED", + "BUSY", + "CANCEL-VIOLATION", + "ATOMIC-LOCK-NOT-SUPPORTED", + "READ-LOCKS-NOT-SUPPORTED", + "INVALID-SEGMENT-NUMBER", + "INVALID-CALLGATE", + "INVALID-ORDINAL", + "ALREADY-EXISTS", + "NO-CHILD-PROCESS", + "CHILD-ALIVE-NOWAIT", + "INVALID-FLAG-NUMBER", + "SEM-NOT-FOUND", + "INVALID-STARTING-CODESEG", + "INVALID-STACKSEG", + "INVALID-MODULETYPE", + "INVALID-EXE-SIGNATURE", + "EXE-MARKED-INVALID", + "BAD-EXE-FORMAT", + "ITERATED-DATA-EXCEEDS-64K", + "INVALID-MINALLOCSIZE", + "DYNLINK-FROM-INVALID-RING", + "IOPL-NOT-ENABLED", + "INVALID-SEGDPL", + "AUTODATASEG-EXCEEDS-64K", + "RING2SEG-MUST-BE-MOVABLE", + "RELOC-CHAIN-XEEDS-SEGLIM", + "INFLOOP-IN-RELOC-CHAIN", + "ENVVAR-NOT-FOUND", + "NOT-CURRENT-CTRY", + "NO-SIGNAL-SENT", + "FILENAME-EXCED-RANGE", + "RING2-STACK-IN-USE", + "META-EXPANSION-TOO-LONG", + "INVALID-SIGNAL-NUMBER", + "THREAD-1-INACTIVE", + "INFO-NOT-AVAIL", + "LOCKED", + "BAD-DYNALINK", + "TOO-MANY-MODULES", + "NESTING-NOT-ALLOWED", + "CANNOT-SHRINK", + "ZOMBIE-PROCESS", + "STACK-IN-HIGH-MEMORY", + "INVALID-EXITROUTINE-RING", + "GETBUF-FAILED", + "FLUSHBUF-FAILED", + "TRANSFER-TOO-LONG", + "FORCENOSWAP-FAILED", + "SMG-NO-TARGET-WINDOW", + "NO-CHILDREN", + "INVALID-SCREEN-GROUP", + "BAD-PIPE", + "PIPE-BUSY", + "NO-DATA", + "PIPE-NOT-CONNECTED", + "MORE-DATA", + "VC-DISCONNECTED", + "CIRCULARITY-REQUESTED", + "DIRECTORY-IN-CDS", + "INVALID-FSD-NAME", + "INVALID-PATH", + "INVALID-EA-NAME", + "EA-LIST-INCONSISTENT", + "EA-LIST-TOO-LONG", + "NO-META-MATCH", + "FINDNOTIFY-TIMEOUT", + "NO-MORE-ITEMS", + "SEARCH-STRUC-REUSED", + "CHAR-NOT-FOUND", + "TOO-MUCH-STACK", + "INVALID-ATTR", + "INVALID-STARTING-RING", + "INVALID-DLL-INIT-RING", + "CANNOT-COPY", + "DIRECTORY", + "OPLOCKED-FILE", + "OPLOCK-THREAD-EXISTS", + "VOLUME-CHANGED", + "FINDNOTIFY-HANDLE-IN-USE", + "FINDNOTIFY-HANDLE-CLOSED", + "NOTIFY-OBJECT-REMOVED", + "ALREADY-SHUTDOWN", + "EAS-DIDNT-FIT", + "EA-FILE-CORRUPT", + "EA-TABLE-FULL", + "INVALID-EA-HANDLE", + "NO-CLUSTER", + "CREATE-EA-FILE", + "CANNOT-OPEN-EA-FILE", + "EAS-NOT-SUPPORTED", + "NEED-EAS-FOUND", + "DUPLICATE-HANDLE", + "DUPLICATE-NAME", + "EMPTY-MUXWAIT", + "MUTEX-OWNED", + "NOT-OWNER", + "PARAM-TOO-SMALL", + "TOO-MANY-HANDLES", + "TOO-MANY-OPENS", + "WRONG-TYPE", + "UNUSED-CODE", + "THREAD-NOT-TERMINATED", + "INIT-ROUTINE-FAILED", + "MODULE-IN-USE", + "NOT-ENOUGH-WATCHPOINTS", + "TOO-MANY-POSTS", + "ALREADY-POSTED", + "ALREADY-RESET", + "SEM-BUSY", + "INVALID-PROCID", + "INVALID-PDELTA", + "NOT-DESCENDANT", + "NOT-SESSION-MANAGER", + "INVALID-PCLASS", + "INVALID-SCOPE", + "INVALID-THREADID", + "DOSSUB-SHRINK", + "DOSSUB-NOMEM", + "DOSSUB-OVERLAP", + "DOSSUB-BADSIZE", + "DOSSUB-BADFLAG", + "DOSSUB-BADSELECTOR", + "MR-MSG-TOO-LONG", + "MR-MID-NOT-FOUND", + "MR-UN-ACC-MSGF", + "MR-INV-MSGF-FORMAT", + "MR-INV-IVCOUNT", + "MR-UN-PERFORM", + "TS-WAKEUP", + "TS-SEMHANDLE", + "TS-NOTIMER", + "TS-HANDLE", + "TS-DATETIME", + "SYS-INTERNAL", + "QUE-CURRENT-NAME", + "QUE-PROC-NOT-OWNED", + "QUE-PROC-OWNED", + "QUE-DUPLICATE", + "QUE-ELEMENT-NOT-EXIST", + "QUE-NO-MEMORY", + "QUE-INVALID-NAME", + "QUE-INVALID-PRIORITY", + "QUE-INVALID-HANDLE", + "QUE-LINK-NOT-FOUND", + "QUE-MEMORY-ERROR", + "QUE-PREV-AT-END", + "QUE-PROC-NO-ACCESS", + "QUE-EMPTY", + "QUE-NAME-NOT-EXIST", + "QUE-NOT-INITIALIZED", + "QUE-UNABLE-TO-ACCESS", + "QUE-UNABLE-TO-ADD", + "QUE-UNABLE-TO-INIT", + "VIO-INVALID-MASK", + "VIO-PTR", + "VIO-APTR", + "VIO-RPTR", + "VIO-CPTR", + "VIO-LPTR", + "VIO-MODE", + "VIO-WIDTH", + "VIO-ATTR", + "VIO-ROW", + "VIO-COL", + "VIO-TOPROW", + "VIO-BOTROW", + "VIO-RIGHTCOL", + "VIO-LEFTCOL", + "SCS-CALL", + "SCS-VALUE", + "VIO-WAIT-FLAG", + "VIO-UNLOCK", + "SGS-NOT-SESSION-MGR", + "SMG-INVALID-SESSION-ID", + "SMG-NO-SESSIONS", + "SMG-SESSION-NOT-FOUND", + "SMG-SET-TITLE", + "KBD-PARAMETER", + "KBD-NO-DEVICE", + "KBD-INVALID-IOWAIT", + "KBD-INVALID-LENGTH", + "KBD-INVALID-ECHO-MASK", + "KBD-INVALID-INPUT-MASK", + "MON-INVALID-PARMS", + "MON-INVALID-DEVNAME", + "MON-INVALID-HANDLE", + "MON-BUFFER-TOO-SMALL", + "MON-BUFFER-EMPTY", + "MON-DATA-TOO-LARGE", + "MOUSE-NO-DEVICE", + "MOUSE-INV-HANDLE", + "MOUSE-INV-PARMS", + "MOUSE-CANT-RESET", + "MOUSE-DISPLAY-PARMS", + "MOUSE-INV-MODULE", + "MOUSE-INV-ENTRY-PT", + "MOUSE-INV-MASK", + "MOUSE-NO-DATA", + "MOUSE-PTR-DRAWN", + "INVALID-FREQUENCY", + "NLS-NO-COUNTRY-FILE", + "NLS-OPEN-FAILED", + "NO-COUNTRY-OR-CODEPAGE", + "NLS-TABLE-TRUNCATED", + "NLS-BAD-TYPE", + "NLS-TYPE-NOT-FOUND", + "VIO-SMG-ONLY", + "VIO-INVALID-ASCIIZ", + "VIO-DEREGISTER", + "VIO-NO-POPUP", + "VIO-EXISTING-POPUP", + "KBD-SMG-ONLY", + "KBD-INVALID-ASCIIZ", + "KBD-INVALID-MASK", + "KBD-REGISTER", + "KBD-DEREGISTER", + "MOUSE-SMG-ONLY", + "MOUSE-INVALID-ASCIIZ", + "MOUSE-INVALID-MASK", + "MOUSE-REGISTER", + "MOUSE-DEREGISTER", + "SMG-BAD-ACTION", + "SMG-INVALID-CALL", + "SCS-SG-NOTFOUND", + "SCS-NOT-SHELL", + "VIO-INVALID-PARMS", + "VIO-FUNCTION-OWNED", + "VIO-RETURN", + "SCS-INVALID-FUNCTION", + "SCS-NOT-SESSION-MGR", + "VIO-REGISTER", + "VIO-NO-MODE-THREAD", + "VIO-NO-SAVE-RESTORE-THD", + "VIO-IN-BG", + "VIO-ILLEGAL-DURING-POPUP", + "SMG-NOT-BASESHELL", + "SMG-BAD-STATUSREQ", + "QUE-INVALID-WAIT", + "VIO-LOCK", + "MOUSE-INVALID-IOWAIT", + "VIO-INVALID-HANDLE", + "VIO-ILLEGAL-DURING-LOCK", + "VIO-INVALID-LENGTH", + "KBD-INVALID-HANDLE", + "KBD-NO-MORE-HANDLE", + "KBD-CANNOT-CREATE-KCB", + "KBD-CODEPAGE-LOAD-INCOMPL", + "KBD-INVALID-CODEPAGE-ID", + "KBD-NO-CODEPAGE-SUPPORT", + "KBD-FOCUS-REQUIRED", + "KBD-FOCUS-ALREADY-ACTIVE", + "KBD-KEYBOARD-BUSY", + "KBD-INVALID-CODEPAGE", + "KBD-UNABLE-TO-FOCUS", + "SMG-SESSION-NON-SELECT", + "SMG-SESSION-NOT-FOREGRND", + "SMG-SESSION-NOT-PARENT", + "SMG-INVALID-START-MODE", + "SMG-INVALID-RELATED-OPT", + "SMG-INVALID-BOND-OPTION", + "SMG-INVALID-SELECT-OPT", + "SMG-START-IN-BACKGROUND", + "SMG-INVALID-STOP-OPTION", + "SMG-BAD-RESERVE", + "SMG-PROCESS-NOT-PARENT", + "SMG-INVALID-DATA-LENGTH", + "SMG-NOT-BOUND", + "SMG-RETRY-SUB-ALLOC", + "KBD-DETACHED", + "VIO-DETACHED", + "MOU-DETACHED", + "VIO-FONT", + "VIO-USER-FONT", + "VIO-BAD-CP", + "VIO-NO-CP", + "VIO-NA-CP", + "INVALID-CODE-PAGE", + "CPLIST-TOO-SMALL", + "CP-NOT-MOVED", + "MODE-SWITCH-INIT", + "CODE-PAGE-NOT-FOUND", + "UNEXPECTED-SLOT-RETURNED", + "SMG-INVALID-TRACE-OPTION", + "VIO-INTERNAL-RESOURCE", + "VIO-SHELL-INIT", + "SMG-NO-HARD-ERRORS", + "CP-SWITCH-INCOMPLETE", + "VIO-TRANSPARENT-POPUP", + "CRITSEC-OVERFLOW", + "CRITSEC-UNDERFLOW", + "VIO-BAD-RESERVE", + "INVALID-ADDRESS", + "ZERO-SELECTORS-REQUESTED", + "NOT-ENOUGH-SELECTORS-AVA", + "INVALID-SELECTOR", + "SMG-INVALID-PROGRAM-TYPE", + "SMG-INVALID-PGM-CONTROL", + "SMG-INVALID-INHERIT-OPT", + "VIO-EXTENDED-SG", + "VIO-NOT-PRES-MGR-SG", + "VIO-SHIELD-OWNED", + "VIO-NO-MORE-HANDLES", + "VIO-SEE-ERROR-LOG", + "VIO-ASSOCIATED-DC", + "KBD-NO-CONSOLE", + "MOUSE-NO-CONSOLE", + "MOUSE-INVALID-HANDLE", + "SMG-INVALID-DEBUG-PARMS", + "KBD-EXTENDED-SG", + "MOU-EXTENDED-SG", + "SMG-INVALID-ICON-FILE", + "TRC-PID-NON-EXISTENT", + "TRC-COUNT-ACTIVE", + "TRC-SUSPENDED-BY-COUNT", + "TRC-COUNT-INACTIVE", + "TRC-COUNT-REACHED", + "NO-MC-TRACE", + "MC-TRACE", + "TRC-COUNT-ZERO", + "SMG-TOO-MANY-DDS", + "SMG-INVALID-NOTIFICATION", + "LF-INVALID-FUNCTION", + "LF-NOT-AVAIL", + "LF-SUSPENDED", + "LF-BUF-TOO-SMALL", + "LF-BUFFER-FULL", + "LF-INVALID-RECORD", + "LF-INVALID-SERVICE", + "LF-GENERAL-FAILURE", + "LF-INVALID-ID", + "LF-INVALID-HANDLE", + "LF-NO-ID-AVAIL", + "LF-TEMPLATE-AREA-FULL", + "LF-ID-IN-USE", + "MOU-NOT-INITIALIZED", + "MOUINITREAL-DONE", + "DOSSUB-CORRUPTED", + "MOUSE-CALLER-NOT-SUBSYS", + "ARITHMETIC-OVERFLOW", + "TMR-NO-DEVICE", + "TMR-INVALID-TIME", + "PVW-INVALID-ENTITY", + "PVW-INVALID-ENTITY-TYPE", + "PVW-INVALID-SPEC", + "PVW-INVALID-RANGE-TYPE", + "PVW-INVALID-COUNTER-BLK", + "PVW-INVALID-TEXT-BLK", + "PRF-NOT-INITIALIZED", + "PRF-ALREADY-INITIALIZED", + "PRF-NOT-STARTED", + "PRF-ALREADY-STARTED", + "PRF-TIMER-OUT-OF-RANGE", + "PRF-TIMER-RESET", + "VDD-LOCK-USEAGE-DENIED", + "TIMEOUT", + "VDM-DOWN", + "VDM-LIMIT", + "VDD-NOT-FOUND", + "INVALID-CALLER", + "PID-MISMATCH", + "INVALID-VDD-HANDLE", + "VLPT-NO-SPOOLER", + "VCOM-DEVICE-BUSY", + "VLPT-DEVICE-BUSY", + "NESTING-TOO-DEEP", + "VDD-MISSING", + "BIDI-INVALID-LENGTH", + "BIDI-INVALID-INCREMENT", + "BIDI-INVALID-COMBINATION", + "BIDI-INVALID-RESERVED", + "BIDI-INVALID-EFFECT", + "BIDI-INVALID-CSDREC", + "BIDI-INVALID-CSDSTATE", + "BIDI-INVALID-LEVEL", + "BIDI-INVALID-TYPE-SUPPORT", + "BIDI-INVALID-ORIENTATION", + "BIDI-INVALID-NUM-SHAPE", + "BIDI-INVALID-CSD", + "BIDI-NO-SUPPORT", + "BIDI-RW-INCOMPLETE", + "IMP-INVALID-PARM", + "IMP-INVALID-LENGTH", + "HPFS-DISK-ERROR-WARN", + "MON-BAD-BUFFER", + "MODULE-CORRUPTED", + "SM-OUTOF-SWAPFILE", + "LF-TIMEOUT", + "LF-SUSPEND-SUCCESS", + "LF-RESUME-SUCCESS", + "LF-REDIRECT-SUCCESS", + "LF-REDIRECT-FAILURE", + "SWAPPER-NOT-ACTIVE", + "INVALID-SWAPID", + "IOERR-SWAP-FILE", + "SWAP-TABLE-FULL", + "SWAP-FILE-FULL", + "CANT-INIT-SWAPPER", + "SWAPPER-ALREADY-INIT", + "PMM-INSUFFICIENT-MEMORY", + "PMM-INVALID-FLAGS", + "PMM-INVALID-ADDRESS", + "PMM-LOCK-FAILED", + "PMM-UNLOCK-FAILED", + "PMM-MOVE-INCOMPLETE", + "UCOM-DRIVE-RENAMED", + "UCOM-FILENAME-TRUNCATED", + "UCOM-BUFFER-LENGTH", + "MON-CHAIN-HANDLE", + "MON-NOT-REGISTERED", + "SMG-ALREADY-TOP", + "PMM-ARENA-MODIFIED", + "SMG-PRINTER-OPEN", + "PMM-SET-FLAGS-FAILED", + "INVALID-DOS-DD", + "BLOCKED", + "NOBLOCK", + "INSTANCE-SHARED", + "NO-OBJECT", + "PARTIAL-ATTACH", + "INCACHE", + "SWAP-IO-PROBLEMS", + "CROSSES-OBJECT-BOUNDARY", + "LONGLOCK", + "SHORTLOCK", + "UVIRTLOCK", + "ALIASLOCK", + "ALIAS", + "NO-MORE-HANDLES", + "SCAN-TERMINATED", + "TERMINATOR-NOT-FOUND", + "NOT-DIRECT-CHILD", + "DELAY-FREE", + "GUARDPAGE", + "SWAPERROR", + "LDRERROR", + "NOMEMORY", + "NOACCESS", + "NO-DLL-TERM", + "CPSIO-CODE-PAGE-INVALID", + "CPSIO-NO-SPOOLER", + "CPSIO-FONT-ID-INVALID", + "CPSIO-INTERNAL-ERROR", + "CPSIO-INVALID-PTR-NAME", + "CPSIO-NOT-ACTIVE", + "CPSIO-PID-FULL", + "CPSIO-PID-NOT-FOUND", + "CPSIO-READ-CTL-SEQ", + "CPSIO-READ-FNT-DEF", + "CPSIO-WRITE-ERROR", + "CPSIO-WRITE-FULL-ERROR", + "CPSIO-WRITE-HANDLE-BAD", + "CPSIO-SWIT-LOAD", + "CPSIO-INV-COMMAND", + "CPSIO-NO-FONT-SWIT", + "ENTRY-IS-CALLGATE", + "UNKNOWN" +}; + +void +OS_syserr_names (unsigned int * length, unsigned char *** names) +{ + (*length) = ((sizeof (syserr_names_table)) / (sizeof (char *))); + (*names) = ((unsigned char **) syserr_names_table); +} diff --git a/v7/src/microcode/os2tty.c b/v7/src/microcode/os2tty.c new file mode 100644 index 000000000..804e13b30 --- /dev/null +++ b/v7/src/microcode/os2tty.c @@ -0,0 +1,96 @@ +/* -*-C-*- + +$Id: os2tty.c,v 1.1 1994/11/28 03:43:02 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "os2.h" +#include "ostty.h" +#ifdef USE_PMIO +#include +#endif + +static Tchannel input_channel; +static Tchannel output_channel; + +void +OS2_initialize_tty (void) +{ + extern Tchannel EXFUN (OS_open_fd, (int fd)); + input_channel = (OS2_make_channel (0, CHANNEL_READ)); + (CHANNEL_INTERNAL (input_channel)) = 1; + output_channel = (OS2_make_channel (1, CHANNEL_WRITE)); + (CHANNEL_INTERNAL (output_channel)) = 1; +} + +Tchannel +OS_tty_input_channel (void) +{ + return (input_channel); +} + +Tchannel +OS_tty_output_channel (void) +{ + return (output_channel); +} + +unsigned int +OS_tty_x_size (void) +{ +#ifdef USE_PMIO + return (get_screen_width ()); +#else + return (80); +#endif +} + +unsigned int +OS_tty_y_size (void) +{ +#ifdef USE_PMIO + return (get_screen_height ()); +#else + return (24); +#endif +} + +const char * +OS_tty_command_beep (void) +{ + return ("\a"); +} + +const char * +OS_tty_command_clear (void) +{ + return ("\f"); +} diff --git a/v7/src/microcode/pros2fs.c b/v7/src/microcode/pros2fs.c new file mode 100644 index 000000000..596d52d7c --- /dev/null +++ b/v7/src/microcode/pros2fs.c @@ -0,0 +1,369 @@ +/* -*-C-*- + +$Id: pros2fs.c,v 1.1 1994/11/28 03:43:02 cph Exp $ + +Copyright (c) 1994 Massachusetts Institute of Technology + +This material was developed by the Scheme project at the Massachusetts +Institute of Technology, Department of Electrical Engineering and +Computer Science. Permission to copy this software, to redistribute +it, and to use it for any purpose is granted, subject to the following +restrictions and understandings. + +1. Any copy made of this software must include this copyright notice +in full. + +2. Users of this software agree to make their best efforts (a) to +return to the MIT Scheme project any improvements or extensions that +they make, so that these may be included in future releases; and (b) +to inform MIT of noteworthy uses of this software. + +3. All materials developed as a consequence of the use of this +software shall duly acknowledge such use, in accordance with the usual +standards of acknowledging credit in academic research. + +4. MIT has made no warrantee or representation that the operation of +this software will be error-free, and MIT is under no obligation to +provide any services, by way of maintenance, update, or otherwise. + +5. In conjunction with products arising from the use of this material, +there shall be no use of the name of the Massachusetts Institute of +Technology nor of any adaptation thereof in any advertising, +promotional, or sales literature without prior written consent from +MIT in each case. */ + +#include "scheme.h" +#undef END_OF_CHAIN +#include "prims.h" +#include "os2.h" +#include "osfs.h" + +extern FILESTATUS3 * OS2_read_file_status (const char *); +extern void OS2_write_file_status (const char *, FILESTATUS3 *); + +#ifndef FILE_TOUCH_OPEN_TRIES +#define FILE_TOUCH_OPEN_TRIES 5 +#endif + +static SCHEME_OBJECT time_to_integer (FDATE *, FTIME *); +static void integer_to_time (SCHEME_OBJECT, FDATE *, FTIME *); +static SCHEME_OBJECT file_touch (const char *); +static void protect_handle (LHANDLE); + +DEFINE_PRIMITIVE ("FILE-ATTRIBUTES", Prim_file_attributes, 1, 1, + "Return attributes of FILE, as an integer.") +{ + PRIMITIVE_HEADER (1); + { + FILESTATUS3 * info = (OS2_read_file_status (STRING_ARG (1))); + PRIMITIVE_RETURN + ((info == 0) + ? SHARP_F + : (LONG_TO_UNSIGNED_FIXNUM (info -> attrFile))); + } +} + +DEFINE_PRIMITIVE ("SET-FILE-ATTRIBUTES!", Prim_set_file_attributes, 2, 2, + "Set the attributes of FILE to ATTRIBUTES.") +{ + PRIMITIVE_HEADER (2); + { + FILESTATUS3 * info = (OS2_read_file_status (STRING_ARG (1))); + if (info == 0) + error_bad_range_arg (1); + (info -> attrFile) = (arg_index_integer (2, 0x10000)); + OS2_write_file_status ((STRING_ARG (1)), info); + PRIMITIVE_RETURN (UNSPECIFIC); + } +} + +DEFINE_PRIMITIVE ("FILE-LENGTH", Prim_file_length, 1, 1, + "Return attributes of FILE, as an integer.") +{ + PRIMITIVE_HEADER (1); + { + FILESTATUS3 * info = (OS2_read_file_status (STRING_ARG (1))); + PRIMITIVE_RETURN + ((info == 0) + ? SHARP_F + : (LONG_TO_UNSIGNED_FIXNUM (info -> cbFile))); + } +} + +DEFINE_PRIMITIVE ("GET-ENVIRONMENT-VARIABLE", Prim_get_environment_variable, 1, 1, + "Look up the value of a variable in the user's shell environment.\n\ +The argument, a variable name, must be a string.\n\ +The result is either a string (the variable's value),\n\ + or #F indicating that the variable does not exist.") +{ + PRIMITIVE_HEADER (1); + { + PSZ result; + XTD_API_CALL + (dos_scan_env, ((STRING_ARG (1)), (& result)), + { + if (rc == ERROR_ENVVAR_NOT_FOUND) + PRIMITIVE_RETURN (SHARP_F); + }); + PRIMITIVE_RETURN (char_pointer_to_string (result)); + } +} + +DEFINE_PRIMITIVE ("FILE-EQ?", Prim_file_eq_p, 2, 2, + "True iff the two file arguments are the same file.") +{ + PRIMITIVE_HEADER (2); + CHECK_ARG (1, STRING_P); + CHECK_ARG (2, STRING_P); + { + unsigned long length = (STRING_LENGTH (ARG_REF (1))); + const char * s1 = (STRING_LOC ((ARG_REF (1)), 0)); + const char * s2 = (STRING_LOC ((ARG_REF (2)), 0)); + const char * e1 = (s1 + length); + if ((STRING_LENGTH (ARG_REF (2))) != length) + PRIMITIVE_RETURN (SHARP_F); + while (s1 < e1) + if ((char_upcase (*s1++)) != (char_upcase (*s2++))) + PRIMITIVE_RETURN (SHARP_F); + PRIMITIVE_RETURN (SHARP_T); + } +} + +DEFINE_PRIMITIVE ("FILE-MOD-TIME", Prim_file_mod_time, 1, 1, 0) +{ + PRIMITIVE_HEADER (1); + { + FILESTATUS3 * info = (OS2_read_file_status (STRING_ARG (1))); + PRIMITIVE_RETURN + ((info == 0) + ? SHARP_F + : (time_to_integer ((& (info -> fdateLastWrite)), + (& (info -> ftimeLastWrite))))); + } +} + +DEFINE_PRIMITIVE ("FILE-ACCESS-TIME", Prim_file_acc_time, 1, 1, 0) +{ + PRIMITIVE_HEADER (1); + { + FILESTATUS3 * info = (OS2_read_file_status (STRING_ARG (1))); + PRIMITIVE_RETURN + ((info == 0) + ? SHARP_F + : (time_to_integer ((& (info -> fdateLastAccess)), + (& (info -> ftimeLastAccess))))); + } +} + +DEFINE_PRIMITIVE ("SET-FILE-TIMES!", Prim_set_file_times, 3, 3, + "Change the access and modification times of FILE.\n\ +The second and third arguments are the respective times.\n\ +The file must exist and you must be the owner (or superuser).") +{ + PRIMITIVE_HEADER (3); + { + FILESTATUS3 * info = (OS2_read_file_status (STRING_ARG (1))); + SCHEME_OBJECT atime = (ARG_REF (2)); + SCHEME_OBJECT mtime = (ARG_REF (3)); + if (info == 0) + error_bad_range_arg (1); + if (atime != SHARP_F) + { + if (!INTEGER_P (atime)) + error_wrong_type_arg (2); + if (integer_negative_p (atime)) + error_bad_range_arg (2); + integer_to_time (atime, + (& (info -> fdateLastAccess)), + (& (info -> ftimeLastAccess))); + } + if (mtime != SHARP_F) + { + if (!INTEGER_P (mtime)) + error_wrong_type_arg (3); + if (integer_negative_p (mtime)) + error_bad_range_arg (3); + integer_to_time (mtime, + (& (info -> fdateLastWrite)), + (& (info -> ftimeLastWrite))); + } + OS2_write_file_status ((STRING_ARG (1)), info); + } + PRIMITIVE_RETURN (UNSPECIFIC); +} + +DEFINE_PRIMITIVE ("FILE-TOUCH", Prim_file_touch, 1, 1, + "Given a file name, change the times of the file to the current time.\n\ +If the file does not exist, create it.\n\ +Both the access time and modification time are changed.\n\ +Return #F if the file existed and its time was modified.\n\ +Otherwise the file did not exist and it was created.") +{ + PRIMITIVE_HEADER (1); + PRIMITIVE_RETURN (file_touch ((CONST char *) (STRING_ARG (1)))); +} + +static SCHEME_OBJECT +time_to_integer (FDATE * date, FTIME * time) +{ + unsigned long id; + unsigned long it; + id = (date -> year); + id = ((id << 4) | (date -> month)); + id = ((id << 5) | (date -> day)); + it = (time -> hours); + it = ((it << 6) | (time -> minutes)); + it = ((it << 5) | (time -> twosecs)); + return + (integer_add ((integer_multiply ((LONG_TO_UNSIGNED_FIXNUM (id)), + (LONG_TO_UNSIGNED_FIXNUM (0x10000)))), + (LONG_TO_UNSIGNED_FIXNUM (it)))); +} + +static void +integer_to_time (SCHEME_OBJECT encoding, FDATE * date, FTIME * time) +{ + unsigned long id; + unsigned long it; + { + SCHEME_OBJECT q; + SCHEME_OBJECT r; + (void) integer_divide + (encoding, (LONG_TO_UNSIGNED_FIXNUM (0x10000)), (&q), (&r)); + it = (UNSIGNED_FIXNUM_TO_LONG (r)); + /* If encoding is larger than 32 bits, ignore MS bits. */ + (void) integer_divide + (q, (LONG_TO_UNSIGNED_FIXNUM (0x10000)), (&q), (&r)); + id = (UNSIGNED_FIXNUM_TO_LONG (r)); + } + (date -> day) = (id & 0x1f); + id >>= 5; + (date -> month) = (id & 0x0f); + id >>= 4; + (date -> year) = id; + (time -> twosecs) = (it & 0x1f); + it >>= 5; + (time -> minutes) = (it & 0x3f); + it >>= 6; + (time -> hours) = it; +} + +static SCHEME_OBJECT +file_touch (const char * filename) +{ + HFILE handle; + ULONG action; + APIRET rc; + unsigned int count = 0; + + transaction_begin (); + while (1) + { + APIRET rc + = (dos_open (((char *) filename), + (&handle), + (&action), + 0, + FILE_NORMAL, + (OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW), + (OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE), + 0)); + if (rc == NO_ERROR) + break; + if ((rc != NO_ERROR) + && (rc != ERROR_FILE_NOT_FOUND) + && (rc != ERROR_PATH_NOT_FOUND) + && ((++ count) >= FILE_TOUCH_OPEN_TRIES)) + OS2_error_system_call (rc, syscall_dos_open); + } + protect_handle (handle); + if (action == FILE_CREATED) + { + transaction_commit (); + return (SHARP_T); + } + /* Existing file -- we'll write something to it to make sure that it + has its times updated properly upon close. This was needed for + unix implementation, but it is not known whether it is needed in + OS/2. In any case, it does no harm to do this. */ + { + FILESTATUS3 info; + char buffer [1]; + ULONG n; + STD_API_CALL (dos_query_file_info, + (handle, FIL_STANDARD, (& info), (sizeof (info)))); + if ((info . cbFile) == 0) + { + /* Zero-length file: write a byte, then reset the length. */ + (buffer[0]) = '\0'; + STD_API_CALL (dos_write, (handle, buffer, 1, (& n))); + STD_API_CALL (dos_set_file_size, (handle, 0)); + } + else + { + /* Read the first byte, then write it back in place. */ + STD_API_CALL (dos_read, (handle, buffer, 1, (&n))); + STD_API_CALL (dos_set_file_ptr, (handle, 0, FILE_BEGIN, (& n))); + STD_API_CALL (dos_write, (handle, buffer, 1, (& n))); + } + } + transaction_commit (); + return (SHARP_F); +} + +static void +protect_handle_1 (void * hp) +{ + (void) dos_close (* ((LHANDLE *) hp)); +} + +static void +protect_handle (LHANDLE h) +{ + LHANDLE * hp = (dstack_alloc (sizeof (LHANDLE))); + (*hp) = h; + transaction_record_action (tat_always, protect_handle_1, hp); +} + +DEFINE_PRIMITIVE ("FILE-INFO", Prim_file_info, 1, 1, + "Given a file name, return information about the file.\n\ +If the file exists and its information is accessible,\n\ + the result is a vector of 6 items.\n\ +Otherwise the result is #F.") +{ + FILESTATUS3 * info; + SCHEME_OBJECT result; + SCHEME_OBJECT modes; + PRIMITIVE_HEADER (1); + + info = (OS2_read_file_status (STRING_ARG (1))); + if (info == 0) + PRIMITIVE_RETURN (SHARP_F); + result = (allocate_marked_vector (TC_VECTOR, 6, true)); + modes = (allocate_string (5)); + VECTOR_SET (result, 0, + ((((info -> attrFile) & FILE_DIRECTORY) != 0) + ? SHARP_T + : SHARP_F)); + VECTOR_SET (result, 1, + (time_to_integer ((& (info -> fdateLastAccess)), + (& (info -> ftimeLastAccess))))); + VECTOR_SET (result, 2, + (time_to_integer ((& (info -> fdateLastWrite)), + (& (info -> ftimeLastWrite))))); + VECTOR_SET (result, 3, + (time_to_integer ((& (info -> fdateCreation)), + (& (info -> ftimeCreation))))); + VECTOR_SET (result, 4, (long_to_integer (info -> cbFile))); + { + unsigned int attr = (info -> attrFile); + char * s = ((char *) (STRING_LOC (modes, 0))); + (s[0]) = (((attr & FILE_READONLY) != 0) ? 'r' : '_'); + (s[1]) = (((attr & FILE_HIDDEN) != 0) ? 'h' : '_'); + (s[2]) = (((attr & FILE_SYSTEM) != 0) ? 's' : '_'); + (s[3]) = (((attr & FILE_ARCHIVED) != 0) ? 'a' : '_'); + (s[4]) = (((attr & FILE_DIRECTORY) != 0) ? 'd' : '_'); + } + VECTOR_SET (result, 5, modes); + PRIMITIVE_RETURN (result); +}