home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / turbo_c / tbug.arc / TBUG.C < prev    next >
Text File  |  1987-09-15  |  21KB  |  861 lines

  1. /**************************************************
  2. *
  3. *   SOURCE LEVEL DEBUG MODULE FOR TURBO C
  4. *   by: Gary L. Mellor          Sept 1987
  5. *
  6. **************************************************/
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11. #include <alloc.h>
  12. #include <dos.h>
  13.  
  14. /*     IDENTIFIER ATTRIBUTE CODES */
  15.  
  16. #define  INT        1
  17. #define  CHAR       2
  18. #define  FLOAT      3
  19. #define  DOUBLE     4
  20. #define  POINTER    0x1000
  21. #define  ADDRESS    0x2000
  22.  
  23. /*     COMMAND CODES    */
  24.  
  25. #define  HELP        1
  26. #define  MAP         2
  27. #define  SYMS        3
  28. #define  LIST        4
  29. #define  PRINT       5
  30. #define  BREAK       6
  31. #define  NOBREAK     7
  32. #define  STEP        8
  33. #define  CONTINUE    9
  34. #define  TRACE       10
  35. #define  REGISTERS   11
  36. #define  QUIT        12
  37.  
  38.  
  39. typedef struct          /* INTERRUPT REGISTERS */
  40. {
  41.   unsigned int bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags;
  42. }INTREGS;
  43.  
  44.  
  45. typedef struct         /* LINE NUMBER TABLE ENTRY */
  46. {
  47.   int line_number;
  48.   int address;
  49.   unsigned char flag;
  50.   unsigned char opcode;
  51.   void far *link;
  52. }LINE;
  53.  
  54.  
  55. typedef struct         /* SYMBOL TABLE ENTRY */
  56. {
  57.   char name[32];
  58.   int  offset;
  59.   void far *link;
  60. }SYMBOL;
  61.  
  62. typedef struct        /* DECODE LIST ENTRY */
  63. {
  64.   int key;
  65.   char *string;
  66. }DECODELIST;
  67.  
  68. /* COMMAND DECODE LIST IS ALSO USED TO DISPLAY HELP  */
  69.  
  70. DECODELIST cmdlist[]=
  71. {
  72.   HELP,     "HELP\n\nCOMMAND PARAM(s) <>=optional     FUNCTION\n",
  73.   MAP,      "MAP                         lists the line numbers",
  74.   SYMS,     "SYMS                        lists the public symbols",
  75.   LIST,     "LIST    <line_number>       lists the source file",
  76.   PRINT,    "PRINT   <type> identifier   prints the value",
  77.   BREAK,    "BREAK   <line_number>       sets/lists the breakpoint(s)",
  78.   NOBREAK,  "NOBREAK line_number         removes a breakpoint",
  79.   STEP,     "STEP                        steps to the next source line",
  80.   CONTINUE, "CONTINUE                    executes to next breakpoint",
  81.   REGISTERS,"REGISTERS                   displays the cpu registers",
  82.   QUIT,     "QUIT                        terminates the program",
  83.   0,0
  84. };
  85.  
  86. /* IDENTIFIER ATTRIBUTE DECODE LIST FOR PRINT COMMAND */
  87. DECODELIST keylist[]=
  88. {
  89.   INT,"INT",
  90.   CHAR,"CHAR",
  91.   FLOAT,"FLOAT",
  92.   DOUBLE,"DOUBLE",
  93.   0,0
  94. };
  95.  
  96. LINE far *linetable;
  97. SYMBOL far *symtable;
  98. void interrupt (*vect1)();
  99. void interrupt (*vect3)();
  100.  
  101. /*******************************
  102. *  DEBUG INITIALIZATION
  103. *******************************/
  104. int debug_init(name)
  105. char *name;
  106. {
  107.   void interrupt brk_handler();
  108.   void interrupt trace_handler();
  109.   void debug_exit();
  110.  
  111.   FILE *mapfile;
  112.   char mapname[40];
  113.   char sname[40];
  114.   char buffer[80];
  115.   char *ptr;
  116.   int i;
  117.  
  118.   i = 0;
  119.   while (*name && (*name != '.'))
  120.     mapname[i++] = *name++;
  121.   mapname[i] = 0;
  122.   strcat(mapname,".MAP");
  123.   mapfile = fopen(mapname,"r");
  124.   if (mapfile == 0)
  125.   {
  126.     printf("MAPFILE NOT FOUND: %s\n",mapname);
  127.     return(-1);
  128.   }
  129.   while(fgets(buffer,80,mapfile))
  130.   {
  131.                                   /* locate public symbols */
  132.     if (strstr(buffer,"Publics by Val"))
  133.     {
  134.                                   /* allocate root entry */
  135.       symtable = farmalloc(sizeof(SYMBOL));
  136.       symtable->link = 0;
  137.       fgets(buffer,80,mapfile);   /* dump blank line */
  138.       do                          /* build symbol table */
  139.       {
  140.         fgets(buffer,80,mapfile);
  141.         i = addsym(symtable,buffer);
  142.         if (i < 0)
  143.           break;
  144.       }
  145.       while(buffer[0] == ' ');
  146.       break;
  147.     }
  148.   }
  149.   while(fgets(buffer,80,mapfile))
  150.   {
  151.                                   /* locate the line numbers */
  152.     if (buffer[0] == 'L')
  153.     {
  154.                                   /* allocate root entry */
  155.       linetable =  farmalloc(sizeof(LINE));
  156.       linetable->link = 0;
  157.                                   /* extract source file name */
  158.       ptr = strchr(buffer,'(');
  159.       ptr++;
  160.       i = 0;
  161.       while (*ptr != ')')
  162.         sname[i++] = *ptr++;
  163.       sname[i] = 0;
  164.       fgets(buffer,80,mapfile);   /* dump blank line */
  165.       do                          /* build the line number table */
  166.  
  167.       {
  168.         fgets(buffer,80,mapfile);
  169.         i = addlines(linetable,buffer);
  170.       }while(i > 0);
  171.       if (i < 0)
  172.       {
  173.         puts("NOT ENOUGH MEMORY FOR DEBUGGER");
  174.         return(-1);
  175.       }
  176.       break;
  177.     }
  178.   }
  179.   fclose(mapfile);
  180.   vect1 = getvect(1);            /* save old vectors */
  181.   vect3 = getvect(3);
  182.   if (cmdline(0,sname) != 0)     /* bkpts have been set */
  183.   {
  184.     setvect(1,&trace_handler);   /* so init our vectors */
  185.     setvect(3,&brk_handler);
  186.     atexit(debug_exit);          /* and exit handler */
  187.  
  188.   }
  189.   return(0);
  190. }
  191. /*******************************
  192. *  DEBUG EXIT HANDLER
  193. *******************************/
  194. void debug_exit()
  195. {
  196.   printf("\nPROGRAM TERMINATION\n");
  197.   setvect(1,vect1);
  198.   setvect(3,vect3);
  199.  
  200. }
  201. /*******************************
  202. * COMMAND LINE INPUT HANDLER
  203. ********************************/
  204. /*
  205.    prompts for operator input 
  206.    and handles commands
  207. */
  208. int cmdline(regs,file)
  209. INTREGS *regs;
  210. char *file;
  211. {
  212.   LINE far *findline();
  213.   SYMBOL far *findsym();
  214.   char *fstrg();
  215.   char *next();
  216.  
  217.   char temp[132];
  218.   char *tptr;
  219.   int  brkline;
  220.   int  listline;
  221.   int  address;
  222.   int  index;
  223.   LINE far *line;
  224.   SYMBOL far *symbol;
  225.  
  226.   static int cmd;
  227.   static FILE *fp;
  228.   static char name[15];
  229.   int i;
  230.   int mode;
  231.   int flag;
  232.  
  233.   if (regs == 0)          /* if called from debug_init  */
  234.   {
  235.     fp = fopen(file,"r"); /* open the source file       */
  236.     strcpy(name,file);
  237.   }
  238.   listline = 1;
  239.   for(;;)
  240.   {
  241.     printf("TBUG?? ");    /* prompt for and     */
  242.     gets(temp);           /* input command line */
  243.     tptr = temp;
  244.     while (*tptr == ' ')  /* skip leading spaces */
  245.       tptr++;
  246.     if (*tptr != 0)       /* if more than RETURN then  */
  247.                           /* decode new command  code  */
  248.       cmd = decode(tptr,cmdlist);
  249.     switch(cmd)           /* process command code */
  250.     {
  251.       case HELP:
  252.                 i = 0;
  253.                 while(cmdlist[i].key != 0)
  254.                   puts(cmdlist[i++].string);
  255.                 break;
  256.       case MAP:
  257.               line = linetable;
  258.               i = 0;
  259.               printf("LINE NUMBERS FOR %s\n",name);
  260.               while(line->link != 0)
  261.               {
  262.                 if ((i++ % 4) == 0)
  263.                   putchar('\n');
  264.                  printf("%4d  %04X     ",
  265.                         line->line_number,line->address);
  266.                  line = line->link;
  267.               }
  268.               putchar('\n');
  269.               break;
  270.       case SYMS:
  271.               symbol = symtable;
  272.               while(symbol->link != 0)
  273.               {
  274.                 if ((i++ % 2) == 0)
  275.                   putchar('\n');
  276.                 printf("%32s %04X  ",
  277.                         fstrg(symbol->name),symbol->offset);
  278.                 symbol = symbol->link;
  279.               }
  280.               putchar('\n');
  281.               break;
  282.       case PRINT:
  283.               tptr = next(tptr);
  284.               if (*tptr != 0)
  285.               {
  286.                 mode = 0;
  287.                 do
  288.                 {
  289.                   i = decode(tptr,keylist);
  290.                   if (i != 0)
  291.                     tptr = next(tptr);
  292.                   mode = mode | i;
  293.                 }while (i != 0);
  294.                 i = 0;
  295.                 if (*tptr == '*')
  296.                 {
  297.                   mode = mode | POINTER;
  298.                   tptr++;
  299.                 }
  300.                 while ((*tptr != 0) && (strchr(" +-[",*tptr) == 0))
  301.                   temp[i++] = *tptr++;
  302.                 temp[i] = 0;
  303.                 while(*tptr == ' ')
  304.                   tptr++;
  305.                 switch(*tptr++)
  306.                 {
  307.                   case '+':
  308.                   case '[':
  309.                             while (*tptr == ' ')
  310.                               tptr++;
  311.                             index = getnum(tptr);
  312.                             break;
  313.                   case '-':
  314.                             while (*tptr == ' ')
  315.                               tptr++;
  316.                             index = -(getnum(tptr));
  317.                             break;
  318.                    default:
  319.                             index = 0;
  320.                 }
  321.                 if (isalpha(temp[0]))
  322.                 {
  323.                   symbol = findsym(temp,symtable);
  324.                   if (symbol == 0)
  325.                   {
  326.                     puts("SYMBOL NOT FOUND");
  327.                     break;
  328.                   }
  329.                   address = symbol->offset;
  330.                 }
  331.                 else
  332.                 {
  333.                   if (strcmp(temp,"_BP") == 0)
  334.                   {
  335.                     address = regs->bp + index;
  336.                     index = 0;
  337.                   }
  338.                   else
  339.                     address = getnum(temp);
  340.                 }
  341.                 printloc(mode,address,index);
  342.               }
  343.               else
  344.                 puts("VARIABLE MUST BE SPECIFIED");
  345.               break;
  346.       case LIST:
  347.               if (fp == 0)
  348.                 puts("SOURCE NOT AVAILABLE");
  349.               else
  350.               {
  351.                 tptr = next(tptr);
  352.                 if (*tptr != 0)
  353.                 {
  354.                   rewind(fp);
  355.                   listline = atoi(tptr);
  356.                   i = listline - 1;
  357.                   if ( i < 0)
  358.                     i = 0;
  359.                 }
  360.                 else
  361.                   i = 0;
  362.                 while(i-- > 0)
  363.                   fgets(temp,132,fp);
  364.                 for (i = 0; i < 20; i++)
  365.                 {
  366.                   if (fgets(temp,132,fp))
  367.                     printf ("%03d:  %s",listline++,temp);
  368.                   else
  369.                   {
  370.                     puts("*****END OF FILE*****");
  371.                     break;
  372.                   }
  373.                 }
  374.               }
  375.               break;
  376.       case BREAK:
  377.               tptr = next(tptr);
  378.               if (*tptr != 0)
  379.               {
  380.                 brkline = atoi(tptr);
  381.                 line = findline(brkline,linetable);
  382.                 if (line == 0)
  383.                   puts("LINE NOT FOUND");
  384.                 else
  385.                 {
  386.                   if (line->flag != BREAK)
  387.                   {
  388.                     line->flag = BREAK;
  389.                     pokeb(_CS,line->address,0xCC);
  390.                   }
  391.                   else
  392.                     puts("BREAK ALREADY SET");
  393.                 }
  394.               }
  395.               else
  396.               {
  397.                 for(line = linetable; line->link != 0; line = line->link)
  398.                 {
  399.                   if (line->flag == BREAK)
  400.                   {
  401.                     printf("%d  %04X\n",line->line_number,
  402.                            line->address);
  403.                   }
  404.                 }
  405.               }
  406.               break;
  407.       case NOBREAK:
  408.               tptr = next(tptr);
  409.               brkline = atoi(tptr);
  410.               line = findline(brkline,linetable);
  411.               if (line == 0)
  412.                 puts("LINE NOT FOUND");
  413.               else
  414.               {
  415.                 if (line->flag == BREAK)
  416.                 {
  417.                   line->flag = NOBREAK;
  418.                   pokeb(_CS,line->address,line->opcode);
  419.                 }
  420.                 else
  421.                   puts("BREAK NOT SET");
  422.               }
  423.               break;
  424.       case REGISTERS:
  425.               printf("AX = %04X  BX = %04X  CX = %04X  DX = %04X\n",
  426.                      regs->ax,regs->bx,regs->cx,regs->dx);
  427.               printf("BP = %04X  SI = %04X  DI = %04X  IP = %04X\n",
  428.                      regs->bp,regs->si,regs->di,regs->ip);
  429.               printf("DS = %04X  ES = %04X  CS = %04X  FLAGS  %02X\n",
  430.                      regs->ds,regs->es,regs->cs,regs->flags&0xFF);
  431.               break;
  432.       case CONTINUE:
  433.               line = linetable;
  434.               i = 0;
  435.               flag = 0;
  436.               while(line->link != 0)
  437.               {
  438.                 if (line->flag != BREAK) /* restore proper opcode */
  439.                 {
  440.                   line->flag = NOBREAK;
  441.                   pokeb(_CS,line->address,line->opcode);
  442.                 }
  443.                 else
  444.                   flag = 1;             /* we have at least one bkpt */
  445.                 line = line->link;
  446.               }
  447.               if (flag ==  0)
  448.               {
  449.                 setvect(1,vect1);
  450.                 setvect(3,vect3);
  451.               }
  452.               return(flag);             /* tell caller if have bkpts */
  453.       case STEP:
  454.               line = linetable;
  455.               while(line->link != 0)
  456.               {
  457.                 if (line->flag != BREAK)
  458.                 {
  459.                   line->flag = STEP;
  460.                   pokeb(_CS,line->address,0xCC);
  461.                 }
  462.                 line = line->link;
  463.               }
  464.               return(1);                /* we definately have bkpts */
  465.       case QUIT:
  466.               exit(0);
  467.       case -1:
  468.               puts("COMMAND SPELLING NOT UNIQUE");
  469.               break;
  470.       default:
  471.               puts("INVALID COMMAND");
  472.     }
  473.   }
  474. }
  475. /*******************************
  476. *   STRING HANDELING ROUTINES
  477. *******************************/
  478. /*
  479.     decode compares a command string
  480.     to a command list and returns a
  481.     command key. More than one match
  482.     means enough chars in command spelling
  483.     to decode the command.
  484. */
  485. int decode(s,list)
  486. char s[];
  487. DECODELIST list[];
  488. {
  489.   int i;
  490.   int idx;
  491.  
  492.   i = 0;
  493.   idx = 0;
  494.   while(list[i].key)        /* while not end of list */
  495.   {
  496.      if (match(s,list[i].string))
  497.      {
  498.        if (idx == 0)        /* first match OK */
  499.          idx = list[i].key;
  500.        else                 
  501.          return(-1);        /* multiple match NOT OK */
  502.      }
  503.      i++;
  504.   }
  505.   return(idx);
  506. }
  507. /*
  508.   string comparison is a match
  509.   if all chars of string s1 match s2,
  510.   even if we are not at end of s2
  511. */
  512. int match(s1,s2)
  513. char *s1;
  514. char *s2;
  515. {
  516.   while (*s1 == ' ')    /* skip leading spaces */
  517.     s1++;
  518.   while(*s1 > ' ')      /* while valid char */
  519.   {
  520.     if (toupper(*s1++) != *s2++)
  521.       return(0);        /* we didnt match */
  522.   }
  523.   return(1);
  524. }
  525. /*
  526.   next skips the current token
  527.   and trailing spaces to return
  528.   a pointer to the next token
  529. */
  530. char *next(s)
  531. char *s;
  532. {
  533.   while(*s)        /* skip over current token */
  534.   {
  535.     if (*s <= ' ')
  536.       break;
  537.     else
  538.       s++;
  539.   }
  540.   while (*s)       /* skip over spaces */
  541.   {
  542.     if (*s > ' ')
  543.       break;
  544.     else
  545.       s++;
  546.   }
  547.   return(s);
  548. }
  549. /*
  550.   moves a far string into local data space
  551.   and returns a pointer to it.
  552. */
  553. char *fstrg(fs)
  554. char far *fs;
  555. {
  556.   static char temp[80];
  557.   int i;
  558.  
  559.   i = 0;
  560.  
  561.   while (*fs != 0)
  562.     temp[i++] = *fs++;
  563.   temp[i] = 0;
  564.   return(&temp[0]);
  565. }
  566. /*******************************
  567. * LINE NUMBER TABLE ROUTINES
  568. *******************************/
  569. /*
  570.     adds line numbers/offsets to table
  571. */
  572. int addlines(table,buf)
  573. LINE far *table;
  574. char *buf;
  575. {
  576.   int count;
  577.  
  578.   while(table->link != 0)
  579.     table  = table->link;
  580.   count = 0;
  581.   while (*buf != 0)
  582.   {
  583.     if (isdigit(*buf))
  584.     {
  585.       table->line_number = atoi(buf);
  586.       while(*buf++ != ':');
  587.       table->address = xatoi(buf);
  588.       table->flag = 0;
  589.       table->opcode = peekb(_CS,table->address);
  590.       while(isxdigit(*buf++));
  591.       table->link = farmalloc(sizeof(LINE));
  592.       table = table->link;
  593.       table->link = 0;
  594.       if (table == 0)
  595.         return(-1);
  596.       count++;
  597.     }
  598.     else
  599.       buf++;
  600.   }
  601.   return(count);
  602. }
  603. /*
  604.   finds a line number in the table
  605. */
  606. LINE far *findline(lnum,table)
  607. int lnum;
  608. LINE far *table;
  609. {
  610.   int i;
  611.  
  612.   while(table->link != 0)
  613.   {
  614.     if (table->line_number == lnum)
  615.       return(table);
  616.     table = table->link;
  617.    }
  618.    return(0);
  619. }
  620. /*
  621.   finds an address in the table
  622. */
  623. LINE far *findaddress(adr,table)
  624. int adr;
  625. LINE far *table;
  626. {
  627.  
  628.   while(table->link != 0)
  629.   {
  630.     if (table->address == adr)
  631.       return(table);
  632.     table = table->link;
  633.    }
  634.    return(0);
  635. }
  636. /*******************************
  637. * SYMBOL TABLE ROUTINES
  638. I*******************************/
  639. /*
  640.   adds symbol info to the table
  641. */
  642. int addsym(table,buf)
  643. SYMBOL far *table;
  644. char *buf;
  645. {
  646.   char *fstrg();
  647.   int i;
  648.   int n;
  649.   char *tptr;
  650.  
  651.   tptr = buf;
  652.   while (*tptr == ' ')
  653.     tptr++;
  654.   i = xatoi(tptr);
  655.   if (i != (_DS - _CS))
  656.     return(0);
  657.   while(table->link != 0)
  658.     table  = table->link;
  659.   while (*tptr != ':')
  660.     tptr++;
  661.   tptr++;
  662.   n = xatoi(tptr);
  663.   table->offset = n;
  664.   while (*tptr != '_')
  665.     tptr++;
  666.   tptr++;
  667.   i = 0;
  668.   while(*tptr > ' ')
  669.     table->name[i++] = *tptr++;
  670.   table->name[i] = 0;
  671.   table->link = farmalloc(sizeof(SYMBOL));
  672.   table = table->link;
  673.   if (table == 0)                  /* out of memory */
  674.     return(-1);
  675.   table->link = 0;
  676.   return(1);
  677. }
  678. /*
  679.   finds a symbol in the table
  680. */
  681. SYMBOL far *findsym(s,table)
  682. char *s;
  683. SYMBOL far *table;
  684. {
  685.   char *fstrg();
  686.   int i;
  687.  
  688.   while(table->link != 0)
  689.   {
  690.     if (strcmp(s,fstrg(table->name)) == 0)
  691.       return(table);
  692.     table = table->link;
  693.    }
  694.    return(0);
  695. }
  696. /*******************************
  697. *  FORMATTED DATA PRINT
  698. *******************************/
  699. /*
  700.   uses printf to display the data
  701.   int the specified format
  702. */
  703. int printloc(mode,loc,idx)
  704. int mode;
  705. void *loc;
  706. int idx;
  707. {
  708.   int *iptr;
  709.   char *cptr;
  710.   float *fptr;
  711.   double *dptr;
  712.  
  713.   switch(mode & 7)
  714.   {
  715.     case 0:
  716.     case INT:
  717.            iptr = (int *)loc + idx;
  718.            if (mode & POINTER)
  719.              printf("%04X = %d   %#X\n",*iptr,*((int *)*iptr),*(int *)*iptr);
  720.            else
  721.              printf("%04X  = %d   %#X\n",iptr,*iptr,*iptr);
  722.            break;
  723.     case CHAR:
  724.            cptr = (char *)loc + idx;
  725.            if (mode & POINTER)
  726.              printf("%04X  = %s\n",cptr,cptr);
  727.            else
  728.              printf("%04X  = %c   %#X\n",cptr,*cptr,*cptr);
  729.            break;
  730.     case FLOAT:
  731.            fptr = (float *)loc + idx;
  732.            if (mode & POINTER)
  733.              printf("%04X  = %g\n",*fptr,*(float *)fptr);
  734.            else
  735.              printf("%04X  = %g\n",fptr,*fptr);
  736.            break;
  737.     case DOUBLE:
  738.            dptr = (double *)loc + idx;
  739.            if (mode & POINTER)
  740.              printf("%04X  = %lg\n",*dptr,*(double *)dptr);
  741.            else
  742.              printf("%04X  = %lg\n",dptr,*dptr);
  743.            break;
  744.     default:
  745.            puts("MODE NOT SUPPORTED");
  746.   }
  747.   return(0);
  748. }
  749.  
  750. /*******************************
  751. * ASCII NUMBER CONVERSIONS
  752. *******************************/
  753. /*
  754.     converts a number in the various
  755.     C formats to an integer
  756. */
  757. int getnum(s)
  758. char *s;
  759. {
  760.   int val;
  761.  
  762.   if (*s == '0')
  763.   {
  764.     s++;
  765.     if (toupper(*s) == 'X')
  766.     {
  767.       s++;
  768.       val = xatoi(s);
  769.     }
  770.     else
  771.       val = oatoi(s);
  772.   }
  773.   else
  774.     val = atoi(s);
  775.   return(val);
  776. }
  777. /*
  778.     octal ascii to integer conversion
  779. */
  780. int oatoi(s)
  781. char *s;
  782. {
  783.   int num;
  784.   num = 0;
  785.   while((*s >= '0') && (*s <= '7'))
  786.   {
  787.     num = num << 3;
  788.     num = num + (*s++ - '0');
  789.   }
  790.   return(num);
  791. }
  792. /*
  793.     hexadecimal ascii to integer conversion
  794. */
  795. int xatoi(s)
  796. char *s;
  797. {
  798.   int num;
  799.   num = 0;
  800.   while(isxdigit(*s))
  801.   {
  802.     num = num << 4;
  803.     if (*s <= '9')
  804.       num = num + (*s++ - '0');
  805.     else
  806.       num = num + (toupper(*s++) - 'A' + 10);
  807.   }
  808.   return(num);
  809. }
  810.  
  811. /*******************************
  812. * BREAKPOINT and TRACE HANDLERS
  813. *******************************/
  814. LINE far *brkline;
  815. void interrupt brk_handler(regs)
  816. INTREGS regs;
  817. {
  818.   LINE far *findaddress();
  819.  
  820.   regs.ip--;
  821.   brkline = findaddress(regs.ip,linetable);
  822.   if (brkline == 0)
  823.     printf("INTERRUPT 3 AT ADDRESS = %02X\n",regs.ip++);
  824.   else
  825.   {
  826.     switch(brkline->flag)
  827.     {
  828.       case BREAK:
  829.                  printf("BREAKPOINT");
  830.                  break;
  831.       case STEP:
  832.                  printf("STEP");
  833.                  break;
  834.       default:
  835.                  printf("INTERRUPT 3");
  836.                  regs.ip++;
  837.     }
  838.     printf(" AT LINE %d = %04X\n",brkline->line_number,brkline->address);
  839.   }
  840.   enable();                /* enable other interrupts */
  841.   if (cmdline(®s) != 0) /* we need trace to resotre bkpts */
  842.     regs.flags = regs.flags | 0x100;
  843.   pokeb(_CS,brkline->address,brkline->opcode);
  844. }
  845.  
  846. void interrupt trace_handler(regs)
  847. INTREGS regs;
  848. {
  849.   if (brkline == 0)
  850.   {
  851.     printf("TRACE AT %04X\n",regs.ip);
  852.     cmdline(®s);
  853.   }
  854.   else
  855.   {
  856.     if (brkline->flag != NOBREAK)
  857.       pokeb(_CS,brkline->address,0xCC);
  858.   }
  859.   regs.flags = regs.flags & 0xFF;
  860. }
  861.