Changed a few Makefiles & Fixed 3 bugs.
[fw/sdcc] / debugger / mcs51 / symtab.c
1 /*-------------------------------------------------------------------------
2   symtab.c - Header file for symbol table for sdcdb ( debugger )
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
27 extern char *currModName ;
28 structdef *structWithName (char *);
29
30 /*------------------------------------------------------------------*/
31 /* getSize - returns size of a type chain in bits                   */
32 /*------------------------------------------------------------------*/
33 unsigned int   getSize ( link *p )
34 {
35     /* if nothing return 0 */
36     if ( ! p )
37   return 0 ;
38
39     if ( IS_SPEC(p) ) { /* if this is the specifier then */
40
41   switch (SPEC_NOUN(p)) { /* depending on the specifier type */
42   case V_INT:
43       return (IS_LONG(p) ? LONGSIZE : ( IS_SHORT(p) ? SHORTSIZE: INTSIZE)) ;
44   case V_FLOAT:
45       return FLOATSIZE ;
46   case V_CHAR:
47       return   CHARSIZE ;
48   case V_VOID:
49       return   0 ;
50   case V_STRUCT:
51       return   SPEC_STRUCT(p)->size ;
52   case V_LABEL:
53       return 0 ;
54   case V_SBIT:
55       return BITSIZE ;
56   case V_BIT:
57       return ((SPEC_BLEN(p) / 8) + (SPEC_BLEN(p) % 8 ? 1 : 0)) ;
58   default  :
59       return 0 ;
60   }
61     }
62
63     /* this is a specifier  */
64     switch (DCL_TYPE(p))  {
65     case FUNCTION:
66   return 2;
67     case ARRAY:
68   return DCL_ELEM(p) * getSize (p->next) ;
69     case IPOINTER:
70     case PPOINTER:
71     case POINTER:
72   return ( PTRSIZE ) ;
73     case FPOINTER:
74     case CPOINTER:
75   return ( FPTRSIZE );
76     case GPOINTER:
77   return ( GPTRSIZE );
78
79     default     :
80   return  0 ;
81     }
82 }
83
84
85 /*-----------------------------------------------------------------*/
86 /* parseFunc - creates a function record entry                     */
87 /*-----------------------------------------------------------------*/
88 void parseFunc (char *line)
89 {
90     function *func ;
91     char *rs;
92     int i;
93     Safe_calloc(1,func,sizeof(function));
94     func->sym = parseSymbol(line,&rs);
95     func->sym->isfunc = 1;
96     func->modName = currModName ;
97     while(*rs != ',') rs++;
98     rs++;
99     sscanf(rs,"%d,%d,%d",&i,
100      &(SPEC_INTN(func->sym->etype)),
101      &(SPEC_BANK(func->sym->etype)));
102     SPEC_INTRTN(func->sym->etype) = i;
103     addSet(&functions,func);
104 }
105
106 /*-----------------------------------------------------------------*/
107 /* parseTypeInfo - parse the type info of a symbol expects the type*/
108 /*                 info to be of the form                          */
109 /*                 ({<size>}<type info chain)                      */
110 /*-----------------------------------------------------------------*/
111 static char  *parseTypeInfo (symbol *sym, char *s)
112 {
113     char *bp;
114
115     s += 2; /* go past the ({ */
116     /* get the size */
117     sym->size = strtol (s,&bp,10);
118     /* bp now points to '}' ... go past it */
119     s = ++bp;
120     while (*s != ')') { /* till we reach the end */
121   link *type;
122   Safe_calloc(1,type,sizeof(link));
123   if (*s == ',') s++;
124
125   /* is a declarator */
126   if (*s == 'D') {
127       s++;
128       switch (*s) {
129       case 'F':
130     DCL_TYPE(type) = FUNCTION;
131     s++;
132     break;
133       case 'G':
134     DCL_TYPE(type) = GPOINTER;
135     s++;
136     break;
137       case 'C':
138     DCL_TYPE(type) = CPOINTER;
139     s++;
140     break;
141       case 'X':
142     DCL_TYPE(type) = FPOINTER;
143     s++;
144     break;
145       case 'D':
146     DCL_TYPE(type) = POINTER;
147     s++;
148     break;
149       case 'I':
150     DCL_TYPE(type) = IPOINTER;
151     s++;
152     break;
153       case 'P':
154     DCL_TYPE(type) = PPOINTER;
155     s++;
156     break;
157       case 'A':
158     s++;
159     DCL_TYPE(type) = ARRAY ;
160     DCL_ELEM(type) = strtol(s,&s,10);
161     break;
162       }
163   } else {
164       /* is a specifier */
165       type->class = SPECIFIER ;
166       s++;
167       switch (*s) {
168       case 'L':
169     SPEC_NOUN(type) = V_INT;
170     SPEC_LONG(type) = 1;
171     s++;
172     break;
173       case 'I':
174     SPEC_NOUN(type) = V_INT;
175     s++;
176     break;
177       case 'S':
178       case 'C':
179     SPEC_NOUN(type) = V_CHAR ;
180     s++;
181     break;
182       case 'V':
183     SPEC_NOUN(type) = V_VOID;
184     s++;
185     break;
186       case 'F':
187     SPEC_NOUN(type) = V_FLOAT;
188     s++;
189     break;
190       case 'T':
191     s++;
192     SPEC_NOUN(type) = V_STRUCT;
193     {
194         char *ss = strtok(strdup(s),",):");
195
196         SPEC_STRUCT(type) = structWithName(ss);
197         free(ss);
198     }
199     break;
200       case 'X':
201     s++;
202     SPEC_NOUN(type) = V_SBIT;
203     break;
204       case 'B':
205     SPEC_NOUN(type) = V_BIT;
206     s++;
207     SPEC_BSTR(type) = strtol(s,&s,10);
208     s++;
209     SPEC_BLEN(type) = strtol(s,&s,10);
210     break;
211       }
212       while (*s != ':') s++;
213       s++;
214       if (*s++ == 'S')
215     SPEC_USIGN(type) = 0;
216       else
217     SPEC_USIGN(type) = 1;
218
219   }
220
221   /* add the type to the symbol's type chain */
222   if (sym->type)
223       sym->etype = sym->etype->next = type;
224   else
225       sym->type = sym->etype = type;
226     }
227
228     return ++s;
229
230 }
231
232 /*-----------------------------------------------------------------*/
233 /* symFromRec - parse a symbol record and extract and create a sym */
234 /*              expects the input string to be of the form         */
235 /*              {G|F<filename>|L<functionName>}'$'<name>'$'<level> */
236 /*              '$'<block><type info>                              */
237 /*-----------------------------------------------------------------*/
238 symbol *parseSymbol (char *s, char **rs)
239 {
240     symbol *nsym ;
241     char *bp = s;
242
243     Safe_calloc(1,nsym,sizeof(symbol));
244
245     /* copy over the mangled name */
246     while (*bp != '(') bp++;
247      bp -= 1;
248     nsym->rname = alloccpy(s,bp - s);
249
250     /* if this is a Global Symbol */
251     nsym->scopetype = *s;
252     s++ ;
253     if (nsym->scopetype != 'G') {
254   /* get the function name it is local to */
255   bp = s;
256   while (*s != '$') s++;
257   nsym->sname = alloccpy(bp,s - bp);
258     }
259
260     /* next get the name */
261     bp = ++s;
262     while ( *s != '$' ) s++;
263     nsym->name = alloccpy(bp,s - bp);
264
265     s++;
266     /* get the level number */
267     nsym->level = strtol (s,&bp,10);
268     s = ++bp;
269     /* skip the '$' & get the block number */
270     nsym->block = strtol (s,&bp,10);
271
272     s = parseTypeInfo(nsym,bp);
273
274     /* get the address space after going past the comma */
275     s++;
276     nsym->addrspace =*s;
277
278     s+= 2;
279     nsym->isonstack = strtol(s,&s,10);
280     /* get the stack offset */
281     s++;
282     nsym->offset = strtol(s,&s,10);
283     *rs = s;
284
285     addSet(&symbols,nsym);
286
287     return nsym;
288 }
289
290
291 /*-----------------------------------------------------------------*/
292 /* parseStruct - parses a structure record expected in format      */
293 /*         {F<filename>}$<tag>[()()()...]                          */
294 /*-----------------------------------------------------------------*/
295 structdef *parseStruct (char *s)
296 {
297     structdef *nsdef ;
298     char *bp;
299     char *name;
300     symbol *fields = NULL;
301
302     while (*s != '$') s++;
303
304     bp =++s;
305     while (*s != '[') s++ ;
306     name = alloccpy(bp,s - bp);
307     nsdef = structWithName(name);
308     nsdef->fields = NULL;
309     s++;
310     while (*s && *s != ']') {
311   int offset ;
312   symbol *sym ;
313   while (!isdigit(*s)) s++;
314   offset = strtol(s,&s,10);
315   while (*s != ':') s++;
316   s++;
317   sym = parseSymbol(s,&s);
318   sym->offset = offset ;
319   s += 3;
320   if (!fields)
321       fields = nsdef->fields = sym;
322   else
323       fields = fields->next = sym;
324
325     }
326
327     return nsdef;
328 }
329
330 /*-----------------------------------------------------------------*/
331 /* parseModule - creates a module with a given name                */
332 /*-----------------------------------------------------------------*/
333 module *parseModule (char *s, bool createName )
334 {
335     module *nmod ;
336     char buffer[512];
337
338     Safe_calloc(1,nmod,sizeof(module));
339
340     addSet (&modules,nmod);
341
342
343     /* create copy file name */
344     nmod->name = s;
345
346     if (createName) {
347   sprintf(buffer,"%s.c",s);
348
349   Safe_calloc(1,nmod->c_name,strlen(buffer)+1);
350   strcpy(nmod->c_name,buffer);
351
352   sprintf(buffer,"%s.asm",s);
353   Safe_calloc(1,nmod->asm_name,strlen(buffer)+1);
354   strcpy(nmod->asm_name,buffer);
355     }
356
357     return nmod;
358 }
359
360 /*-----------------------------------------------------------------*/
361 /* moduleWithName - finds and returns a module with a given name   */
362 /*-----------------------------------------------------------------*/
363 DEFSETFUNC(moduleWithName)
364 {
365     module *mod = item;
366     V_ARG(char *,s);
367     V_ARG(module **,rmod);
368
369     if (*rmod)
370   return 0;
371
372     if (strcmp(mod->name,s) == 0) {
373   *rmod = mod ;
374   return 1;
375     }
376
377     return 0;
378 }
379
380 /*-----------------------------------------------------------------*/
381 /* moduleWithCName - finds and returns a module with a given c_name*/
382 /*-----------------------------------------------------------------*/
383 DEFSETFUNC(moduleWithCName)
384 {
385     module *mod = item;
386     V_ARG(char *,s);
387     V_ARG(module **,rmod);
388
389     if (*rmod)
390   return 0;
391     if (strcmp(mod->c_name,s) == 0) {
392   *rmod = mod;
393   return 1;
394     }
395
396     return 0;
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* moduleWithAsmName - finds & returns a module with given asm_name*/
401 /*-----------------------------------------------------------------*/
402 DEFSETFUNC(moduleWithAsmName)
403 {
404     module *mod = item;
405     V_ARG(char *,s);
406     V_ARG(module **,rmod);
407
408     if (*rmod)
409   return 0;
410     if (strcmp(mod->asm_name,s) == 0) {
411   *rmod = mod;
412   return 1;
413     }
414
415     return 0;
416 }
417
418
419 /*-----------------------------------------------------------------*/
420 /* structWithName - returns a structure with a given name          */
421 /*-----------------------------------------------------------------*/
422 structdef *structWithName (char *s)
423 {
424     int i;
425     structdef *nsdef ;
426
427     /* go thru the struct table looking for a match */
428     for ( i = 0 ; i < nStructs ; i++ ) {
429
430   if (strcmp(currModName,structs[i]->sname) == 0 &&
431       strcmp(s,structs[i]->tag) == 0)
432       return structs[i];
433     }
434
435     Safe_calloc(1,nsdef,sizeof(structdef));
436     nsdef->tag = alloccpy(s,strlen(s));
437     nsdef->sname = currModName ;
438
439     nStructs++;
440     structs = (struct structdef **)resize((void **)structs,nStructs);
441     structs[nStructs-1] = nsdef;
442     return nsdef;
443 }
444
445 /*-----------------------------------------------------------------*/
446 /* symWithRName - look for symbol with mangled name = parm         */
447 /*-----------------------------------------------------------------*/
448 DEFSETFUNC(symWithRName)
449 {
450     symbol *sym = item;
451     V_ARG(char *,s);
452     V_ARG(symbol **,rsym);
453
454     if (*rsym)
455   return 0;
456
457     if (strcmp(sym->rname,s) == 0) {
458   *rsym = sym;
459   return 1;
460     }
461
462     return 0;
463 }
464
465 /*-----------------------------------------------------------------*/
466 /* funcWithRName - look for function with name                     */
467 /*-----------------------------------------------------------------*/
468 DEFSETFUNC(funcWithRName)
469 {
470     function *func = item;
471     V_ARG(char *,s);
472     V_ARG(function **,rfunc);
473
474     if (*rfunc)
475   return 0;
476
477     if (strcmp(func->sym->rname,s) == 0) {
478   *rfunc = func;
479   return 1;
480     }
481
482     return 0;
483 }
484
485 /*-----------------------------------------------------------------*/
486 /* symLocal - local symbol respecting blocks & levels              */
487 /*-----------------------------------------------------------------*/
488 DEFSETFUNC(symLocal)
489 {
490     symbol *sym = item;
491     V_ARG(char *,name);
492     V_ARG(char *,sname);
493     V_ARG(int   ,block);
494     V_ARG(int   ,level);
495     V_ARG(symbol **,rsym);
496
497     if (strcmp(name,sym->name) == 0 && /* name matches */
498   sym->scopetype != 'G'       && /* local scope  */
499   (sym->sname && strcmp(sym->sname,sname) == 0) && /* scope == specified scope */
500   sym->block <= block         && /* block & level kindo matches */
501   sym->level <= level) {
502
503   /* if a symbol was previously found then
504      sure that ones block & level are less
505      then this one */
506   if (*rsym && (*rsym)->block >= block &&
507       (*rsym)->level >= level)
508       return 0;
509
510   *rsym = sym;
511   return 1;
512     }
513
514     return 0;
515 }
516
517 /*-----------------------------------------------------------------*/
518 /* symGlobal - return global symbol of name                        */
519 /*-----------------------------------------------------------------*/
520 DEFSETFUNC(symGlobal)
521 {
522     symbol *sym = item;
523     V_ARG(char *,name);
524     V_ARG(symbol **,rsym);
525
526     if (*rsym)
527   return 0;
528
529     /* simple :: global & name matches */
530     if (sym->scopetype == 'G' &&
531   strcmp(sym->name,name) == 0) {
532   *rsym = sym;
533   return 1;
534     }
535
536     return 0;
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* symLookup - determine symbol from name & context                */
541 /*-----------------------------------------------------------------*/
542 symbol *symLookup (char *name, context *ctxt)
543 {
544     symbol *sym = NULL ;
545
546     /* first try & find a local variable for the
547        given name */
548     if ( applyToSet(symbols,symLocal,
549         name,
550         ctxt->func->sym->name,
551         ctxt->block,
552         ctxt->level,
553         &sym))
554   return sym;
555
556     sym = NULL;
557     /* then try local to this module */
558     if (applyToSet(symbols,symLocal,
559        name,
560        ctxt->func->mod->name,
561        0,0,&sym))
562   return sym;
563     sym = NULL;
564     /* no:: try global */
565     if ( applyToSet(symbols,symGlobal,name,&sym))
566   return sym;
567
568     /* cannot find return null */
569     return NULL;
570 }
571
572 /*-----------------------------------------------------------------*/
573 /* lnkFuncEnd - link record for end of function                    */
574 /*-----------------------------------------------------------------*/
575 static void lnkFuncEnd (char *s)
576 {
577     char sname[128], *bp = sname;
578     function *func;
579
580     /* copy till we get to a ':' */
581     while ( *s != ':' )
582   *bp++ = *s++;
583     bp -= 1;
584     *bp = '\0';
585
586     func = NULL;
587     if (!applyToSet(functions,funcWithRName,sname,&func))
588   return ;
589
590     s++;
591     sscanf(s,"%x",&func->sym->eaddr);
592 #ifdef SDCDB_DEBUG
593     printf("%s(eaddr%x)\n",func->sym->name,func->sym->eaddr);
594 #endif
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* lnkSymRec - record for a symbol                                 */
599 /*-----------------------------------------------------------------*/
600 static void lnkSymRec (char *s)
601 {
602     char sname[128], *bp = sname;
603     symbol *sym;
604
605     /* copy till we get to a ':' */
606     while ( *s != ':')
607   *bp++ = *s++;
608     bp -= 1;
609     *bp = '\0';
610
611
612     sym = NULL;
613     if (!applyToSet(symbols,symWithRName,sname,&sym))
614   return ;
615
616     s++;
617     sscanf(s,"%x",&sym->addr);
618 #ifdef SDCDB_DEBUG
619     printf("%s(%x)\n",sym->name,sym->addr);
620 #endif
621 }
622
623 /*-----------------------------------------------------------------*/
624 /* lnkAsmSrc - process linker record for asm sources               */
625 /*-----------------------------------------------------------------*/
626 static void lnkAsmSrc (char *s)
627 {
628     char mname[128], *bp = mname;
629     int line ;
630     unsigned addr;
631     module *mod = NULL;
632
633     /* input will be of format
634        filename$<line>:<address> */
635     while (*s != '$' && *s != '.')
636   *bp++ = *s++;
637     *bp = '\0';
638     /* skip to line stuff */
639     while (*s != '$') s++;
640
641     if (!applyToSet(modules,moduleWithName,mname,&mod))
642   return ;
643
644     if (sscanf(s,"$%d:%x",&line,&addr) != 2)
645   return ;
646
647     line--;
648     if (line < mod->nasmLines) {
649   mod->asmLines[line]->addr = addr;
650 #ifdef SDCDB_DEBUG
651   printf("%s(%d:%x) %s",mod->asm_name,line,addr,mod->asmLines[line]->src);
652 #endif
653     }
654 }
655
656 /*-----------------------------------------------------------------*/
657 /* lnkCSrc - process linker output for c source                    */
658 /*-----------------------------------------------------------------*/
659 static void lnkCSrc (char *s)
660 {
661     char mname[128], *bp = mname;
662     int block,level,line;
663     unsigned int addr;
664     module *mod ;
665
666     /* input will be of format
667        filename.ext$<level>$<block>$<line>:<address> */
668     /* get the module name */
669     while (*s != '$' )
670   *bp++ = *s++;
671     *bp = '\0';
672     /* skip the extension */
673     while (*s != '$') s++;
674
675     if (sscanf(s,"$%d$%d$%d:%x",
676          &line,&level,&block,&addr) != 4)
677   return ;
678
679     mod = NULL;
680     if (!applyToSet(modules,moduleWithCName,mname,&mod)) {
681   mod = parseModule(mname,FALSE);
682   mod->c_name = alloccpy(mname,strlen(mname));
683   mod->cfullname=searchDirsFname(mod->c_name);
684   mod->cLines = loadFile(mod->c_name,&mod->ncLines);
685     }
686
687     line--;
688     if (line < mod->ncLines && line > 0) {
689   mod->cLines[line]->addr = addr;
690   mod->cLines[line]->block = block;
691   mod->cLines[line]->level = level;
692 #ifdef SDCDB_DEBUG
693   printf("%s(%d:%x) %s",mod->c_name,
694          line+1,addr,mod->cLines[line]->src);
695 #endif
696     }
697     return;
698
699 }
700
701 /*-----------------------------------------------------------------*/
702 /* parseLnkRec - parses a linker generated record                  */
703 /*-----------------------------------------------------------------*/
704 void parseLnkRec (char *s)
705 {
706     /* link records can be several types
707        dpeneding on the type do */
708
709     switch (*s) {
710
711   /* c source line address */
712     case 'C':
713   lnkCSrc(s+2);
714   break;
715   /* assembler source address */
716     case 'A':
717   lnkAsmSrc(s+2);
718   break;
719
720     case 'X':
721   lnkFuncEnd(s+1);
722   break;
723
724     default :
725   lnkSymRec(s);
726   break;
727     }
728 }