home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_06 / 2n06023a < prev    next >
Text File  |  1991-04-30  |  9KB  |  272 lines

  1. /* ----------------------------------------------------------
  2.  *  Turbo C++
  3.  *
  4.  *  Source code Copyright (c) 1991 T.W. Nelson. May be used
  5.  *  only for non-commercial purposes with appropriate
  6.  *  acknowledgement of copyright.
  7.  * ------------------------------------------------------- */
  8.  
  9. #define NO_EXT_MALLOC
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <conio.h>
  14. #include <bios.h>
  15. #include <stdarg.h>
  16. #include "snooper.h"
  17.  
  18. struct device_table {
  19.     char   *d_name;             /* device name */
  20.     FILE   *d_ptr;              /* stream pointer */
  21.     void   (*d_setup)(void);    /* setup debugger */
  22.     void   (*d_exec)(void);     /* execute debugger */
  23.     };
  24.  
  25. /* scan codes ...... */
  26. enum keys { ESC = 1, Y_KEY = 21,
  27.             F1 = 59, F2 = 60, F3 = 61,
  28.             F4 = 62, F5 = 63, F6 = 64,
  29.             F7 = 65, F8 = 66, F9 = 67, F10 = 68 };
  30.  
  31. void set_scrn(void);
  32. void exec_scrn(void);
  33. void open_file(void);
  34. void no_op(void);
  35.  
  36. static struct device_table Dtab[] = {
  37. /*  name        stream  setup         execute
  38. ------------------------------------------------- */
  39. "",             stderr, set_scrn,     exec_scrn,   /* SCRN */
  40. "con",          NULL,   open_file,    no_op,       /* CON  */
  41. "debug.000",    NULL,   open_file,    no_op,       /* FIL0 */
  42. "debug.001",    NULL,   open_file,    no_op,       /* FIL1 */
  43. "debug.002",    NULL,   open_file,    no_op,       /* FIL2 */
  44. "debug.003",    NULL,   open_file,    no_op,       /* FIL3 */
  45. "lpt1",         NULL,   open_file,    no_op,       /* LPT1 */
  46. "lpt2",         NULL,   open_file,    no_op,       /* LPT2 */
  47. "lpt3",         NULL,   open_file,    no_op,       /* LPT3 */
  48. "com1",         NULL,   open_file,    no_op,       /* COM1 */
  49. "com2",         NULL,   open_file,    no_op,       /* COM2 */
  50. 0,              0,      0,            0,
  51. };
  52.  
  53. static int Dnum = __SCRN__;    /* current Dtab[] index */
  54.  
  55. /* data for __SCRN__ device .... */
  56. static void *SaveBuf;           /* video save buffer */
  57. static void *SwapBuf;           /* video swap buffer */
  58. static FILE *pEfile = 0;        /* -> echo stream file */
  59. static char Efile[] = "__SCRN__.CAP";   /* echo file */
  60. static struct text_info Ti;     /* video state info */
  61. static char Menu[] = "<Esc>-Continue <F1>-Exit <F2>-Swap"
  62.             " <F3>-Echo (%s) <F4>-DOS Shell <F5>-Command";
  63.  
  64. /* Breakpoint locus indicators  .... */
  65. static const char *Filename;    /* -> __FILE__ */
  66. static int Line;                /* __LINE__ */
  67.  
  68. #define getxy(x,y)    x = wherex();   \
  69.                       y = wherey();
  70. #define getscan()     (bioskey(0) >> 8)
  71. #define getkey()        bioskey(0)
  72.  
  73. static void no_op(void) { }
  74.  
  75. static void open_file(void)
  76. {
  77.    /* Open a file/device for writing debug data */
  78.     FILE *fp;
  79.  
  80.     if( Dtab[Dnum].d_ptr == NULL )   {
  81.             fp = fopen(Dtab[Dnum].d_name, "wt");
  82.             __WATCH(fp == NULL,__SCRN__,
  83.                  cprintf("Can't open snooper device %s\n",
  84.                              Dtab[Dnum].d_name ));
  85.             Dtab[Dnum].d_ptr = fp;
  86.             setbuf( fp, NULL );     /* set unbuffered */
  87.     }
  88. }
  89.  
  90. static void print_menu(void)
  91. {
  92.         int x, y;
  93.         getxy(x,y);
  94.         gotoxy(1,Ti.screenheight);
  95.         cprintf(Menu,pEfile ? "ON" : "OFF" );
  96.         gotoxy(x,y);
  97. }
  98.  
  99. static void set_scrn(void)
  100. {
  101.    /* Save the current application video state and popup
  102.     * the debugger screen. If a screen save buffer can't
  103.     * be allocated, application's screen will be trashed
  104.     * on break to __SCRN__ device.
  105.     */
  106.  
  107.     static char malloced = 0;     /* mem alloc flag */
  108.     size_t bsize;     /* monitor buffer size, bytes */
  109.  
  110.     gettextinfo( &Ti );
  111.  
  112.     if( !malloced )    {
  113.             malloced = 1;
  114.             bsize = Ti.screenheight * Ti.screenwidth * 2;
  115.  
  116.             if( !(SaveBuf = malloc( bsize )) )
  117.                     return ;
  118.  
  119.             SwapBuf = malloc( bsize );
  120.     }
  121.  
  122.     gettext(1,1,Ti.screenwidth,Ti.screenheight,SaveBuf);
  123.     window( 1,1, Ti.screenwidth,Ti.screenheight );
  124.     clrscr();
  125.     d_printf("\n**** Breakpoint in \"%s\", line %d:\n",
  126.                                         Filename, Line);
  127.     print_menu();
  128. }
  129.  
  130. static void user_input(void)
  131. {
  132.     int x, y, depart = 0;
  133.     char cmd[150];
  134.  
  135.     getxy(x,y);
  136.  
  137.     while( !depart )    {
  138.         switch( getscan() )   {
  139.         case ESC:   ++depart;   /* continue */
  140.                     break;
  141.         case F1:    cprintf("\r\nPress 'Y' to confirm: ");
  142.                     if( getscan() != Y_KEY )
  143.                             goto restore_screen;
  144.                     clrscr();   /* abort */
  145.                     exit(1);
  146.                     break;
  147.         case F2:    if( !SaveBuf )     /* swap screens */
  148.                             break;
  149.                     puttext(1,1,Ti.screenwidth,
  150.                                   Ti.screenheight,SaveBuf);
  151.                     getkey();
  152.                     goto restore_screen;
  153.         case F3:    d_echo( pEfile ? 0 : 1 );
  154.                     print_menu();  /* toggle echo */
  155.                     break;
  156.         case F4:    cmd[0] = '\0';   /* Shell escape */
  157.                     goto do_shell;
  158.         case F5:    cprintf( "\r\nCMD>" );
  159.                     gets(cmd);
  160.         do_shell:   clrscr();
  161.                     system(cmd);
  162.         restore_screen:
  163.                     if( SwapBuf )
  164.                         puttext(1,1,Ti.screenwidth,
  165.                                 Ti.screenheight,SwapBuf);
  166.                     gotoxy(x,y);
  167.                     break;
  168.         default:    printf("\a");   break;
  169.         }
  170.     }
  171. }
  172.  
  173. static void exec_scrn(void)
  174. {
  175.        /* Save initial debugger screen .... */
  176.         if( SwapBuf )
  177.                gettext(1,1,Ti.screenwidth,
  178.                            Ti.screenheight,SwapBuf);
  179.         user_input();
  180.  
  181.        /* Restore application video state */
  182.         if( !SaveBuf )
  183.                 return;         /* screen was trashed */
  184.  
  185.         window( Ti.winleft, Ti.wintop,
  186.                             Ti.winright,Ti.winbottom );
  187.         puttext(1,1,Ti.screenwidth,Ti.screenheight,SaveBuf);
  188.         gotoxy( Ti.curx, Ti.cury );
  189. }
  190.  
  191. void d_break(int dh, const char *file, int linenum)
  192. {
  193.    /* Initialize application break to debugger using the
  194.     * specified device handle.
  195.     */
  196.  
  197.     if( dh > MAX_DEVICES-1 )    {
  198.         __BREAK(__SCRN__,
  199.             cprintf("Invalid debugger handle %d\n", dh));
  200.         exit(1);
  201.     }
  202.  
  203.     Dnum = dh;       /* remember current device */
  204.     Filename = file;    /* save breakpoint locus */
  205.     Line = linenum;
  206.     (*Dtab[dh].d_setup)();
  207. }
  208.  
  209. void d_exec(void)
  210. {
  211.        /* Called after debugger has been setup and the user-
  212.         * supplied function has been executed.
  213.         */
  214.         (*Dtab[Dnum].d_exec)();
  215.         Dnum = __SCRN__;    /* reset to default */
  216. }
  217.  
  218. void d_printf( const char *format, ... )
  219. {
  220.    /* Debugger version of fprintf(). Allows writing of
  221.     * formatted data to pre-opened stream file associated
  222.     * with last call to d_break().  If echo mode is set,
  223.     * all data written to __SCRN__ device is also sent to
  224.     * disk file. Uses SwapBuf[] as a temporary work buffer.
  225.     */
  226.  
  227.     va_list argptr;
  228.  
  229.     va_start(argptr, format);
  230.  
  231.     if( Dnum == __SCRN__ && pEfile && SwapBuf )  {
  232.             vsprintf( SwapBuf, format, argptr );
  233.             fprintf( stderr, SwapBuf );     /* to SCRN */
  234.             fprintf( pEfile, SwapBuf );     /* echo it */
  235.     }
  236.     else
  237.             vfprintf( Dtab[Dnum].d_ptr, format, argptr );
  238.  
  239.     va_end(argptr);
  240. }
  241.  
  242. int d_putc( int ch )
  243. {
  244.    /* Debugger version of fputc().  Allows writing of <ch>
  245.     * to pre-opened stream file associated with last call
  246.     * to d_break().
  247.     */
  248.  
  249.     return fputc( ch, Dtab[Dnum].d_ptr );
  250. }
  251.  
  252. void d_echo(int mode)
  253. {
  254.    /* Set the debugger screen-echo mode. If <mode> is
  255.     * non-zero, all debug data written to __SCRN__ device
  256.     * will be sent also to echo file <Efile>, but only if
  257.     * d_printf() is used in the __BREAK() statement.
  258.     */
  259.  
  260.     if( mode && pEfile == NULL )   {
  261.             pEfile = fopen( Efile, "wt" );
  262.             __WATCH(pEfile == NULL, __SCRN__,
  263.                 cprintf("Unable to open SCRN echo file" ));
  264.     }
  265.     else if( mode == 0 && pEfile )  {
  266.             fclose(pEfile);
  267.             pEfile = NULL;
  268.     }
  269. }
  270.  
  271. /* -------------------------------------------------------- */
  272.