Additional corrections for Safe_calloc in sdcdb
[fw/sdcc] / debugger / mcs51 / break.c
1 /*-------------------------------------------------------------------------
2   break.c - Source file for break point management
3         Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
4
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.
9
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.
14
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.
18
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 -------------------------------------------------------------------------*/
23
24 #include "sdcdb.h"
25 #include "symtab.h"
26 #include "break.h"
27 #include "newalloc.h"
28
29 static hTab *bptable = NULL;
30 char userBpPresent = 0;
31 /* call stack can be 1024 deep */
32 STACK_DCL(callStack,function *,1024);
33
34 /*-----------------------------------------------------------------*/
35 /* setBreakPoint - creates an entry in the break point table       */
36 /*-----------------------------------------------------------------*/
37 int setBreakPoint (unsigned addr, char addrType, char bpType,
38         int (*callBack)(unsigned,char,char,int,context *) ,
39         char *fileName, int lineno)
40 {
41     breakp *bp, *bpl;
42     static long bpnum = 0;
43     char simbuf[50];
44
45     /* allocate & init a new bp */
46     bp = Safe_calloc(1,sizeof(breakp));
47     bp->addr = addr;
48     bp->addrType = addrType;
49     bp->bpType = bpType;
50     bp->callBack = callBack;
51     bp->bpnum = (bpType == USER ? ++bpnum : 0);
52     bp->filename = fileName;
53     bp->lineno = lineno;
54
55     /* if this is an user break point then
56        check if there already exists one for this address */
57     if (bpType == USER) {
58   for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl;
59         bpl = hTabNextItemWK(bptable)) {
60
61       /* if also a user break point then issue Note : */
62       if (bpl->bpType == USER)
63     fprintf(stderr,"Note: breakpoint %d also set at pc 0x%x\n",
64       bpl->bpnum,bpl->addr);
65   }
66
67   fprintf(stderr,"Breakpoint %d at 0x%x: file %s, line %d.\n",
68     bp->bpnum, addr, fileName, lineno);
69
70   userBpPresent++;
71     }
72
73     /* if a break point does not already exist then
74        send command to simulator to add one */
75     if (!hTabSearch(bptable,addr))
76   /* send the break command to the simulator */
77   simSetBP (addr);
78
79
80     /* now add the break point to list */
81     hTabAddItem(&bptable,addr,bp);
82
83     return bp->bpnum ;
84 }
85
86 /*-----------------------------------------------------------------*/
87 /* deleteSTEPbp - deletes all step break points                    */
88 /*-----------------------------------------------------------------*/
89 void deleteSTEPbp ()
90 {
91     breakp *bp;
92     int k;
93
94     /* for break points delete if they are STEP */
95     for ( bp = hTabFirstItem(bptable,&k); bp ;
96     bp = hTabNextItem(bptable,&k)) {
97
98   /* if this is a step then delete */
99   if (bp->bpType == STEP) {
100       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
101
102       /* if this leaves no other break points then
103          send command to simulator to delete bp from this addr */
104       if (hTabSearch(bptable,bp->addr) == NULL)
105     simClearBP (bp->addr);
106
107       free(bp);
108   }
109     }
110
111 }
112
113 /*-----------------------------------------------------------------*/
114 /* deleteNEXTbp - deletes all step break points                    */
115 /*-----------------------------------------------------------------*/
116 void deleteNEXTbp ()
117 {
118     breakp *bp;
119     int k;
120     char simcmd[50];
121
122     /* for break points delete if they are NEXT */
123     for ( bp = hTabFirstItem(bptable,&k); bp ;
124     bp = hTabNextItem(bptable,&k)) {
125
126   /* if this is a step then delete */
127   if (bp->bpType == NEXT) {
128       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
129
130       /* if this leaves no other break points then
131          send command to simulator to delete bp from this addr */
132       if (hTabSearch(bptable,bp->addr) == NULL) {
133     simClearBP(bp->addr);
134
135       }
136
137       free(bp);
138   }
139     }
140
141 }
142
143 /*-----------------------------------------------------------------*/
144 /* deleteUSERbp - deletes USER break point with number             */
145 /*-----------------------------------------------------------------*/
146 void deleteUSERbp (int bpnum)
147 {
148     breakp *bp;
149     int k;
150     char simcmd[50];
151
152     /* for break points delete if they are STEP */
153     for ( bp = hTabFirstItem(bptable,&k); bp ;
154     bp = hTabNextItem(bptable,&k)) {
155
156   /* if this is a user then delete if break
157      point matches or bpnumber == -1 (meaning delete
158      all user break points */
159   if (bp->bpType == USER && ( bp->bpnum == bpnum || bpnum == -1)) {
160       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
161
162       /* if this leaves no other break points then
163          send command to simulator to delete bp from this addr */
164       if (hTabSearch(bptable,bp->addr) == NULL) {
165     simClearBP (bp->addr);
166
167       }
168       fprintf(stdout,"Deleted breakpoint %d\n",
169         bp->bpnum);
170       userBpPresent --;
171       if (bpnum == -1)
172     continue ;
173       else
174     break;
175   }
176     }
177
178     if (!bp && bpnum != -1)
179   fprintf(stderr,"No breakpoint number %d.\n",bpnum);
180 }
181
182 /*-----------------------------------------------------------------*/
183 /* listUSERbp - list all user break points                         */
184 /*-----------------------------------------------------------------*/
185 void listUSERbp ()
186 {
187     breakp *bp;
188     int k;
189
190     /* if there are none then say so & return */
191     if (!userBpPresent) {
192   fprintf(stdout,"No breakpoints.\n");
193   return ;
194     }
195     fprintf(stdout,"Num Address What\n");
196     for ( bp = hTabFirstItem(bptable,&k) ; bp ;
197     bp = hTabNextItem(bptable,&k)) {
198
199   if (bp->bpType == USER ) {
200       fprintf(stdout,"%-3d 0x%04x  at %s:%d\n",
201         bp->bpnum,bp->addr,
202         bp->filename,bp->lineno);
203
204   }
205     }
206 }
207
208 /*-----------------------------------------------------------------*/
209 /* simStopBPCB - simulator stopped break point                     */
210 /*-----------------------------------------------------------------*/
211 static int simStopBPCB( unsigned int addr)
212 {
213   fprintf(stdout,"Simulator stopped at Address 0x%04x\n",addr);
214   fprintf(stdout,"%s",simResponse());
215   return 1;
216 }
217
218 /*-----------------------------------------------------------------*/
219 /* clearUSERbp - deletes USER break point at address               */
220 /*-----------------------------------------------------------------*/
221 void clearUSERbp ( unsigned int addr )
222 {
223     breakp *bp;
224     char simcmd[50];
225
226     /* for break points delete if they are STEP */
227     for ( bp = hTabFirstItemWK(bptable,addr); bp ;
228     bp = hTabNextItemWK(bptable)) {
229
230   /* if this is a step then delete */
231   if (bp->bpType == USER) {
232       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
233
234       /* if this leaves no other break points then
235          send command to simulator to delete bp from this addr */
236       if (hTabSearch(bptable,bp->addr) == NULL) {
237     simClearBP(bp->addr);
238
239       }
240       fprintf(stdout,"Deleted breakpoint %d\n",
241         bp->bpnum);
242       userBpPresent-- ;
243       break;
244   }
245     }
246
247     if (!bp)
248   fprintf(stderr,"No breakpoint at address 0x%x.\n",addr);
249 }
250
251 /*-----------------------------------------------------------------*/
252 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
253 /*-----------------------------------------------------------------*/
254 int dispatchCB (unsigned addr, context *ctxt)
255 {
256     breakp *bp;
257     int rv =0;
258
259     /* if no break points set for this address
260        then use a simulator stop break point */
261     if ((bp = hTabFirstItemWK(bptable,addr)) == NULL) {
262       return simStopBPCB(addr);
263     }
264
265     /* dispatch the call back functions */
266     for (; bp; bp = hTabNextItemWK(bptable)) {
267
268       rv += (*bp->callBack)(addr,bp->addrType,
269           bp->bpType,bp->bpnum,ctxt);
270
271     }
272
273     return rv;
274 }
275
276 /*-----------------------------------------------------------------*/
277 /* fentryCB - callback function for function entry                 */
278 /*-----------------------------------------------------------------*/
279 BP_CALLBACK(fentryCB)
280 {
281     /* add the current function into the call stack */
282     STACK_PUSH(callStack,ctxt->func);
283
284     /* will have to add code here to get the value of SP
285        which will be used to display the value of local variables
286        and parameters on the stack */
287
288     return 0;
289 }
290
291 /*-----------------------------------------------------------------*/
292 /* fexitCB - call back for function exit                           */
293 /*-----------------------------------------------------------------*/
294 BP_CALLBACK(fexitCB)
295 {
296     /* pop the top most from the call stack */
297     STACK_POP(callStack);
298     return 0;
299 }
300 /*-----------------------------------------------------------------*/
301 /* userBpCB - call back function for user break points             */
302 /*-----------------------------------------------------------------*/
303 BP_CALLBACK(userBpCB)
304 {
305     if (srcMode == SRC_CMODE) {
306   fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
307     bpnum,
308     ctxt->func->sym->name,
309     ctxt->func->mod->c_name,
310     ctxt->cline);
311   if (ctxt->func->mod && ctxt->cline > 0)
312       fprintf(stdout,"%d\t%s",ctxt->cline,
313         ctxt->func->mod->cLines[ctxt->cline]->src);
314     } else {
315   fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
316     bpnum,
317     ctxt->func->sym->name,
318     ctxt->func->mod->asm_name,
319     ctxt->asmline);
320   if (ctxt->func->mod && ctxt->asmline > 0)
321       fprintf(stdout,"%d\t%s",ctxt->asmline,
322         ctxt->func->mod->asmLines[ctxt->asmline]->src);
323     }
324
325     return 1;
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* stepBpCB - call back function for step break points             */
330 /*-----------------------------------------------------------------*/
331 BP_CALLBACK(stepBpCB)
332 {
333     static function *lfunc = NULL;
334
335     if (srcMode == SRC_CMODE) {
336   if ((lfunc && lfunc != ctxt->func) || !lfunc)
337       fprintf(stdout,"%s () at %s:%d\n",
338         ctxt->func->sym->name,
339         ctxt->func->mod->c_name,
340         ctxt->cline);
341
342   if (ctxt->func->mod && ctxt->cline > 0) {
343       fprintf(stdout,"%d\t%s",ctxt->cline ,
344         ctxt->func->mod->cLines[ctxt->cline]->src);
345   }
346     } else {
347   if ((lfunc && lfunc != ctxt->func) || !lfunc)
348       fprintf(stdout,"%s () at %s:%d\n",
349         ctxt->func->sym->name,
350         ctxt->func->mod->asm_name,
351         ctxt->asmline);
352
353   if (ctxt->func->mod && ctxt->cline > 0) {
354       fprintf(stdout,"%d\t%s",ctxt->asmline ,
355         ctxt->func->mod->asmLines[ctxt->asmline]->src);
356   }
357     }
358     lfunc = ctxt->func;
359
360     deleteSTEPbp();
361     return 1;
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* nextBpCB - call back function for next break points             */
366 /*-----------------------------------------------------------------*/
367 BP_CALLBACK(nextBpCB)
368 {
369     static function *lfunc = NULL;
370
371     if (srcMode == SRC_CMODE) {
372   if ((lfunc && lfunc != ctxt->func) || !lfunc)
373       fprintf(stdout,"%s () at %s:%d\n",
374         ctxt->func->sym->name,
375         ctxt->func->mod->c_name,
376         ctxt->cline);
377
378   if (ctxt->func->mod && ctxt->cline > 0)
379       fprintf(stdout,"%d\t%s",ctxt->cline,
380         ctxt->func->mod->cLines[ctxt->cline]->src);
381     } else {
382   if ((lfunc && lfunc != ctxt->func) || !lfunc)
383       fprintf(stdout,"%s () at %s:%d\n",
384         ctxt->func->sym->name,
385         ctxt->func->mod->asm_name,
386         ctxt->asmline);
387
388   if (ctxt->func->mod && ctxt->asmline > 0)
389       fprintf(stdout,"%d\t%s",ctxt->asmline,
390         ctxt->func->mod->asmLines[ctxt->asmline]->src);
391
392     }
393     lfunc = ctxt->func;
394
395     deleteNEXTbp();
396     return 1;
397 }