* debugger/mcs51/break.c, debugger/mcs51/cmd.c,
[fw/sdcc] / debugger / mcs51 / symtab.c
index c79906c27cdbb3071b55ef92f458b4862108a36a..5473d60e31c079d2bdf91fa2c52428f818d67cbf 100644 (file)
@@ -1,31 +1,32 @@
 /*-------------------------------------------------------------------------
   symtab.c - Header file for symbol table for sdcdb ( debugger )
-             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
+        Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   
+
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
 #include "sdcdb.h"
 #include "symtab.h"
+#include "newalloc.h"
 
-extern char *currModName ;
 structdef *structWithName (char *);
+DEFSETFUNC(symWithRName);
 
 /*------------------------------------------------------------------*/
 /* getSize - returns size of a type chain in bits                   */
@@ -34,50 +35,50 @@ unsigned int   getSize ( link *p )
 {
     /* if nothing return 0 */
     if ( ! p )
-       return 0 ;
-    
+        return 0 ;
+
     if ( IS_SPEC(p) ) { /* if this is the specifier then */
-       
-       switch (SPEC_NOUN(p)) { /* depending on the specifier type */
-       case V_INT:
-           return (IS_LONG(p) ? LONGSIZE : ( IS_SHORT(p) ? SHORTSIZE: INTSIZE)) ;
-       case V_FLOAT:
-           return FLOATSIZE ;
-       case V_CHAR:
-           return   CHARSIZE ;
-       case V_VOID:
-           return   0 ;
-       case V_STRUCT:
-           return   SPEC_STRUCT(p)->size ;
-       case V_LABEL:
-           return 0 ;
-       case V_SBIT:
-           return BITSIZE ;
-       case V_BIT:
-           return ((SPEC_BLEN(p) / 8) + (SPEC_BLEN(p) % 8 ? 1 : 0)) ;
-       default  :
-           return 0 ;
-       }
+
+        switch (SPEC_NOUN(p)) { /* depending on the specifier type */
+        case V_INT:
+            return (IS_LONG(p) ? LONGSIZE : ( IS_SHORT(p) ? SHORTSIZE: INTSIZE)) ;
+        case V_FLOAT:
+            return FLOATSIZE ;
+        case V_CHAR:
+            return   CHARSIZE ;
+        case V_VOID:
+            return   0 ;
+        case V_STRUCT:
+            return   SPEC_STRUCT(p)->size ;
+        case V_LABEL:
+            return 0 ;
+        case V_SBIT:
+            return BITSIZE ;
+        case V_BIT:
+            return ((SPEC_BLEN(p) / 8) + (SPEC_BLEN(p) % 8 ? 1 : 0)) ;
+        default  :
+            return 0 ;
+        }
     }
-    
+
     /* this is a specifier  */
     switch (DCL_TYPE(p))  {
     case FUNCTION:
-       return 2;
+        return 2;
     case ARRAY:
-       return DCL_ELEM(p) * getSize (p->next) ;
+        return DCL_ELEM(p) * getSize (p->next) ;
     case IPOINTER:
     case PPOINTER:
     case POINTER:
-       return ( PTRSIZE ) ;
+        return ( PTRSIZE ) ;
     case FPOINTER:
     case CPOINTER:
-       return ( FPTRSIZE );
+        return ( FPTRSIZE );
     case GPOINTER:
-       return ( GPTRSIZE );
-       
+        return ( GPTRSIZE );
+
     default     :
-       return  0 ;
+        return  0 ;
     }
 }
 
