home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 2.ddi / TOOLS.2 / EXAMPLES / ISCLOCK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-31  |  7.6 KB  |  303 lines

  1. /*
  2. *    ISCLOCK.C    Display a constantly updated digital clock on
  3. *            the screen.
  4. *
  5. *  This program displays a clock in the upper-right corner of the
  6. *  screen.  All of the interrupt support for running the clock is
  7. *  provided by Turbo C TOOLS interrupt support (IS) routines.
  8. *
  9. *  ISCLOCK is set up to receive control every clock tick, but only
  10. *  to do any work on every tenth clock tick.  (a little less than
  11. *  once every half second).
  12. *
  13. *  ISCLOCK retrieves the time-of-day (in clock ticks) from the BIOS.
  14. *
  15. *  The command line format is as follows:
  16. *
  17. *    isclock [-r]
  18. *
  19. *  ISCLOCK is a self-removing interrupt service routine.  If ISCLOCK
  20. *  is invoked with no arguments, it installs itself (if not already
  21. *  installed); if it is invoked with the "-r" argument, it
  22. *  removes a running copy of ISCLOCK (if present).
  23. *
  24. *  The purpose of ISCLOCK is to exhibit the interrupt service
  25. *  capabilities of Turbo C TOOLS, and to provide a working example
  26. *  of the proper method of construction and use of interrupt service
  27. *  code.
  28. *
  29. *  Version    6.00 (C)Copyright Blaise Computing, Inc. 1987, 1989
  30. *
  31. */
  32.  
  33.  
  34. #include <dos.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37.  
  38. #include <bintrupt.h>
  39. #include <bscreens.h>
  40. #include <bvideo.h>
  41.  
  42.         /* The function which will be called every timer    */
  43.         /* tick.                        */
  44. void intime (ALLREG *,ISRCTRL *,ISRMSG *);
  45.  
  46. #if  (IS_NUM_FLOAT_VECS > 0)
  47.         /* Storage for floating point vectors.            */
  48. static void far *float_vec [IS_NUM_FLOAT_VECS];
  49. #endif
  50.  
  51. #define STKSIZE   2000
  52.  
  53.         /* Exit values.                     */
  54. #define FALL_OUT  101
  55. #define OK      0
  56.  
  57. #define NOT_FOUND      1
  58. #define ERROR_REMOVING      3
  59. #define ALREADY_INSTALLED 4
  60.  
  61. #define TIMER_VEC 0x08
  62.  
  63.         /* Definitive signature for this version of ISCLOCK.*/
  64. char *isclock_ident = "ISCLOK 03/31/89";
  65.  
  66.         /* Allocation of stack space for the intervention   */
  67.         /* scheduler and user function.             */
  68. char  isstack [STKSIZE];
  69.  
  70.         /* Control block for ISR dispatcher.            */
  71. ISRCTRL isrctrl;
  72.  
  73.         /* Internal functions -- install & remove ISR.        */
  74. int install_is (void);
  75. int remove_is  (void);
  76.  
  77. void main(int, char **);
  78.  
  79.  
  80. void main (argc, argv)
  81. int   argc;
  82. char *argv [];
  83. {
  84.     if (argc == 1)
  85.     exit (install_is ());
  86.  
  87.     if ((argc == 2)                       &&
  88.     (((argv [1][0] == '-') || (argv [1][0] == '/')) &&
  89.      ((argv [1][1] == 'r') || (argv [1][1] == 'R'))))
  90.     exit (remove_is ());
  91.  
  92.     printf ("usage: isclock [-r]\n");
  93.     exit (0);
  94. }
  95.  
  96.  
  97.  
  98. /**
  99. *
  100. * Name        INSTALL_IS -- Install interrupt vectors for ISCLOCK and
  101. *                  go TSR.
  102. *
  103. * Synopsis    ret = install_is ();
  104. *
  105. *        int ret     Return code from ISINSTAL if there was
  106. *                a problem with installation of the
  107. *                interrupt service routine.
  108. *
  109. * Description    This function installs ISCLOCK if another copy of
  110. *        ISCLOCK is not already installed.
  111. *
  112. * Returns    ret
  113. *
  114. **/
  115.  
  116. int install_is ()
  117. {
  118.     int       i, ret;
  119.     void far *timer_vec = isgetvec (TIMER_VEC);
  120.  
  121.     if (issense (timer_vec, isclock_ident) != FARNIL)
  122.     {
  123.     puts ("ISCLOCK already installed");
  124.     return (ALREADY_INSTALLED);
  125.     }
  126.  
  127. #if  (IS_NUM_FLOAT_VECS > 0)
  128.         /* Save floating point vectors.             */
  129.     for (i = 0;  i < IS_NUM_FLOAT_VECS;  i++)
  130.     float_vec[i] = isgetvec (IS_1ST_FLOAT_VEC + i);
  131. #endif
  132.  
  133.         /* Install the interrupt service routine.        */
  134.     if ((ret = isinstal (TIMER_VEC, intime, isclock_ident,
  135.              &isrctrl, isstack, STKSIZE, 1)) != 0)
  136.     {        /* Error!                        */
  137.     printf ("ISINSTAL error %d.\n", ret);
  138.     return (ret);
  139.     }
  140.  
  141.         /* Terminate and stay resident.             */
  142.     isresext (OK);
  143.  
  144.         /* Should never get here.                */
  145.     return (FALL_OUT);
  146. }
  147.  
  148.  
  149.  
  150. /**
  151. *
  152. * Name        REMOVE_IS -- Remove a previously-installed copy of ISCLOCK.
  153. *
  154. * Synopsis    ret = remove_is ();
  155. *
  156. *        int ret     Return code.
  157. *                  NO_ERROR  (0)-
  158. *                      No error encountered.
  159. *                  NOT_FOUND (1)-
  160. *                      ISCLOCK not found.
  161. *                  ERROR_REMOVING (3)--
  162. *                      ISCLOCK could not be removed
  163. *                      (most likely overwritten MALLOC
  164. *                      pointers).
  165. *
  166. * Description    This function removes a currently-active copy of ISCLOCK
  167. *        from memory, cleaning up interrupt vectors and freeing
  168. *        memory in the process.
  169. *
  170. * Returns    ret (nonzero if error--see above).
  171. *
  172. **/
  173.  
  174. int remove_is ()
  175. {
  176.     ISRCTRL far *pisrctrl;
  177.     void far *timer_vec = isgetvec (TIMER_VEC);
  178.  
  179.         /* Check to see if ISCLOCK installed.            */
  180.     if ((pisrctrl = issense (timer_vec, isclock_ident)) == FARNIL)
  181.     {
  182.     puts ("ISCLOCK not found.");
  183.     return (NOT_FOUND);
  184.     }
  185.  
  186.         /* Restore the old interrupt vector.            */
  187.     isputvec (TIMER_VEC, pisrctrl->prev_vec);
  188.  
  189.     if (isremove (pisrctrl->isrpsp))
  190.     {
  191.     puts ("Error removing ISCLOCK.");
  192.     return (ERROR_REMOVING);
  193.     }
  194.  
  195.     return (0);
  196. }
  197.  
  198.  
  199.  
  200. /**
  201. *
  202. * Name        INTIME -- Display a digital clock with the current
  203. *              time on the screen.
  204. *
  205. * Synopsis    (To be called only by interrupt service dispatcher)
  206. *
  207. *        intime (pallreg, pisrctrl, pisrmsg);
  208. *
  209. *        ALLREG    *pallreg    Pointer to a structure which
  210. *                    contains the contents of all
  211. *                    CPU registers.
  212. *        ISRCTRL *pisrctrl    Pointer to information used by
  213. *                    ISR dispatcher.  This is where
  214. *                    information on nested-ness is
  215. *                    kept.
  216. *        ISRMSG    *pisrmsg    Not used.
  217. *
  218. * Description    This function accepts control from the dispatcher
  219. *        approximately 18.2 times per second, displays a
  220. *        digital clock with the current time (every 18th
  221. *        invocation), and exits.
  222. *
  223. * Returns    None.
  224. *
  225. **/
  226.  
  227. void intime (pallreg, pisrctrl, pisrmsg)
  228. ALLREG    *pallreg;
  229. ISRCTRL *pisrctrl;
  230. ISRMSG    *pisrmsg;
  231. {
  232.     static int      ticks = 0;
  233.     long      elpsec, time;
  234.     int       mode, act_page, columns;
  235.     int       hours, mins, secs;
  236.     char      time_str[10];
  237. #if  (IS_NUM_FLOAT_VECS > 0)
  238.     void far     *save_float [IS_NUM_FLOAT_VECS];
  239. #endif
  240.  
  241.         /* Get rid of compiler warning message.         */
  242.     hours = *((int *) pisrmsg);
  243.  
  244.  
  245.         /* Call previous owner of the timer vector first.   */
  246.     iscall (pisrctrl->prev_vec, pallreg);
  247.  
  248.         /* If we have enough ticks, get time from BIOS tick */
  249.         /* counter (via UTGETCLK), and display it.        */
  250.     if (++ticks >= 18)
  251.     {
  252.     ticks = 0;
  253.  
  254. #if  (IS_NUM_FLOAT_VECS > 0)
  255.         /* Save current floating point vectors.         */
  256.     utintflg (UT_INTOFF);
  257.     utpeekn (uttofar (0, 4*IS_1ST_FLOAT_VEC, char), save_float,
  258.          sizeof (save_float));
  259.  
  260.         /* Reinstall our own floating point vectors.  */
  261.     utpoken (float_vec, uttofar (0, 4*IS_1ST_FLOAT_VEC, char),
  262.          sizeof (float_vec));
  263.     utintflg (UT_INTON);
  264. #endif
  265.         /* Get the current mode and active display page     */
  266.         /* from BIOS.                        */
  267.     scmode (&mode, &columns, &act_page);
  268.  
  269.         /* Direct our display output to the current display */
  270.         /* page.                        */
  271.     scpage (act_page);
  272.  
  273.         /* Get current time of day from BIOS.            */
  274.  
  275.         /* Figure out number of seconds past midnight from  */
  276.         /* (given) number of timer ticks since midnight.    */
  277.     utgetclk (&time);
  278.  
  279.         /* Figure out number of seconds past midnight from  */
  280.         /* (given) number of timer ticks since midnight.    */
  281.     elpsec = (long) (0.0549254 * (double) time);
  282.  
  283.         /* Figure out hours, minutes, seconds from seconds  */
  284.         /* past midnight.                    */
  285.     hours = (int)  (elpsec / 3600L);
  286.     mins  = (int) ((elpsec / 60L) % 60L);
  287.     secs  = (int)  (elpsec % 60L);
  288.  
  289.         /* Display the time.                    */
  290.     sprintf (time_str, "%02d:%02d:%02d", hours, mins, secs);
  291.     vidspmsg (0, columns - strlen (time_str),
  292.           NORMAL | INTENSITY, SC_BLACK, time_str);
  293.  
  294. #if  (IS_NUM_FLOAT_VECS > 0)
  295.         /* Restore floating point vectors.            */
  296.     utintflg (UT_INTOFF);
  297.     utpoken (save_float, uttofar (0, 4*IS_1ST_FLOAT_VEC, char),
  298.          sizeof (save_float));
  299.     utintflg (UT_INTON);
  300. #endif
  301.     }
  302. }
  303.