home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / ntsig.c < prev    next >
C/C++ Source or Header  |  2000-12-05  |  12KB  |  508 lines

  1. /* -*-C-*-
  2.  
  3. $Id: ntsig.c,v 1.22 2000/12/05 21:23:45 cph Exp $
  4.  
  5. Copyright (c) 1992-2000 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22.  
  23. /* Hacks by SRA for NT:
  24.     1. punt interactive debugging completely
  25. */
  26.  
  27. #include "scheme.h"
  28. #include "critsec.h"
  29. #include "ossig.h"
  30. #include "osctty.h"
  31. #include "ostty.h"
  32. #include "nt.h"
  33. #include "ntgui.h"
  34. #include "ntio.h"
  35. #include "ntscmlib.h"
  36. #include "ntscreen.h"
  37. #include "ntsys.h"
  38.  
  39. extern HANDLE master_tty_window;
  40.  
  41. /* Signal mask manipulation */
  42.  
  43. /* These could be implemented, at least under Win32s/DPMI
  44.    by examining and setting the virtual interrupt state.
  45.  */
  46.  
  47. void
  48. DEFUN_VOID (preserve_signal_mask)
  49. {
  50.   return;
  51. }
  52.  
  53. void
  54. DEFUN_VOID (block_signals)
  55. {
  56.   return;
  57. }
  58.  
  59. void
  60. DEFUN_VOID (unblock_signals)
  61. {
  62.   return;
  63. }
  64.  
  65. #define CONTROL_B_INTERRUPT_CHAR    'B'
  66. #define CONTROL_G_INTERRUPT_CHAR    'G'
  67. #define CONTROL_U_INTERRUPT_CHAR    'U'
  68. #define CONTROL_X_INTERRUPT_CHAR    'X'
  69. #define INTERACTIVE_INTERRUPT_CHAR    '!'
  70. #define TERMINATE_INTERRUPT_CHAR    '@'
  71. #define NO_INTERRUPT_CHAR        '0'
  72.  
  73. /* Keyboard interrupt */
  74.  
  75. #define KB_INT_TABLE_SIZE        ((256) + 1)
  76.  
  77. #define CONTROL_BREAK            '\0'        /* A lie. */
  78. #define CONTROL_B            '\002'
  79. #define CONTROL_C            '\003'
  80. #define CONTROL_G            '\007'
  81. #define CONTROL_U            '\025'
  82. #define CONTROL_X            '\030'
  83.  
  84. #define CONTROL_B_ENABLE        (0x1)
  85. #define CONTROL_G_ENABLE        (0x2)
  86. #define CONTROL_U_ENABLE        (0x4)
  87. #define CONTROL_X_ENABLE        (0x8)
  88. #define INTERACTIVE_INTERRUPT_ENABLE    (0x10)
  89. #define TERMINATE_INTERRUPT_ENABLE    (0x20)
  90.  
  91. /* This is a table and also a null terminated string. */
  92. unsigned char keyboard_interrupt_table[KB_INT_TABLE_SIZE];
  93. static unsigned char keyboard_interrupt_enables;
  94.  
  95. void
  96. DEFUN (OS_ctty_get_interrupt_enables, (mask), Tinterrupt_enables * mask)
  97. {
  98.   *mask = ((Tinterrupt_enables) keyboard_interrupt_enables);
  99.   return;
  100. }
  101.  
  102. void
  103. DEFUN (OS_ctty_set_interrupt_enables, (mask), Tinterrupt_enables * mask)
  104. {
  105.   /* Kludge: ctl-break always enabled. */
  106.   keyboard_interrupt_enables = (((unsigned char) (* mask))
  107.                 | TERMINATE_INTERRUPT_ENABLE);
  108.   return;
  109. }
  110.  
  111. /* This is a temporary kludge. */
  112.  
  113. #define NUM_INT_CHANNELS 6
  114.  
  115. static cc_t int_chars[NUM_INT_CHANNELS];
  116. static cc_t int_handlers[NUM_INT_CHANNELS];
  117.  
  118. #define SCREEN_COMMAND_INTERRUPT_FIRST (SCREEN_COMMAND_CLOSE+10)
  119.  
  120. int EXFUN (signal_keyboard_character_interrupt, (int));
  121.  
  122. LRESULT
  123. master_tty_interrupt (HWND tty, WORD command)
  124. {
  125.   int ch = int_chars[command - SCREEN_COMMAND_INTERRUPT_FIRST];
  126.   return (signal_keyboard_character_interrupt (ch));
  127. }
  128.  
  129. static void
  130. DEFUN_VOID (update_interrupt_characters)
  131. {
  132.   int i;
  133.  
  134.   for (i = 0; i < KB_INT_TABLE_SIZE; i++)
  135.   {
  136.     keyboard_interrupt_table[i] = NO_INTERRUPT_CHAR;
  137.     SendMessage (master_tty_window, SCREEN_SETBINDING, i, 0);
  138.   }
  139.  
  140.   for (i = 0; i < NUM_INT_CHANNELS; i++)
  141.   {
  142.     unsigned char handler;
  143.  
  144.     switch (int_handlers[i])
  145.     {
  146.       case interrupt_handler_control_b:
  147.         handler = CONTROL_B_INTERRUPT_CHAR;
  148.     break;
  149.  
  150.       case interrupt_handler_control_g:
  151.         handler = CONTROL_G_INTERRUPT_CHAR;
  152.     break;
  153.  
  154.       case interrupt_handler_control_u:
  155.         handler = CONTROL_U_INTERRUPT_CHAR;
  156.     break;
  157.  
  158.       case interrupt_handler_control_x:
  159.         handler = CONTROL_X_INTERRUPT_CHAR;
  160.     break;
  161.  
  162.       case interrupt_handler_interactive:
  163.         handler = INTERACTIVE_INTERRUPT_CHAR;
  164.     break;
  165.  
  166.       case interrupt_handler_terminate:
  167.     handler = TERMINATE_INTERRUPT_CHAR;
  168.     break;
  169.  
  170.       default:
  171.         handler = NO_INTERRUPT_CHAR;
  172.     break;
  173.     }
  174.     keyboard_interrupt_table[(int) (int_chars[i])] = handler;
  175.  
  176.     SendMessage (master_tty_window,
  177.          SCREEN_SETCOMMAND,
  178.                  (SCREEN_COMMAND_INTERRUPT_FIRST + i),
  179.          (LPARAM) master_tty_interrupt);
  180.  
  181.     SendMessage (master_tty_window,
  182.          SCREEN_SETBINDING,
  183.                  int_chars[i],
  184.          (SCREEN_COMMAND_INTERRUPT_FIRST + i));
  185.   }
  186.   return;
  187. }
  188.  
  189. unsigned int
  190. DEFUN_VOID (OS_ctty_num_int_chars)
  191. {
  192.   return (NUM_INT_CHANNELS);
  193. }
  194.  
  195. cc_t *
  196. DEFUN_VOID (OS_ctty_get_int_chars)
  197. {
  198.   return (&int_chars[0]);
  199. }
  200.  
  201. void
  202. DEFUN (OS_ctty_set_int_chars, (new_int_chars), cc_t * new_int_chars)
  203. {
  204.   int i;
  205.  
  206.   for (i = 0; i < NUM_INT_CHANNELS; i++)
  207.     int_chars[i] = new_int_chars[i];
  208.   update_interrupt_characters ();
  209.   return;
  210. }
  211.  
  212. cc_t *
  213. DEFUN_VOID (OS_ctty_get_int_char_handlers)
  214. {
  215.   return (&int_handlers[0]);
  216. }
  217.  
  218. void
  219. DEFUN (OS_ctty_set_int_char_handlers, (new_int_handlers),
  220.        cc_t * new_int_handlers)
  221. {
  222.   int i;
  223.  
  224.   for (i = 0; i < NUM_INT_CHANNELS; i++)
  225.     int_handlers[i] = new_int_handlers[i];
  226.   update_interrupt_characters ();
  227.   return;
  228. }
  229.  
  230. static void
  231. DEFUN (console_write_string, (string), unsigned char * string)
  232. {
  233.   outf_console ("%s", string);
  234.   outf_flush_console ();
  235.   return;
  236. }
  237.  
  238. static void
  239. DEFUN_VOID (initialize_keyboard_interrupt_table)
  240. {
  241.   /* Set up default interrupt characters */
  242.   int_chars[0] = CONTROL_B;
  243.   int_handlers[0] = ((unsigned char) interrupt_handler_control_b);
  244.   int_chars[1] = CONTROL_G;
  245.   int_handlers[1] = ((unsigned char) interrupt_handler_control_g);
  246.   int_chars[2] = CONTROL_U;
  247.   int_handlers[2] = ((unsigned char) interrupt_handler_control_u);
  248.   int_chars[3] = CONTROL_X;
  249.   int_handlers[3] = ((unsigned char) interrupt_handler_control_x);
  250.   int_chars[4] = CONTROL_C;
  251.   int_handlers[4] = ((unsigned char) interrupt_handler_interactive);
  252.   int_chars[5] = CONTROL_BREAK;
  253.   int_handlers[5] = ((unsigned char) interrupt_handler_terminate);
  254.   keyboard_interrupt_enables =
  255.     (CONTROL_B_ENABLE | CONTROL_G_ENABLE
  256.      | CONTROL_U_ENABLE | CONTROL_X_ENABLE
  257.      | INTERACTIVE_INTERRUPT_ENABLE
  258.      | TERMINATE_INTERRUPT_ENABLE);
  259.   update_interrupt_characters ();
  260.   return;
  261. }
  262.  
  263. static int hard_attn_limit = 2;
  264. static int hard_attn_counter = 0;
  265.  
  266. cc_t
  267. DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char)
  268. {
  269.   /* Scheme got a keyboard interrupt, reset the hard attention counter. */
  270.   hard_attn_counter = 0;
  271.   return (int_char);
  272. }
  273.  
  274. static void
  275. DEFUN_VOID (print_interrupt_help)
  276. {
  277.   console_write_string (
  278.     "\r\nInterrupt choices are:\r\n"
  279.     "C-G interrupt:   ^G (abort to top level)\r\n"
  280.     "C-X interrupt:   ^x (abort)\r\n"
  281.     "C-B interrupt:   ^B (break)\r\n"
  282.     "C-U interrupt:   ^U (up)\r\n"
  283.     "(exit) to exit Scheme\r\n"
  284.     );
  285.  
  286.   return;
  287. }
  288.  
  289. extern void EXFUN (tty_set_next_interrupt_char, (cc_t));
  290.  
  291. #define REQUEST_INTERRUPT_IF_ENABLED(mask) do                \
  292. {                                    \
  293.   if (keyboard_interrupt_enables & (mask))                \
  294.   {                                    \
  295.     tty_set_next_interrupt_char ((cc_t) interrupt_char);        \
  296.     interrupt_p = 1;                            \
  297.   }                                    \
  298.   else                                    \
  299.     interrupt_p = 0;                            \
  300. } while (0)
  301.  
  302. int
  303. DEFUN (signal_keyboard_character_interrupt, (c), int c)
  304. {
  305.   if (c == -1)
  306.   {
  307.     if (keyboard_interrupt_enables & TERMINATE_INTERRUPT_ENABLE)
  308.       goto interactive_interrupt;
  309.     else
  310.       return (0);
  311.   }
  312.   if (c == -2)
  313.   {
  314.     /* Special kludge for hard attn. */
  315.     if (keyboard_interrupt_enables & TERMINATE_INTERRUPT_ENABLE)
  316.     {
  317.       hard_attn_counter += 1;
  318.       if (hard_attn_counter >= hard_attn_limit)
  319.       {
  320.     console_write_string ("\nTerminating scheme!");
  321.     termination_normal (0);
  322.       }
  323.       tty_set_next_interrupt_char (CONTROL_G_INTERRUPT_CHAR);
  324.     }
  325.     return (0);
  326.   }
  327.  
  328.   else if ((c >= 0) && (c < KB_INT_TABLE_SIZE))
  329.   {
  330.     int interrupt_p, interrupt_char;
  331.  
  332.     interrupt_char = keyboard_interrupt_table[c];
  333.  
  334.     switch (interrupt_char)
  335.     {
  336.       case CONTROL_B_INTERRUPT_CHAR:
  337.     REQUEST_INTERRUPT_IF_ENABLED (CONTROL_B_ENABLE);
  338.     break;
  339.  
  340.       case CONTROL_G_INTERRUPT_CHAR:
  341.     REQUEST_INTERRUPT_IF_ENABLED (CONTROL_G_ENABLE);
  342.     break;
  343.  
  344.       case CONTROL_U_INTERRUPT_CHAR:
  345.     REQUEST_INTERRUPT_IF_ENABLED (CONTROL_U_ENABLE);
  346.     break;
  347.  
  348.       case CONTROL_X_INTERRUPT_CHAR:
  349.     REQUEST_INTERRUPT_IF_ENABLED (CONTROL_X_ENABLE);
  350.     break;
  351.  
  352.       case INTERACTIVE_INTERRUPT_CHAR:
  353.     if (! (keyboard_interrupt_enables & INTERACTIVE_INTERRUPT_ENABLE))
  354.     {
  355.       interrupt_p = 0;
  356.       break;
  357.     }
  358. interactive_interrupt:
  359.     print_interrupt_help ();
  360.     interrupt_p = 1;
  361.     break;
  362.  
  363.       default:
  364.     interrupt_p = 0;
  365.     }
  366.     return (interrupt_p);
  367.   }
  368.   return (0);
  369. }
  370.  
  371. void
  372. DEFUN_VOID (OS_restartable_exit)
  373. {
  374.   return;
  375. }
  376.  
  377. /* System-level timer interrupt */
  378.  
  379. /* INT_Global_GC: High-priority Windows polling interrupt.
  380.    INT_Global_1:  Windows polling interrupt.
  381.  */
  382.  
  383. #define CATATONIA_PERIOD       120000    /* msec */
  384. #define ASYNC_TIMER_PERIOD    50    /* msec */
  385.  
  386. static void * timer_state = ((void *) NULL);
  387. extern unsigned long * win32_catatonia_block;
  388.  
  389. static char *
  390. DEFUN_VOID (install_timer)
  391. {
  392.   /* This presumes that the catatonia block is allocated near
  393.      the register block and locked in physical memory with it.
  394.    */
  395.  
  396.   long catatonia_offset
  397.     = (((SCHEME_OBJECT *) &win32_catatonia_block[0]) - (&Registers[0]));
  398.  
  399.   win32_catatonia_block[CATATONIA_BLOCK_COUNTER] = 0;
  400.   win32_catatonia_block[CATATONIA_BLOCK_LIMIT]
  401.     = (CATATONIA_PERIOD / ASYNC_TIMER_PERIOD);
  402.   win32_catatonia_block[CATATONIA_BLOCK_FLAG] = 0;
  403.   switch (win32_system_utilities.install_async_timer
  404.       (&timer_state,
  405.        &Registers[0],
  406.        REGBLOCK_MEMTOP,
  407.        REGBLOCK_INT_CODE,
  408.        REGBLOCK_INT_MASK,
  409.        (INT_Global_GC | INT_Global_1),
  410.        catatonia_offset,
  411.        WM_CATATONIC,
  412.        WM_SCHEME_INTERRUPT,
  413.        master_tty_window,
  414.        OS_grab_interrupt_registers,
  415.        OS_release_interrupt_registers))
  416.   {
  417.     case WIN32_ASYNC_TIMER_OK:
  418.       return (NULL);
  419.  
  420.     case WIN32_ASYNC_TIMER_NONE:
  421.       return ("No asynchronous timer facilities available");
  422.  
  423.     case WIN32_ASYNC_TIMER_EXHAUSTED:
  424.       return ("No asynchronous timers available");
  425.  
  426.     case WIN32_ASYNC_TIMER_RESOLUTION:
  427.       return ("Wrong asynchronous timer resolution");
  428.  
  429.     case WIN32_ASYNC_TIMER_NOLOCK:
  430.       return ("Unable to lock the system timer interrupt handler");
  431.  
  432.     case WIN32_ASYNC_TIMER_NOMEM:
  433.       return ("Not enough memory to install the timer interrupt handler");
  434.  
  435.     case WIN32_ASYNC_TIMER_NOLDT:
  436.       return ("Not enough selectors to fix the timer interrupt handler");
  437.  
  438.     default:
  439.       return ("Unknown asynchronous timer return code");
  440.   }
  441. }
  442.  
  443. static void
  444. DEFUN_VOID (flush_timer)
  445. {
  446.   win32_system_utilities.flush_async_timer (timer_state);
  447.   return;
  448. }
  449.  
  450. /* This sets up the interrupt handlers for both DOS and NT,
  451.    so that bands can be shared.
  452.  */
  453.  
  454. void
  455. DEFUN (NT_initialize_fov, (fov), SCHEME_OBJECT fov)
  456. {
  457.   int ctr, in;
  458.   SCHEME_OBJECT iv, imv, prim;
  459.   extern SCHEME_OBJECT EXFUN (make_primitive, (char *, int));
  460.   static int interrupt_numbers[2] =
  461.   {
  462.     Global_GC_Level,
  463.     Global_1_Level,
  464.   };
  465.   static long interrupt_masks[2] =
  466.   {
  467.     0,                /* No interrupts allowed */
  468.     (INT_Stack_Overflow | INT_Global_GC | INT_GC),
  469.   };
  470.  
  471.   iv = (FAST_VECTOR_REF (fov, System_Interrupt_Vector));
  472.   imv = (FAST_VECTOR_REF (fov, FIXOBJ_INTERRUPT_MASK_VECTOR));
  473.   prim = (make_primitive ("MICROCODE-POLL-INTERRUPT-HANDLER", 2));
  474.  
  475.   for (ctr = 0; ctr < ((sizeof (interrupt_numbers)) / (sizeof (int))); ctr++)
  476.   {
  477.     in = interrupt_numbers[ctr];
  478.     VECTOR_SET (iv, in, prim);
  479.     VECTOR_SET (imv, in, (long_to_integer (interrupt_masks[ctr])));
  480.   }
  481.   return;
  482. }
  483.  
  484. void
  485. DEFUN_VOID (NT_initialize_signals)
  486. {
  487.   char * timer_error;
  488.  
  489.   initialize_keyboard_interrupt_table ();
  490.   timer_error = (install_timer ());
  491.   if (timer_error)
  492.   {
  493.     outf_fatal ("install_timer:  %s", timer_error);
  494.     outf_flush_fatal ();
  495.     abort ();
  496.   }    
  497.   return;
  498. }
  499.  
  500. extern void EXFUN (NT_restore_signals, (void));
  501.  
  502. void
  503. DEFUN_VOID (NT_restore_signals)
  504. {
  505.   flush_timer ();
  506.   return;
  507. }
  508.