@@ -88,17 +89,25 @@ unsigned int   getSize ( link *p )
 void parseFunc (char *line)
 {
     function *func ;
-    char *rs;
+    char *rs = line ;
     int i;
-    Safe_calloc(func,sizeof(function));
-    func->sym = parseSymbol(line,&rs);
+
+    while (*rs && *rs != '(') rs++ ;
+    *--rs = '\0';
+
+    func = Safe_calloc(1,sizeof(function));
+    func->sym = NULL;
+    applyToSetFTrue(symbols,symWithRName,line,&func->sym);
+    *rs++ = '0';
+    if (! func->sym)
+        func->sym = parseSymbol(line,&rs,1);
     func->sym->isfunc = 1;
-    func->modName = currModName ;   
-    while(*rs != ',') rs++;
+    func->modName = currModName ;
+    while(*rs && *rs != ',') rs++;
     rs++;
-    sscanf(rs,"%d,%d,%d",&i,
-          &(SPEC_INTN(func->sym->etype)),
-          &(SPEC_BANK(func->sym->etype)));
+    sscanf(rs,"%d,%d,%hd",&i,
+        &(SPEC_INTN(func->sym->etype)),
+        &(SPEC_BANK(func->sym->etype)));
     SPEC_INTRTN(func->sym->etype) = i;
     addSet(&functions,func);
 }
@@ -106,7 +115,7 @@ void parseFunc (char *line)
 /*-----------------------------------------------------------------*/
 /* parseTypeInfo - parse the type info of a symbol expects the type*/
 /*                 info to be of the form                          */
