home *** CD-ROM | disk | FTP | other *** search
- /**************************************************
- *
- * SOURCE LEVEL DEBUG MODULE FOR TURBO C
- * by: Gary L. Mellor Sept 1987
- *
- **************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include <alloc.h>
- #include <dos.h>
-
- /* IDENTIFIER ATTRIBUTE CODES */
-
- #define INT 1
- #define CHAR 2
- #define FLOAT 3
- #define DOUBLE 4
- #define POINTER 0x1000
- #define ADDRESS 0x2000
-
- /* COMMAND CODES */
-
- #define HELP 1
- #define MAP 2
- #define SYMS 3
- #define LIST 4
- #define PRINT 5
- #define BREAK 6
- #define NOBREAK 7
- #define STEP 8
- #define CONTINUE 9
- #define TRACE 10
- #define REGISTERS 11
- #define QUIT 12
-
-
- typedef struct /* INTERRUPT REGISTERS */
- {
- unsigned int bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags;
- }INTREGS;
-
-
- typedef struct /* LINE NUMBER TABLE ENTRY */
- {
- int line_number;
- int address;
- unsigned char flag;
- unsigned char opcode;
- void far *link;
- }LINE;
-
-
- typedef struct /* SYMBOL TABLE ENTRY */
- {
- char name[32];
- int offset;
- void far *link;
- }SYMBOL;
-
- typedef struct /* DECODE LIST ENTRY */
- {
- int key;
- char *string;
- }DECODELIST;
-
- /* COMMAND DECODE LIST IS ALSO USED TO DISPLAY HELP */
-
- DECODELIST cmdlist[]=
- {
- HELP, "HELP\n\nCOMMAND PARAM(s) <>=optional FUNCTION\n",
- MAP, "MAP lists the line numbers",
- SYMS, "SYMS lists the public symbols",
- LIST, "LIST <line_number> lists the source file",
- PRINT, "PRINT <type> identifier prints the value",
- BREAK, "BREAK <line_number> sets/lists the breakpoint(s)",
- NOBREAK, "NOBREAK line_number removes a breakpoint",
- STEP, "STEP steps to the next source line",
- CONTINUE, "CONTINUE executes to next breakpoint",
- REGISTERS,"REGISTERS displays the cpu registers",
- QUIT, "QUIT terminates the program",
- 0,0
- };
-
- /* IDENTIFIER ATTRIBUTE DECODE LIST FOR PRINT COMMAND */
- DECODELIST keylist[]=
- {
- INT,"INT",
- CHAR,"CHAR",
- FLOAT,"FLOAT",
- DOUBLE,"DOUBLE",
- 0,0
- };
-
- LINE far *linetable;
- SYMBOL far *symtable;
- void interrupt (*vect1)();
- void interrupt (*vect3)();
-
- /*******************************
- * DEBUG INITIALIZATION
- *******************************/
- int debug_init(name)
- char *name;
- {
- void interrupt brk_handler();
- void interrupt trace_handler();
- void debug_exit();
-
- FILE *mapfile;
- char mapname[40];
- char sname[40];
- char buffer[80];
- char *ptr;
- int i;
-
- i = 0;
- while (*name && (*name != '.'))
- mapname[i++] = *name++;
- mapname[i] = 0;
- strcat(mapname,".MAP");
- mapfile = fopen(mapname,"r");
- if (mapfile == 0)
- {
- printf("MAPFILE NOT FOUND: %s\n",mapname);
- return(-1);
- }
- while(fgets(buffer,80,mapfile))
- {
- /* locate public symbols */
- if (strstr(buffer,"Publics by Val"))
- {
- /* allocate root entry */
- symtable = farmalloc(sizeof(SYMBOL));
- symtable->link = 0;
- fgets(buffer,80,mapfile); /* dump blank line */
- do /* build symbol table */
- {
- fgets(buffer,80,mapfile);
- i = addsym(symtable,buffer);
- if (i < 0)
- break;
- }
- while(buffer[0] == ' ');
- break;
- }
- }
- while(fgets(buffer,80,mapfile))
- {
- /* locate the line numbers */
- if (buffer[0] == 'L')
- {
- /* allocate root entry */
- linetable = farmalloc(sizeof(LINE));
- linetable->link = 0;
- /* extract source file name */
- ptr = strchr(buffer,'(');
- ptr++;
- i = 0;
- while (*ptr != ')')
- sname[i++] = *ptr++;
- sname[i] = 0;
- fgets(buffer,80,mapfile); /* dump blank line */
- do /* build the line number table */
-
- {
- fgets(buffer,80,mapfile);
- i = addlines(linetable,buffer);
- }while(i > 0);
- if (i < 0)
- {
- puts("NOT ENOUGH MEMORY FOR DEBUGGER");
- return(-1);
- }
- break;
- }
- }
- fclose(mapfile);
- vect1 = getvect(1); /* save old vectors */
- vect3 = getvect(3);
- if (cmdline(0,sname) != 0) /* bkpts have been set */
- {
- setvect(1,&trace_handler); /* so init our vectors */
- setvect(3,&brk_handler);
- atexit(debug_exit); /* and exit handler */
-
- }
- return(0);
- }
- /*******************************
- * DEBUG EXIT HANDLER
- *******************************/
- void debug_exit()
- {
- printf("\nPROGRAM TERMINATION\n");
- setvect(1,vect1);
- setvect(3,vect3);
-
- }
- /*******************************
- * COMMAND LINE INPUT HANDLER
- ********************************/
- /*
- prompts for operator input
- and handles commands
- */
- int cmdline(regs,file)
- INTREGS *regs;
- char *file;
- {
- LINE far *findline();
- SYMBOL far *findsym();
- char *fstrg();
- char *next();
-
- char temp[132];
- char *tptr;
- int brkline;
- int listline;
- int address;
- int index;
- LINE far *line;
- SYMBOL far *symbol;
-
- static int cmd;
- static FILE *fp;
- static char name[15];
- int i;
- int mode;
- int flag;
-
- if (regs == 0) /* if called from debug_init */
- {
- fp = fopen(file,"r"); /* open the source file */
- strcpy(name,file);
- }
- listline = 1;
- for(;;)
- {
- printf("TBUG?? "); /* prompt for and */
- gets(temp); /* input command line */
- tptr = temp;
- while (*tptr == ' ') /* skip leading spaces */
- tptr++;
- if (*tptr != 0) /* if more than RETURN then */
- /* decode new command code */
- cmd = decode(tptr,cmdlist);
- switch(cmd) /* process command code */
- {
- case HELP:
- i = 0;
- while(cmdlist[i].key != 0)
- puts(cmdlist[i++].string);
- break;
- case MAP:
- line = linetable;
- i = 0;
- printf("LINE NUMBERS FOR %s\n",name);
- while(line->link != 0)
- {
- if ((i++ % 4) == 0)
- putchar('\n');
- printf("%4d %04X ",
- line->line_number,line->address);
- line = line->link;
- }
- putchar('\n');
- break;
- case SYMS:
- symbol = symtable;
- while(symbol->link != 0)
- {
- if ((i++ % 2) == 0)
- putchar('\n');
- printf("%32s %04X ",
- fstrg(symbol->name),symbol->offset);
- symbol = symbol->link;
- }
- putchar('\n');
- break;
- case PRINT:
- tptr = next(tptr);
- if (*tptr != 0)
- {
- mode = 0;
- do
- {
- i = decode(tptr,keylist);
- if (i != 0)
- tptr = next(tptr);
- mode = mode | i;
- }while (i != 0);
- i = 0;
- if (*tptr == '*')
- {
- mode = mode | POINTER;
- tptr++;
- }
- while ((*tptr != 0) && (strchr(" +-[",*tptr) == 0))
- temp[i++] = *tptr++;
- temp[i] = 0;
- while(*tptr == ' ')
- tptr++;
- switch(*tptr++)
- {
- case '+':
- case '[':
- while (*tptr == ' ')
- tptr++;
- index = getnum(tptr);
- break;
- case '-':
- while (*tptr == ' ')
- tptr++;
- index = -(getnum(tptr));
- break;
- default:
- index = 0;
- }
- if (isalpha(temp[0]))
- {
- symbol = findsym(temp,symtable);
- if (symbol == 0)
- {
- puts("SYMBOL NOT FOUND");
- break;
- }
- address = symbol->offset;
- }
- else
- {
- if (strcmp(temp,"_BP") == 0)
- {
- address = regs->bp + index;
- index = 0;
- }
- else
- address = getnum(temp);
- }
- printloc(mode,address,index);
- }
- else
- puts("VARIABLE MUST BE SPECIFIED");
- break;
- case LIST:
- if (fp == 0)
- puts("SOURCE NOT AVAILABLE");
- else
- {
- tptr = next(tptr);
- if (*tptr != 0)
- {
- rewind(fp);
- listline = atoi(tptr);
- i = listline - 1;
- if ( i < 0)
- i = 0;
- }
- else
- i = 0;
- while(i-- > 0)
- fgets(temp,132,fp);
- for (i = 0; i < 20; i++)
- {
- if (fgets(temp,132,fp))
- printf ("%03d: %s",listline++,temp);
- else
- {
- puts("*****END OF FILE*****");
- break;
- }
- }
- }
- break;
- case BREAK:
- tptr = next(tptr);
- if (*tptr != 0)
- {
- brkline = atoi(tptr);
- line = findline(brkline,linetable);
- if (line == 0)
- puts("LINE NOT FOUND");
- else
- {
- if (line->flag != BREAK)
- {
- line->flag = BREAK;
- pokeb(_CS,line->address,0xCC);
- }
- else
- puts("BREAK ALREADY SET");
- }
- }
- else
- {
- for(line = linetable; line->link != 0; line = line->link)
- {
- if (line->flag == BREAK)
- {
- printf("%d %04X\n",line->line_number,
- line->address);
- }
- }
- }
- break;
- case NOBREAK:
- tptr = next(tptr);
- brkline = atoi(tptr);
- line = findline(brkline,linetable);
- if (line == 0)
- puts("LINE NOT FOUND");
- else
- {
- if (line->flag == BREAK)
- {
- line->flag = NOBREAK;
- pokeb(_CS,line->address,line->opcode);
- }
- else
- puts("BREAK NOT SET");
- }
- break;
- case REGISTERS:
- printf("AX = %04X BX = %04X CX = %04X DX = %04X\n",
- regs->ax,regs->bx,regs->cx,regs->dx);
- printf("BP = %04X SI = %04X DI = %04X IP = %04X\n",
- regs->bp,regs->si,regs->di,regs->ip);
- printf("DS = %04X ES = %04X CS = %04X FLAGS %02X\n",
- regs->ds,regs->es,regs->cs,regs->flags&0xFF);
- break;
- case CONTINUE:
- line = linetable;
- i = 0;
- flag = 0;
- while(line->link != 0)
- {
- if (line->flag != BREAK) /* restore proper opcode */
- {
- line->flag = NOBREAK;
- pokeb(_CS,line->address,line->opcode);
- }
- else
- flag = 1; /* we have at least one bkpt */
- line = line->link;
- }
- if (flag == 0)
- {
- setvect(1,vect1);
- setvect(3,vect3);
- }
- return(flag); /* tell caller if have bkpts */
- case STEP:
- line = linetable;
- while(line->link != 0)
- {
- if (line->flag != BREAK)
- {
- line->flag = STEP;
- pokeb(_CS,line->address,0xCC);
- }
- line = line->link;
- }
- return(1); /* we definately have bkpts */
- case QUIT:
- exit(0);
- case -1:
- puts("COMMAND SPELLING NOT UNIQUE");
- break;
- default:
- puts("INVALID COMMAND");
- }
- }
- }
- /*******************************
- * STRING HANDELING ROUTINES
- *******************************/
- /*
- decode compares a command string
- to a command list and returns a
- command key. More than one match
- means enough chars in command spelling
- to decode the command.
- */
- int decode(s,list)
- char s[];
- DECODELIST list[];
- {
- int i;
- int idx;
-
- i = 0;
- idx = 0;
- while(list[i].key) /* while not end of list */
- {
- if (match(s,list[i].string))
- {
- if (idx == 0) /* first match OK */
- idx = list[i].key;
- else
- return(-1); /* multiple match NOT OK */
- }
- i++;
- }
- return(idx);
- }
- /*
- string comparison is a match
- if all chars of string s1 match s2,
- even if we are not at end of s2
- */
- int match(s1,s2)
- char *s1;
- char *s2;
- {
- while (*s1 == ' ') /* skip leading spaces */
- s1++;
- while(*s1 > ' ') /* while valid char */
- {
- if (toupper(*s1++) != *s2++)
- return(0); /* we didnt match */
- }
- return(1);
- }
- /*
- next skips the current token
- and trailing spaces to return
- a pointer to the next token
- */
- char *next(s)
- char *s;
- {
- while(*s) /* skip over current token */
- {
- if (*s <= ' ')
- break;
- else
- s++;
- }
- while (*s) /* skip over spaces */
- {
- if (*s > ' ')
- break;
- else
- s++;
- }
- return(s);
- }
- /*
- moves a far string into local data space
- and returns a pointer to it.
- */
- char *fstrg(fs)
- char far *fs;
- {
- static char temp[80];
- int i;
-
- i = 0;
-
- while (*fs != 0)
- temp[i++] = *fs++;
- temp[i] = 0;
- return(&temp[0]);
- }
- /*******************************
- * LINE NUMBER TABLE ROUTINES
- *******************************/
- /*
- adds line numbers/offsets to table
- */
- int addlines(table,buf)
- LINE far *table;
- char *buf;
- {
- int count;
-
- while(table->link != 0)
- table = table->link;
- count = 0;
- while (*buf != 0)
- {
- if (isdigit(*buf))
- {
- table->line_number = atoi(buf);
- while(*buf++ != ':');
- table->address = xatoi(buf);
- table->flag = 0;
- table->opcode = peekb(_CS,table->address);
- while(isxdigit(*buf++));
- table->link = farmalloc(sizeof(LINE));
- table = table->link;
- table->link = 0;
- if (table == 0)
- return(-1);
- count++;
- }
- else
- buf++;
- }
- return(count);
- }
- /*
- finds a line number in the table
- */
- LINE far *findline(lnum,table)
- int lnum;
- LINE far *table;
- {
- int i;
-
- while(table->link != 0)
- {
- if (table->line_number == lnum)
- return(table);
- table = table->link;
- }
- return(0);
- }
- /*
- finds an address in the table
- */
- LINE far *findaddress(adr,table)
- int adr;
- LINE far *table;
- {
-
- while(table->link != 0)
- {
- if (table->address == adr)
- return(table);
- table = table->link;
- }
- return(0);
- }
- /*******************************
- * SYMBOL TABLE ROUTINES
- I*******************************/
- /*
- adds symbol info to the table
- */
- int addsym(table,buf)
- SYMBOL far *table;
- char *buf;
- {
- char *fstrg();
- int i;
- int n;
- char *tptr;
-
- tptr = buf;
- while (*tptr == ' ')
- tptr++;
- i = xatoi(tptr);
- if (i != (_DS - _CS))
- return(0);
- while(table->link != 0)
- table = table->link;
- while (*tptr != ':')
- tptr++;
- tptr++;
- n = xatoi(tptr);
- table->offset = n;
- while (*tptr != '_')
- tptr++;
- tptr++;
- i = 0;
- while(*tptr > ' ')
- table->name[i++] = *tptr++;
- table->name[i] = 0;
- table->link = farmalloc(sizeof(SYMBOL));
- table = table->link;
- if (table == 0) /* out of memory */
- return(-1);
- table->link = 0;
- return(1);
- }
- /*
- finds a symbol in the table
- */
- SYMBOL far *findsym(s,table)
- char *s;
- SYMBOL far *table;
- {
- char *fstrg();
- int i;
-
- while(table->link != 0)
- {
- if (strcmp(s,fstrg(table->name)) == 0)
- return(table);
- table = table->link;
- }
- return(0);
- }
- /*******************************
- * FORMATTED DATA PRINT
- *******************************/
- /*
- uses printf to display the data
- int the specified format
- */
- int printloc(mode,loc,idx)
- int mode;
- void *loc;
- int idx;
- {
- int *iptr;
- char *cptr;
- float *fptr;
- double *dptr;
-
- switch(mode & 7)
- {
- case 0:
- case INT:
- iptr = (int *)loc + idx;
- if (mode & POINTER)
- printf("%04X = %d %#X\n",*iptr,*((int *)*iptr),*(int *)*iptr);
- else
- printf("%04X = %d %#X\n",iptr,*iptr,*iptr);
- break;
- case CHAR:
- cptr = (char *)loc + idx;
- if (mode & POINTER)
- printf("%04X = %s\n",cptr,cptr);
- else
- printf("%04X = %c %#X\n",cptr,*cptr,*cptr);
- break;
- case FLOAT:
- fptr = (float *)loc + idx;
- if (mode & POINTER)
- printf("%04X = %g\n",*fptr,*(float *)fptr);
- else
- printf("%04X = %g\n",fptr,*fptr);
- break;
- case DOUBLE:
- dptr = (double *)loc + idx;
- if (mode & POINTER)
- printf("%04X = %lg\n",*dptr,*(double *)dptr);
- else
- printf("%04X = %lg\n",dptr,*dptr);
- break;
- default:
- puts("MODE NOT SUPPORTED");
- }
- return(0);
- }
-
- /*******************************
- * ASCII NUMBER CONVERSIONS
- *******************************/
- /*
- converts a number in the various
- C formats to an integer
- */
- int getnum(s)
- char *s;
- {
- int val;
-
- if (*s == '0')
- {
- s++;
- if (toupper(*s) == 'X')
- {
- s++;
- val = xatoi(s);
- }
- else
- val = oatoi(s);
- }
- else
- val = atoi(s);
- return(val);
- }
- /*
- octal ascii to integer conversion
- */
- int oatoi(s)
- char *s;
- {
- int num;
- num = 0;
- while((*s >= '0') && (*s <= '7'))
- {
- num = num << 3;
- num = num + (*s++ - '0');
- }
- return(num);
- }
- /*
- hexadecimal ascii to integer conversion
- */
- int xatoi(s)
- char *s;
- {
- int num;
- num = 0;
- while(isxdigit(*s))
- {
- num = num << 4;
- if (*s <= '9')
- num = num + (*s++ - '0');
- else
- num = num + (toupper(*s++) - 'A' + 10);
- }
- return(num);
- }
-
- /*******************************
- * BREAKPOINT and TRACE HANDLERS
- *******************************/
- LINE far *brkline;
- void interrupt brk_handler(regs)
- INTREGS regs;
- {
- LINE far *findaddress();
-
- regs.ip--;
- brkline = findaddress(regs.ip,linetable);
- if (brkline == 0)
- printf("INTERRUPT 3 AT ADDRESS = %02X\n",regs.ip++);
- else
- {
- switch(brkline->flag)
- {
- case BREAK:
- printf("BREAKPOINT");
- break;
- case STEP:
- printf("STEP");
- break;
- default:
- printf("INTERRUPT 3");
- regs.ip++;
- }
- printf(" AT LINE %d = %04X\n",brkline->line_number,brkline->address);
- }
- enable(); /* enable other interrupts */
- if (cmdline(®s) != 0) /* we need trace to resotre bkpts */
- regs.flags = regs.flags | 0x100;
- pokeb(_CS,brkline->address,brkline->opcode);
- }
-
- void interrupt trace_handler(regs)
- INTREGS regs;
- {
- if (brkline == 0)
- {
- printf("TRACE AT %04X\n",regs.ip);
- cmdline(®s);
- }
- else
- {
- if (brkline->flag != NOBREAK)
- pokeb(_CS,brkline->address,0xCC);
- }
- regs.flags = regs.flags & 0xFF;
- }