Hackfix and re-enable strtoull and wcstoull, see bug #3798.
[sdcc.git] / sdcc / debugger / mcs51 / break.c
blobefec91e53d5349fcf3499732c3605ff62b99da83
1 /*-------------------------------------------------------------------------
2 break.c - Source file for break point management
3 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 In other words, you are welcome to use, share and improve this program.
20 You are forbidden to forbid anyone else to use, share and improve
21 what you give them. Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
24 #include "sdcdb.h"
25 #undef DATADIR
26 #include "symtab.h"
27 #include "break.h"
28 #include "cmd.h"
29 #include "newalloc.h"
31 hTab *bptable = NULL;
32 char doingSteps = 0;
33 char userBpPresent = 0;
35 /* call stack can be 1024 deep */
36 STACK_DCL(callStack,function *,1024)
38 #ifdef SDCDB_DEBUG
39 char *debug_bp_type_strings[] =
40 {"ERR-0",
41 "DATA",
42 "CODE" ,
43 "A_CODE" ,
44 "USER" ,
45 "STEP" ,
46 "NEXT" ,
47 "FENTRY" ,
48 "FEXIT", "TMPUSER", ""};
49 #endif
51 static long bpnum = 0;
53 long getLastBreakptNumber()
55 return bpnum;
58 void resetHitCount()
60 int k;
61 breakp *bp;
62 for ( bp = hTabFirstItem(bptable,&k); bp ;
63 bp = hTabNextItem(bptable,&k))
65 bp->hitCnt = 0;
66 bp->ignoreCnt = 0;
70 /*-----------------------------------------------------------------*/
71 /* setBreakPoint - creates an entry in the break point table */
72 /*-----------------------------------------------------------------*/
73 int setBreakPoint (unsigned addr, char addrType, char bpType,
74 int (*callBack)(unsigned,breakp *,context *) ,
75 char *fileName, int lineno)
77 breakp *bp, *bpl;
79 Dprintf(D_break, ("setBreakPoint: addr:%x atype:%s bpType:%s [%s:%d]\n",
80 addr,
81 debug_bp_type_strings[(int)addrType],
82 debug_bp_type_strings[(int)bpType],
83 fileName, lineno+1));
85 /* allocate & init a new bp */
86 bp = Safe_calloc(1,sizeof(breakp));
87 bp->addr = addr;
88 bp->addrType = addrType;
89 bp->bpType = bpType;
90 bp->callBack = callBack;
91 bp->bpnum = ((bpType == USER || bpType == TMPUSER)? ++bpnum : 0);
92 bp->filename = fileName;
93 bp->lineno = lineno;
95 /* if this is an user break point then
96 check if there already exists one for this address */
97 if (bpType == USER || bpType == TMPUSER)
99 for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl;
100 bpl = hTabNextItemWK(bptable))
103 /* if also a user break point then issue Note : */
104 if (bpl->bpType == USER || bpType == TMPUSER)
105 fprintf(stderr,"Note: breakpoint %d also set at pc 0x%x\n",
106 bpl->bpnum,bpl->addr);
109 fprintf(stderr,"Breakpoint %d at 0x%x: file %s, line %d.\n",
110 bp->bpnum, addr, fileName, lineno+1);
112 userBpPresent++;
115 if (bpType != STEP && bpType != NEXT)
117 /* if a break point does not already exist then
118 send command to simulator to add one */
119 if (!hTabSearch(bptable,addr))
120 /* send the break command to the simulator */
121 simSetBP (addr);
124 /* now add the break point to list */
125 hTabAddItem(&bptable,addr,bp);
127 return bp->bpnum ;
130 /*-----------------------------------------------------------------*/
131 /* deleteSTEPbp - deletes all step break points */
132 /*-----------------------------------------------------------------*/
133 void deleteSTEPbp ()
135 breakp *bp;
136 int k;
138 Dprintf(D_break, ("break: Deleting all STEP BPs\n"));
139 /* for break points delete if they are STEP */
140 for ( bp = hTabFirstItem(bptable,&k); bp ;
141 bp = hTabNextItem(bptable,&k))
144 /* if this is a step then delete */
145 if (bp->bpType == STEP)
147 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
148 Safe_free(bp);
154 /*-----------------------------------------------------------------*/
155 /* deleteNEXTbp - deletes all step break points */
156 /*-----------------------------------------------------------------*/
157 void deleteNEXTbp ()
159 breakp *bp;
160 int k;
162 Dprintf(D_break, ("break: Deleting all NEXT BPs\n"));
164 /* for break points delete if they are NEXT */
165 for ( bp = hTabFirstItem(bptable,&k); bp ;
166 bp = hTabNextItem(bptable,&k))
169 /* if this is a step then delete */
170 if (bp->bpType == NEXT)
172 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
173 Safe_free(bp);
179 static void freeUSERbp(breakp *bp)
181 if ( bp->commands )
182 Safe_free(bp->commands);
183 if ( bp->condition )
184 Safe_free(bp->condition);
185 Safe_free(bp);
188 /*-----------------------------------------------------------------*/
189 /* deleteUSERbp - deletes USER break point with number */
190 /*-----------------------------------------------------------------*/
191 void deleteUSERbp (int bpnum)
193 breakp *bp;
194 int k;
196 Dprintf(D_break, ("break: deleteUSERbp %d\n", bpnum));
198 /* for break points delete if they are STEP */
199 for ( bp = hTabFirstItem(bptable,&k); bp ;
200 bp = hTabNextItem(bptable,&k)) {
202 /* if this is a user then delete if break
203 point matches or bpnumber == -1 (meaning delete
204 all user break points */
205 if ((bp->bpType == USER || bp->bpType == TMPUSER )
206 && ( bp->bpnum == bpnum || bpnum == -1))
208 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
210 /* if this leaves no other break points then
211 send command to simulator to delete bp from this addr */
212 if (hTabSearch(bptable,bp->addr) == NULL) {
213 simClearBP (bp->addr);
214 Dprintf(D_break, ("break: deleteUSERbp:simClearBP 0x%x\n", bp->addr));
217 fprintf(stdout,"Deleted breakpoint %d\n",bp->bpnum);
218 userBpPresent-- ;
219 freeUSERbp(bp);
220 if (bpnum == -1)
221 continue ;
222 else
223 break;
227 if (!bp && bpnum != -1)
228 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
231 /*-----------------------------------------------------------------*/
232 /* setUserbpCommand - set commandstring for breakpoint */
233 /*-----------------------------------------------------------------*/
234 void setUserbpCommand (int bpnum, char *cmds)
236 breakp *bp;
237 int k;
238 Dprintf(D_break, ("break: setUserbpCommand %d: commands:\n%send\n",
239 bpnum, cmds));
241 for ( bp = hTabFirstItem(bptable,&k); bp ;
242 bp = hTabNextItem(bptable,&k))
244 if ((bp->bpType == USER || bp->bpType == TMPUSER )
245 && ( bp->bpnum == bpnum ))
247 if ( bp->commands )
248 Safe_free(bp->commands);
249 bp->commands = cmds;
250 return;
253 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
256 /*-----------------------------------------------------------------*/
257 /* setUserbpCondition - set condition string for breakpoint */
258 /*-----------------------------------------------------------------*/
259 void setUserbpCondition (int bpnum, char *cond)
261 breakp *bp;
262 int k;
263 Dprintf(D_break, ("break: setUserbpCondition %d: condition:'%s'\n",
264 bpnum, cond?cond:""));
266 for ( bp = hTabFirstItem(bptable,&k); bp ;
267 bp = hTabNextItem(bptable,&k))
269 if ((bp->bpType == USER || bp->bpType == TMPUSER )
270 && ( bp->bpnum == bpnum ))
272 if ( bp->condition )
273 Safe_free(bp->condition);
274 bp->condition = cond;
275 return;
278 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
281 /*-----------------------------------------------------------------*/
282 /* setUserbpIgnCount - set ignorecount for breakpoint */
283 /*-----------------------------------------------------------------*/
284 void setUserbpIgnCount (int bpnum, int ignorecnt )
286 breakp *bp;
287 int k;
288 Dprintf(D_break, ("break: setUserbpIgnCount %d: ignorecnt=%d\n",
289 bpnum, ignorecnt));
291 for ( bp = hTabFirstItem(bptable,&k); bp ;
292 bp = hTabNextItem(bptable,&k))
294 if ((bp->bpType == USER || bp->bpType == TMPUSER )
295 && ( bp->bpnum == bpnum ))
297 bp->ignoreCnt = bp->hitCnt + ignorecnt;
298 return;
301 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
304 /*-----------------------------------------------------------------*/
305 /* listUSERbp - list all user break points */
306 /*-----------------------------------------------------------------*/
307 void listUSERbp ()
309 breakp *bp;
310 int k, isuser;
312 /* if there are none then say so & return */
313 if (!userBpPresent) {
314 fprintf(stdout,"No breakpoints.\n");
315 return ;
317 fprintf(stdout,"Num Type Disp Enb Address What\n");
318 for ( bp = hTabFirstItem(bptable,&k) ; bp ;
319 bp = hTabNextItem(bptable,&k)) {
321 isuser = 0;
322 if (bp->bpType == USER ) {
323 fprintf(stdout,"%-3d breakpoint keep y 0x%08x at %s:%d\n",
324 bp->bpnum,bp->addr,
325 bp->filename,bp->lineno+1);
326 isuser = 1;
328 else if (bp->bpType == TMPUSER ) {
329 fprintf(stdout,"%-3d breakpoint del y 0x%08x at %s:%d\n",
330 bp->bpnum,bp->addr,
331 bp->filename,bp->lineno+1);
332 isuser = 1;
334 if ( ! isuser )
335 continue;
336 if ( bp->ignoreCnt > bp->hitCnt )
337 fprintf(stdout,"\tignore next %d hits\n",
338 bp->ignoreCnt - bp->hitCnt );
339 if ( bp->condition )
340 fprintf(stdout,"\tstop only if %s\n",bp->condition );
341 if ( bp->hitCnt > 0 )
342 fprintf(stdout,"\tbreakpoint already hit %d time%s\n",
343 bp->hitCnt,bp->hitCnt>1?"s":"" );
349 /*-----------------------------------------------------------------*/
350 /* simStopBPCB - simulator stopped break point */
351 /*-----------------------------------------------------------------*/
352 static int simStopBPCB( unsigned int addr)
354 fprintf(stdout,"Simulator stopped at Address 0x%04x\n",addr);
355 fprintf(stdout,"%s",simResponse());
356 return 1;
359 /*-----------------------------------------------------------------*/
360 /* clearUSERbp - deletes USER break point at address */
361 /*-----------------------------------------------------------------*/
362 void clearUSERbp ( unsigned int addr )
364 breakp *bp;
366 /* for break points delete if they are STEP */
367 for ( bp = hTabFirstItemWK(bptable,addr); bp ;
368 bp = hTabNextItemWK(bptable)) {
370 /* if this is a step then delete */
371 if (bp->bpType == USER || bp->bpType == TMPUSER)
373 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
375 /* if this leaves no other break points then
376 send command to simulator to delete bp from this addr */
377 if (hTabSearch(bptable,bp->addr) == NULL)
379 simClearBP(bp->addr);
381 fprintf(stdout,"Deleted breakpoint %d\n",
382 bp->bpnum);
383 userBpPresent-- ;
384 freeUSERbp(bp);
385 break;
389 if (!bp)
390 fprintf(stderr,"No breakpoint at address 0x%x.\n",addr);
393 /*-----------------------------------------------------------------*/
394 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
395 /*-----------------------------------------------------------------*/
396 int dispatchCB (unsigned addr, context *ctxt)
398 breakp *bp;
399 int rv =0;
401 Dprintf(D_break, ("break: dispatchCB: addr:0x%x \n", addr));
403 /* if no break points set for this address
404 then use a simulator stop break point */
405 if ((bp = hTabFirstItemWK(bptable,addr)) == NULL) {
406 if ( doingSteps == 2 ) return 1;
407 if ( doingSteps ) return 0;
408 if ( contsim ) return 0;
409 return simStopBPCB(addr);
412 /* dispatch the call back functions */
413 for (; bp; bp = hTabNextItemWK(bptable))
415 rv += (*bp->callBack)(addr,bp,ctxt);
418 if (rv == 0) {
419 Dprintf(D_break, ("break: dispatchCB: WARNING rv==0\n"));
422 return rv;
425 /*-----------------------------------------------------------------*/
426 /* fentryCB - callback function for function entry */
427 /*-----------------------------------------------------------------*/
428 BP_CALLBACK(fentryCB)
430 function *func;
432 /* we save the value of SP
433 which will be used to display the value of local variables
434 and parameters on the stack */
435 ctxt->func->stkaddr = simGetValue (0x81,'I',1);
437 Dprintf(D_break, ("break: fentryCB: BP_CALLBACK entry %s sp=0x%02x %p\n",
438 ctxt->func->sym->name,
439 ctxt->func->stkaddr, p_callStack));
441 /* and set laddr of calling function to return addr from stack */
442 if ((func = STACK_PEEK(callStack)))
444 /* extern stack ?? 'A' */
445 func->laddr = simGetValue (ctxt->func->stkaddr-1,'B',2);
447 /* add the current function into the call stack */
448 STACK_PUSH(callStack,ctxt->func);
450 return 0;
453 /*-----------------------------------------------------------------*/
454 /* fexitCB - call back for function exit */
455 /*-----------------------------------------------------------------*/
456 BP_CALLBACK(fexitCB)
458 function *func;
459 /* pop the top most from the call stack */
460 func = STACK_POP(callStack);
462 if (!func)
464 fprintf(stdout, "Stack underflow\n");
465 return 1;
468 Dprintf(D_break, ("break: fexitCB: BP_CALLBACK entry %s %p\n", func->sym->name, p_callStack));
470 /* check main function */
471 if ( !strcmp(func->sym->name, "main"))
473 fprintf(stdout, "Program exited with code %lu.\n", simGetValue (0x82,'I',2));
474 return 1;
476 return 0;
478 /*-----------------------------------------------------------------*/
479 /* userBpCB - call back function for user break points */
480 /*-----------------------------------------------------------------*/
481 BP_CALLBACK(userBpCB)
483 bp->hitCnt++ ;
484 Dprintf(D_break, ("break: userBpCB: BP_CALLBACK entry hit=%d ignor=%d\n",
485 bp->hitCnt, bp->ignoreCnt));
487 if ( bp->ignoreCnt > bp->hitCnt )
488 return 0;
490 if ( bp->condition )
492 if (! conditionIsTrue( bp->condition, ctxt ))
493 return 0;
496 if ( bp->commands )
498 Dprintf(D_break, ("break: userBpCB: commands:%p\n", bp->commands));
499 setCmdLine(bp->commands);
502 if (srcMode == SRC_CMODE) {
503 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
504 bp->bpnum,
505 ctxt->func->sym->name,
506 ctxt->func->mod->c_name,
507 ctxt->cline+1);
508 if (ctxt->func->mod && ctxt->cline > 0)
509 fprintf(stdout,"%d\t%s",ctxt->cline+1,
510 ctxt->func->mod->cLines[ctxt->cline]->src);
511 } else {
512 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
513 bp->bpnum,
514 ctxt->func->sym->name,
515 ctxt->func->mod->asm_name,
516 ctxt->asmline+1);
517 if (ctxt->func->mod && ctxt->asmline > 0)
518 fprintf(stdout,"%d\t%s",ctxt->asmline+1,
519 ctxt->func->mod->asmLines[ctxt->asmline]->src);
522 if ( bp->bpType == TMPUSER && bp->bpnum > 0 )
524 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
526 /* if this leaves no other break points then
527 send command to simulator to delete bp from this addr */
528 if (hTabSearch(bptable,bp->addr) == NULL)
530 simClearBP (bp->addr);
531 Dprintf(D_break, ("break: simClearBP 0x%x\n", bp->addr));
534 userBpPresent-- ;
535 freeUSERbp(bp);
537 return 1;
540 /*-----------------------------------------------------------------*/
541 /* stepBpCB - call back function for step break points */
542 /*-----------------------------------------------------------------*/
543 BP_CALLBACK(stepBpCB)
545 static function *lfunc = NULL;
547 Dprintf(D_break, ("break: stepBpCB: BP_CALLBACK entry\n"));
549 if (srcMode == SRC_CMODE) {
550 if ((lfunc && lfunc != ctxt->func) || !lfunc)
551 fprintf(stdout,"%s () at %s:%d\n",
552 ctxt->func->sym->name,
553 ctxt->func->mod->c_name,
554 ctxt->cline+1);
556 if (ctxt->func->mod && ctxt->cline > 0) {
557 fprintf(stdout,"%d\t%s",ctxt->cline+1 ,
558 ctxt->func->mod->cLines[ctxt->cline]->src);
560 } else {
561 if ((lfunc && lfunc != ctxt->func) || !lfunc)
562 fprintf(stdout,"%s () at %s:%d\n",
563 ctxt->func->sym->name,
564 ctxt->func->mod->asm_name,
565 ctxt->asmline);
567 if (ctxt->func->mod && ctxt->cline > 0) {
568 fprintf(stdout,"%d\t%s",ctxt->asmline ,
569 ctxt->func->mod->asmLines[ctxt->asmline]->src);
572 lfunc = ctxt->func;
574 deleteSTEPbp();
575 return 1;
578 /*-----------------------------------------------------------------*/
579 /* nextBpCB - call back function for next break points */
580 /*-----------------------------------------------------------------*/
581 BP_CALLBACK(nextBpCB)
583 static function *lfunc = NULL;
585 Dprintf(D_break, ("break: nextBpCB: BP_CALLBACK entry\n"));
587 if (srcMode == SRC_CMODE) {
588 if ((lfunc && lfunc != ctxt->func) || !lfunc)
589 fprintf(stdout,"%s () at %s:%d\n",
590 ctxt->func->sym->name,
591 ctxt->func->mod->c_name,
592 ctxt->cline+1);
594 if (ctxt->func->mod && ctxt->cline > 0)
595 fprintf(stdout,"%d\t%s",ctxt->cline+1,
596 ctxt->func->mod->cLines[ctxt->cline]->src);
597 } else {
598 if ((lfunc && lfunc != ctxt->func) || !lfunc)
599 fprintf(stdout,"%s () at %s:%d\n",
600 ctxt->func->sym->name,
601 ctxt->func->mod->asm_name,
602 ctxt->asmline);
604 if (ctxt->func->mod && ctxt->asmline > 0)
605 fprintf(stdout,"%d\t%s",ctxt->asmline,
606 ctxt->func->mod->asmLines[ctxt->asmline]->src);
609 lfunc = ctxt->func;
611 deleteNEXTbp();
612 return 1;