-/*                 ({<size>}<type info chain)                      */  
+/*                 ({<size>}<type info chain)                      */
 /*-----------------------------------------------------------------*/
 static char  *parseTypeInfo (symbol *sym, char *s)
 {
@@ -116,115 +125,115 @@ static char  *parseTypeInfo (symbol *sym, char *s)
     /* get the size */
     sym->size = strtol (s,&bp,10);
     /* bp now points to '}' ... go past it */
-    s = ++bp;    
+    s = ++bp;
     while (*s != ')') { /* till we reach the end */
-       link *type;
-       Safe_calloc(type,sizeof(link));
-       if (*s == ',') s++;
-
-       /* is a declarator */
-       if (*s == 'D') {
-           s++;
-           switch (*s) {
-           case 'F':           
-               DCL_TYPE(type) = FUNCTION;
-               s++;
-               break;
-           case 'G':           
-               DCL_TYPE(type) = GPOINTER;
-               s++;
-               break;
-           case 'C':
-               DCL_TYPE(type) = CPOINTER;
-               s++;
-               break;
-           case 'X':
-               DCL_TYPE(type) = FPOINTER;
-               s++;
-               break;
-           case 'D':
-               DCL_TYPE(type) = POINTER;
-               s++;
-               break;
-           case 'I':
-               DCL_TYPE(type) = IPOINTER;
-               s++;
-               break;
-           case 'P':
-               DCL_TYPE(type) = PPOINTER;
-               s++;
-               break;
-           case 'A':
-               s++;
-               DCL_TYPE(type) = ARRAY ;
-               DCL_ELEM(type) = strtol(s,&s,10);
-               break;
-           }
-       } else {            
-           /* is a specifier */
-           type->class = SPECIFIER ;
-           s++;
-           switch (*s) {
-           case 'L':
-               SPEC_NOUN(type) = V_INT;
-               SPEC_LONG(type) = 1;
-               s++;
-               break;
-           case 'I':
-               SPEC_NOUN(type) = V_INT;
-               s++;
-               break;
-           case 'S':
-           case 'C':
-               SPEC_NOUN(type) = V_CHAR ;
-               s++;
-               break;
-           case 'V':
-               SPEC_NOUN(type) = V_VOID;
-               s++;
-               break;
-           case 'F':
-               SPEC_NOUN(type) = V_FLOAT;
-               s++;
-               break;
-           case 'T':
-               s++;
-               SPEC_NOUN(type) = V_STRUCT;
-               { 
-                   char *ss = strtok(strdup(s),",):");
-                   
-                   SPEC_STRUCT(type) = structWithName(ss);
-                   free(ss);
-               }
-               break;
-           case 'X':
-               s++;
-               SPEC_NOUN(type) = V_SBIT;
-               break;
-           case 'B':
-               SPEC_NOUN(type) = V_BIT;
-               s++;
-               SPEC_BSTR(type) = strtol(s,&s,10);
-               s++;
-               SPEC_BLEN(type) = strtol(s,&s,10);
-               break;
-           }
-           while (*s != ':') s++;
-           s++;
-           if (*s++ == 'S')
-               SPEC_USIGN(type) = 0;
-           else
-               SPEC_USIGN(type) = 1;
-
-       }
-
-       /* add the type to the symbol's type chain */
-       if (sym->type) 
-           sym->etype = sym->etype->next = type;
-       else
-           sym->type = sym->etype = type;
+        link *type;
+        type = Safe_calloc(1,sizeof(link));
+        if (*s == ',') s++;
+
+        /* is a declarator */
+        if (*s == 'D') {
+            s++;
+            switch (*s) {
+            case 'F':
+                DCL_TYPE(type) = FUNCTION;
+                s++;
+                break;
+            case 'G':
+                DCL_TYPE(type) = GPOINTER;
+                s++;
+                break;
+            case 'C':
+                DCL_TYPE(type) = CPOINTER;
+                s++;
+                break;
+            case 'X':
+                DCL_TYPE(type) = FPOINTER;
+                s++;
+                break;
+            case 'D':
+                DCL_TYPE(type) = POINTER;
+                s++;
+                break;
+            case 'I':
+                DCL_TYPE(type) = IPOINTER;
+                s++;
+                break;
+            case 'P':
+                DCL_TYPE(type) = PPOINTER;
+                s++;
+                break;
+            case 'A':
+                s++;
+                DCL_TYPE(type) = ARRAY ;
+                DCL_ELEM(type) = strtol(s,&s,10);
+                break;
+            }
+        } else {
+            /* is a specifier */
+            type->class = SPECIFIER ;
+            s++;
+            switch (*s) {
+            case 'L':
+                SPEC_NOUN(type) = V_INT;
+                SPEC_LONG(type) = 1;
+                s++;
+                break;
+            case 'I':
+                SPEC_NOUN(type) = V_INT;
+                s++;
+                break;
+            case 'S':
+            case 'C':
+                SPEC_NOUN(type) = V_CHAR ;
+                s++;
+                break;
+            case 'V':
+                SPEC_NOUN(type) = V_VOID;
+                s++;
+                break;
+            case 'F':
+                SPEC_NOUN(type) = V_FLOAT;
+                s++;
+                break;
+            case 'T':
+                s++;
+                SPEC_NOUN(type) = V_STRUCT;
+                {
+                    char *ss = strtok(strdup(s),",):");
+
+                    SPEC_STRUCT(type) = structWithName(ss);
+                    free(ss);
+                }
+                break;
+            case 'X':
+                s++;
+                SPEC_NOUN(type) = V_SBIT;
+                break;
+            case 'B':
+                SPEC_NOUN(type) = V_BIT;
+                s++;
+                SPEC_BSTR(type) = strtol(s,&s,10);
+                s++;
+                SPEC_BLEN(type) = strtol(s,&s,10);
+                break;
+            }
+            while (*s != ':') s++;
+            s++;
+            if (*s++ == 'S')
+                SPEC_USIGN(type) = 0;
+            else
+                SPEC_USIGN(type) = 1;
+
+        }
+
+        /* add the type to the symbol's type chain */
+        if (sym->type)
+            sym->etype = sym->etype->next = type;
+        else
+            sym->type = sym->etype = type;
     }
-    
+
     return ++s;
 
 }
@@ -235,55 +244,84 @@ static char  *parseTypeInfo (symbol *sym, char *s)
 /*              {G|F<filename>|L<functionName>}'$'<name>'$'<level> */
 /*              '$'<block><type info>                              */
 /*-----------------------------------------------------------------*/
-symbol *parseSymbol (char *s, char **rs)
+symbol *parseSymbol (char *s, char **rs, int doadd)
 {
     symbol *nsym ;
+    char save_ch;
     char *bp = s;
 
-    Safe_calloc(nsym,sizeof(symbol));
-
-    /* copy over the mangled name */
-    while (*bp != '(') bp++;   
-     bp -= 1;
-    nsym->rname = alloccpy(s,bp - s);
-
+    /* go the mangled name */
+    for ( bp = s; *bp && *bp != '('; bp++ );
+    save_ch = *--bp;
+    *bp = '\0';
+    nsym = NULL;
+    if ( doadd == 2 )
+    {
+        /* add only if not present and if linkrecord before symbol record*/
+        if ( applyToSetFTrue(symbols,symWithRName,s,&nsym))
+        {
+            if ( nsym->rname != nsym->name )
+                return NULL;
+            doadd = 0;
+        }
+    }
+    if ( ! nsym )
+    {
+        nsym = Safe_calloc(1,sizeof(symbol));
+        nsym->rname = alloccpy(s,bp - s);
+    }
+    *bp = save_ch;
     /* if this is a Global Symbol */
     nsym->scopetype = *s;
     s++ ;
     if (nsym->scopetype != 'G') {
-       /* get the function name it is local to */
-       bp = s;
-       while (*s != '$') s++;
-       nsym->sname = alloccpy(bp,s - bp);
+        /* get the function name it is local to */
+        bp = s;
+        while (*s != '$') s++;
+        nsym->sname = alloccpy(bp,s - bp);
     }
 
-    /* next get the name */    
+    /* next get the name */
     bp = ++s;
     while ( *s != '$' ) s++;
     nsym->name = alloccpy(bp,s - bp);
-    
+
     s++;
     /* get the level number */
     nsym->level = strtol (s,&bp,10);
     s = ++bp;
     /* skip the '$' & get the block number */
     nsym->block = strtol (s,&bp,10);
-    
-    s = parseTypeInfo(nsym,bp);        
+
+    s = parseTypeInfo(nsym,bp);
 
     /* get the address space after going past the comma */
     s++;
     nsym->addrspace =*s;
 
-    s+= 2;    
+    s+= 2;
     nsym->isonstack = strtol(s,&s,10);
     /* get the stack offset */
     s++;
     nsym->offset = strtol(s,&s,10);
+
+    if ( nsym->addrspace == 'R' )
+    {
+        /* get registeroffset */
+        while (*s && *s != '[') s++ ;
+        s++ ;
+        if ( *s == 'r' )
+        {
+            nsym->addr = strtol(s+1,&s,10);
+        }
+        while (*s && *s != ']') s++ ;
+    }
+
     *rs = s;
-   
-    addSet(&symbols,nsym);
-    
+    if ( doadd ) addSet(&symbols,nsym);
+
+    Dprintf(D_symtab, ("symtab: par %s(0x%x) add=%d sym=%p\n",nsym->name,nsym->addr,doadd,nsym));
+
     return nsym;
 }
 
@@ -297,33 +335,34 @@ structdef *parseStruct (char *s)
     structdef *nsdef ;
     char *bp;
     char *name;
-    symbol *fields = NULL;    
-    
+    symbol *fields = NULL;
+
     while (*s != '$') s++;
-   
+
     bp =++s;
     while (*s != '[') s++ ;
     name = alloccpy(bp,s - bp);
     nsdef = structWithName(name);
     nsdef->fields = NULL;
+    nsdef->size = 0;
     s++;
     while (*s && *s != ']') {
-       int offset ;
-       symbol *sym ;
-       while (!isdigit(*s)) s++;
-       offset = strtol(s,&s,10);
-       while (*s != ':') s++;
-       s++;
-       sym = parseSymbol(s,&s);
-       sym->offset = offset ;
-       s += 3;
-       if (!fields) 
-           fields = nsdef->fields = sym;
-       else
-           fields = fields->next = sym;
-       
+        int offset ;
+        symbol *sym ;
+        while (!isdigit(*s)) s++;
+        offset = strtol(s,&s,10);
+        while (*s != ':') s++;
+        s++;
+        sym = parseSymbol(s,&s,0);
+        sym->offset = offset ;
+        s += 3;
+        if (!fields)
+            fields = nsdef->fields = sym;
+        else
+            fields = fields->next = sym;
+        nsdef->size += sym->size;
     }
-    
+
     return nsdef;
 }
 
@@ -335,25 +374,25 @@ module *parseModule (char *s, bool createName )
     module *nmod ;
     char buffer[512];
 
-    Safe_calloc(nmod,sizeof(module));    
-    
+    nmod = Safe_calloc(1,sizeof(module));
+
     addSet (&modules,nmod);
-    
-           
+
+
     /* create copy file name */
     nmod->name = s;
-    
+
     if (createName) {
-       sprintf(buffer,"%s.c",s);
-       
-       Safe_calloc(nmod->c_name,strlen(buffer)+1);
-       strcpy(nmod->c_name,buffer);       
-       
-       sprintf(buffer,"%s.asm",s);
-       Safe_calloc(nmod->asm_name,strlen(buffer)+1);
-       strcpy(nmod->asm_name,buffer);              
+        sprintf(buffer,"%s.c",s);
+
+        nmod->c_name = Safe_malloc(strlen(buffer)+1);
+        strcpy(nmod->c_name,buffer);
+
+        sprintf(buffer,"%s.asm",s);
+        nmod->asm_name = Safe_malloc(strlen(buffer)+1);
+        strcpy(nmod->asm_name,buffer);
     }
-    
+
     return nmod;
 }
 
@@ -365,15 +404,15 @@ DEFSETFUNC(moduleWithName)
     module *mod = item;
     V_ARG(char *,s);
     V_ARG(module **,rmod);
-    
+
     if (*rmod)
-       return 0;
+        return 0;
 
     if (strcmp(mod->name,s) == 0) {
-       *rmod = mod ;
-       return 1;
+        *rmod = mod ;
+        return 1;
     }
-    
+
     return 0;
 }
 
@@ -385,14 +424,14 @@ DEFSETFUNC(moduleWithCName)
     module *mod = item;
     V_ARG(char *,s);
     V_ARG(module **,rmod);
-       
+
     if (*rmod)
-       return 0;
+        return 0;
     if (strcmp(mod->c_name,s) == 0) {
-       *rmod = mod;
-       return 1;
+        *rmod = mod;
+        return 1;
     }
-    
+
     return 0;
 }
 
@@ -404,14 +443,14 @@ DEFSETFUNC(moduleWithAsmName)
     module *mod = item;
     V_ARG(char *,s);
     V_ARG(module **,rmod);
-       
+
     if (*rmod)
-       return 0;
+        return 0;
     if (strcmp(mod->asm_name,s) == 0) {
-       *rmod = mod;
-       return 1;
+        *rmod = mod;
+        return 1;
     }
-    
+
     return 0;
 }
 
@@ -427,15 +466,15 @@ structdef *structWithName (char *s)
     /* go thru the struct table looking for a match */
     for ( i = 0 ; i < nStructs ; i++ ) {
 
-       if (strcmp(currModName,structs[i]->sname) == 0 &&
-           strcmp(s,structs[i]->tag) == 0)
-           return structs[i];
+        if (strcmp(currModName,structs[i]->sname) == 0 &&
+            strcmp(s,structs[i]->tag) == 0)
+            return structs[i];
     }
 
-    Safe_calloc(nsdef,sizeof(structdef));
+    nsdef = Safe_calloc(1,sizeof(structdef));
     nsdef->tag = alloccpy(s,strlen(s));
     nsdef->sname = currModName ;
-    
+
     nStructs++;
     structs = (struct structdef **)resize((void **)structs,nStructs);
     structs[nStructs-1] = nsdef;
@@ -452,12 +491,12 @@ DEFSETFUNC(symWithRName)
     V_ARG(symbol **,rsym);
 
     if (*rsym)
-       return 0;
+        return 0;
 
     if (strcmp(sym->rname,s) == 0) {
-       *rsym = sym;
-       return 1;
-    }    
+        *rsym = sym;
+        return 1;
+    }
 
     return 0;
 }
@@ -472,13 +511,13 @@ DEFSETFUNC(funcWithRName)
     V_ARG(function **,rfunc);
 
     if (*rfunc)
-       return 0;
-    
+        return 0;
+
     if (strcmp(func->sym->rname,s) == 0) {
-       *rfunc = func;
-       return 1;
-    }    
-    
+        *rfunc = func;
+        return 1;
+    }
+
     return 0;
 }
 
@@ -495,20 +534,20 @@ DEFSETFUNC(symLocal)
     V_ARG(symbol **,rsym);
 
     if (strcmp(name,sym->name) == 0 && /* name matches */
-       sym->scopetype != 'G'       && /* local scope  */
-       (sym->sname && strcmp(sym->sname,sname) == 0) && /* scope == specified scope */
-       sym->block <= block         && /* block & level kindo matches */
-       sym->level <= level) {
-       
-       /* if a symbol was previously found then
-          sure that ones block & level are less
-          then this one */
-       if (*rsym && (*rsym)->block >= block && 
-           (*rsym)->level >= level)
-           return 0;
-
-       *rsym = sym;
-       return 1;       
+        sym->scopetype != 'G'       && /* local scope  */
+        (sym->sname && strcmp(sym->sname,sname) == 0) && /* scope == specified scope */
+        sym->block <= block         && /* block & level kindo matches */
+        sym->level <= level) {
+
+        /* if a symbol was previously found then
+           sure that ones block & level are less
+           then this one */
+        if (*rsym && (*rsym)->block >= block &&
+            (*rsym)->level >= level)
+            return 0;
+
+        *rsym = sym;
+        return 1;
     }
 
     return 0;
@@ -524,13 +563,13 @@ DEFSETFUNC(symGlobal)
     V_ARG(symbol **,rsym);
 
     if (*rsym)
-       return 0;
+        return 0;
 
     /* simple :: global & name matches */
     if (sym->scopetype == 'G' &&
-       strcmp(sym->name,name) == 0) {
-       *rsym = sym;
-       return 1;
+        strcmp(sym->name,name) == 0) {
+        *rsym = sym;
+        return 1;
     }
 
     return 0;
@@ -543,27 +582,33 @@ symbol *symLookup (char *name, context *ctxt)
 {
     symbol *sym = NULL ;
 
-    /* first try & find a local variable for the
-       given name */
-    if ( applyToSet(symbols,symLocal,
-                   name, 
-                   ctxt->func->sym->name,
-                   ctxt->block,
-                   ctxt->level,
-                   &sym))
-       return sym;
-    
-    sym = NULL;
-    /* then try local to this module */
-    if (applyToSet(symbols,symLocal,
-                  name,
-                  ctxt->func->mod->name,
-                  0,0,&sym))
-       return sym;
-    sym = NULL;
+    if ((ctxt) && (ctxt->func) &&
+        (ctxt->func->sym) && (ctxt->func->sym->name)) {
+        /* first try & find a local variable for the given name */
+        if ( applyToSet(symbols,symLocal,
+            name,
+            ctxt->func->sym->name,
+            ctxt->block,
+            ctxt->level,
+            &sym))
+            return sym;
+        sym = NULL;
+    }
+
+    if ((ctxt) && (ctxt->func) &&
+        (ctxt->func->mod) && (ctxt->func->mod->name)) {
+      /* then try local to this module */
+      if (applyToSet(symbols,symLocal,
+          name,
+          ctxt->func->mod->name,
+          0,0,&sym))
+          return sym;
+      sym = NULL;
+    }
+
     /* no:: try global */
     if ( applyToSet(symbols,symGlobal,name,&sym))
-       return sym;
+        return sym;
 
     /* cannot find return null */
     return NULL;
@@ -579,19 +624,18 @@ static void lnkFuncEnd (char *s)
 
     /* copy till we get to a ':' */
     while ( *s != ':' )
-       *bp++ = *s++;
+        *bp++ = *s++;
     bp -= 1;
-    *bp = '\0';        
+    *bp = '\0';
 
     func = NULL;
     if (!applyToSet(functions,funcWithRName,sname,&func))
-       return ;
-    
+        return ;
+
     s++;
     sscanf(s,"%x",&func->sym->eaddr);
-#ifdef SDCDB_DEBUG    
-    printf("%s(eaddr%x)\n",func->sym->name,func->sym->eaddr);
-#endif
+
+    Dprintf(D_symtab, ("symtab: ead %s(0x%x)\n",func->sym->name,func->sym->eaddr));
 }
 
 /*-----------------------------------------------------------------*/
@@ -599,25 +643,31 @@ static void lnkFuncEnd (char *s)
 /*-----------------------------------------------------------------*/
 static void lnkSymRec (char *s)
 {
-    char sname[128], *bp = sname;
+    char *bp, save_ch ;
     symbol *sym;
 
-    /* copy till we get to a ':' */
-    while ( *s != ':')
-       *bp++ = *s++;
-    bp -= 1;
+    /* search  to a ':' */
+    for ( bp = s; *bp && *bp != ':'; bp++ );
+    save_ch = *--bp;
     *bp = '\0';
-        
+
 
     sym = NULL;
-    if (!applyToSet(symbols,symWithRName,sname,&sym))
-       return ;
-    
-    s++;
-    sscanf(s,"%x",&sym->addr);
-#ifdef SDCDB_DEBUG
-    printf("%s(%x)\n",sym->name,sym->addr);
-#endif
+    applyToSetFTrue(symbols,symWithRName,s,&sym);
+    if (! sym)
+    {
+        sym = Safe_calloc(1,sizeof(symbol));
+        sym->rname = alloccpy(s,bp - s);
+        sym->scopetype = *s;
+        sym->name  = sym->rname;
+        addSet(&symbols,sym);
+    }
+    *bp = save_ch;
+    if ( *bp )
+    {
+        sscanf(bp+2,"%x",&sym->addr);
+    }
+    Dprintf(D_symtab, ("symtab: lnk %s(0x%x)\n",sym->name,sym->addr));
 }
 
 /*-----------------------------------------------------------------*/
@@ -630,26 +680,24 @@ static void lnkAsmSrc (char *s)
     unsigned addr;
     module *mod = NULL;
 
-    /* input will be of format 
+    /* input will be of format
        filename$<line>:<address> */
     while (*s != '$' && *s != '.')
-       *bp++ = *s++;
+        *bp++ = *s++;
     *bp = '\0';
     /* skip to line stuff */
     while (*s != '$') s++;
-    
+
     if (!applyToSet(modules,moduleWithName,mname,&mod))
-       return ;    
+        return ;
 
     if (sscanf(s,"$%d:%x",&line,&addr) != 2)
-       return ;
+        return ;
 
     line--;
     if (line < mod->nasmLines) {
-       mod->asmLines[line]->addr = addr;
-#ifdef SDCDB_DEBUG
-       printf("%s(%d:%x) %s",mod->asm_name,line,addr,mod->asmLines[line]->src);
-#endif
+        mod->asmLines[line]->addr = addr;
+        Dprintf(D_symtab, ("symtab: asm %s(%d:0x%x) %s",mod->asm_name,line,addr,mod->asmLines[line]->src));
     }
 }
 
@@ -662,39 +710,54 @@ static void lnkCSrc (char *s)
     int block,level,line;
     unsigned int addr;
     module *mod ;
-    
-    /* input will be of format 
-       filename.ext$<level>$<block>$<line>:<address> */
+
+    /* input will be of format
+       filename.ext$<line>$<level>$<block>:<address> */
     /* get the module name */
     while (*s != '$' )
-       *bp++ = *s++;
+        *bp++ = *s++;
     *bp = '\0';
     /* skip the extension */
     while (*s != '$') s++;
 
     if (sscanf(s,"$%d$%d$%d:%x",
-              &line,&level,&block,&addr) != 4)
-       return ;
+        &line,&level,&block,&addr) != 4)
+        return ;
 
     mod = NULL;
-    if (!applyToSet(modules,moduleWithCName,mname,&mod)) { 
-       mod = parseModule(mname,FALSE);
-       mod->c_name = alloccpy(mname,strlen(mname));
-       mod->cfullname=searchDirsFname(mod->c_name);
-       mod->cLines = loadFile(mod->c_name,&mod->ncLines);
-    }      
-    
+    if (!applyToSet(modules,moduleWithCName,mname,&mod)) {
+        mod = parseModule(mname, FALSE);
+        mod->c_name = alloccpy(mname,strlen(mname));
+        mod->cfullname=searchDirsFname(mod->c_name);
+        mod->cLines = loadFile(mod->c_name,&mod->ncLines);
+    }
+
     line--;
-    if (line < mod->ncLines && line > 0) {
-       mod->cLines[line]->addr = addr;
-       mod->cLines[line]->block = block;
-       mod->cLines[line]->level = level;
-#ifdef SDCDB_DEBUG
-       printf("%s(%d:%x) %s",mod->c_name,
-              line+1,addr,mod->cLines[line]->src);
-#endif
+    /* one line can have more than one address : (for loops !)*/
+    if (line < mod->ncLines && line > 0 /*&&
+        ( !mod->cLines[line]->addr ||
+        mod->cLines[line]->level > level )*/ )
+    {
+        if ( mod->cLines[line]->addr != INT_MAX )
+        {
+            /* save double line information for exepoints */
+            exePoint *ep ;
+            ep = Safe_calloc(1,sizeof(exePoint));
+            ep->addr =  mod->cLines[line]->addr ;
+            ep->line = line;
+            ep->block= mod->cLines[line]->block;
+            ep->level= mod->cLines[line]->level;
+            addSet(&mod->cfpoints,ep);
+            Dprintf(D_symtab, ("symtab: exe %s(%d:0x%x) %s",mod->c_name,
+                           line+1,addr,mod->cLines[line]->src));
+        }
+        mod->cLines[line]->addr = addr;
+        mod->cLines[line]->block = block;
+        mod->cLines[line]->level = level;
+        Dprintf(D_symtab, ("symtab: ccc %s(%d:0x%x) %s",mod->c_name,
+                           line+1,addr,mod->cLines[line]->src));
     }
-    return;    
+    return;
 
 }
 
@@ -703,26 +766,26 @@ static void lnkCSrc (char *s)
 /*-----------------------------------------------------------------*/
 void parseLnkRec (char *s)
 {
-    /* link records can be several types 
+    /* link records can be several types
        dpeneding on the type do */
-    
+
     switch (*s) {
-       
-       /* c source line address */
-    case 'C': 
-       lnkCSrc(s+2);
-       break;
-       /* assembler source address */
+
+  /* c source line address */
+    case 'C':
+        lnkCSrc(s+2);
+        break;
+  /* assembler source address */
     case 'A':
-       lnkAsmSrc(s+2);
-       break;
-       
-    case 'X': 
-       lnkFuncEnd(s+1);
-       break; 
-       
+        lnkAsmSrc(s+2);
+        break;
+
+    case 'X':
+        lnkFuncEnd(s+1);
+        break;
+
     default :
-       lnkSymRec(s);
-       break;
+        lnkSymRec(s);
+        break;
     }
 }