summaryrefslogtreecommitdiff
path: root/debugger/mcs51/symtab.c
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /debugger/mcs51/symtab.c
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'debugger/mcs51/symtab.c')
-rw-r--r--debugger/mcs51/symtab.c842
1 files changed, 842 insertions, 0 deletions
diff --git a/debugger/mcs51/symtab.c b/debugger/mcs51/symtab.c
new file mode 100644
index 0000000..fd4e586
--- /dev/null
+++ b/debugger/mcs51/symtab.c
@@ -0,0 +1,842 @@
+/*-------------------------------------------------------------------------
+ symtab.c - Header file for symbol table for sdcdb ( debugger )
+ 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!
+-------------------------------------------------------------------------*/
+
+#include "sdcdb.h"
+#include "symtab.h"
+#include "newalloc.h"
+
+structdef *structWithName (char *);
+DEFSETFUNC(symWithRName);
+
+/*-----------------------------------------------------------------*/
+/* gc_strcat - allocate and return concatenated strings */
+/*-----------------------------------------------------------------*/
+char *gc_strcat(const char *s1, const char *s2, const char *s3)
+{
+ char *p = Safe_malloc(strlen(s1) + strlen(s2) + strlen(s3) + 1);
+ strcat(strcat(strcpy(p, s1), s2), s3);
+ return p;
+}
+
+/*------------------------------------------------------------------*/
+/* getSize - returns size of a type chain in bits */
+/*------------------------------------------------------------------*/
+unsigned int getSize ( st_link *p )
+{
+ /* if nothing return 0 */
+ if ( ! p )
+ 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;
+ }
+ }
+
+ /* this is a specifier */
+ switch (DCL_TYPE(p))
+ {
+ case FUNCTION:
+ return 2;
+ case ARRAY:
+ return DCL_ELEM(p) * getSize (p->next);
+ case IPOINTER:
+ case PPOINTER:
+ case POINTER:
+ return ( PTRSIZE );
+ case FPOINTER:
+ case CPOINTER:
+ return ( FPTRSIZE );
+ case GPOINTER:
+ return ( GPTRSIZE );
+
+ default:
+ return 0;
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* parseFunc - creates a function record entry */
+/*-----------------------------------------------------------------*/
+void parseFunc (char *line)
+{
+ function *func;
+ char *rs = line;
+ int i;
+
+ 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 != ',')
+ rs++;
+ rs++;
+ 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);
+}
+
+/*-----------------------------------------------------------------*/
+/* parseTypeInfo - parse the type info of a symbol expects the type*/
+/* info to be of the form */
+/* ({<size>}<type info chain) */
+/*-----------------------------------------------------------------*/
+static char *parseTypeInfo (symbol *sym, char *s)
+{
+ char *bp;
+
+ s += 2; /* go past the ({ */
+ /* get the size */
+ sym->size = (short)strtol (s, &bp, 10);
+ /* bp now points to '}' ... go past it */
+ s = ++bp;
+ while (*s != ')') /* till we reach the end */
+ {
+ st_link *type;
+ type = Safe_calloc(1, sizeof(st_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) = (short)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;
+}
+
+/*-----------------------------------------------------------------*/
+/* symFromRec - parse a symbol record and extract and create a sym */
+/* expects the input string to be of the form */
+/* {G|F<filename>|L<filename>'.'<functionName>}'$' */
+/* <name>'$'<level>'$'<block><type info> */
+/*-----------------------------------------------------------------*/
+symbol *parseSymbol (char *s, char **rs, int doadd)
+{
+ symbol *nsym;
+ char save_ch;
+ char *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);
+ }
+
+ /* next get the name */
+ bp = ++s;
+ while ( *s != '$' )
+ s++;
+ nsym->name = alloccpy(bp, s - bp);
+
+ s++;
+ /* get the level number */
+ nsym->level = (short)strtol (s, &bp, 10);
+ s = ++bp;
+ /* skip the '$' & get the block number */
+ nsym->block = (short)strtol (s, &bp, 10);
+
+ s = parseTypeInfo(nsym, bp);
+
+ /* get the address space after going past the comma */
+ s++;
+ nsym->addrspace = *s;
+
+ s+= 2;
+ nsym->isonstack = (short)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;
+ 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* parseStruct - parses a structure record expected in format */
+/* {F<filename>}$<tag>[()()()...] */
+/*-----------------------------------------------------------------*/
+structdef *parseStruct (char *s)
+{
+ structdef *nsdef ;
+ char *bp;
+ char *name;
+ 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,0);
+ sym->offset = offset ;
+ s += 3;
+ if (!fields)
+ fields = nsdef->fields = sym;
+ else
+ fields = fields->next = sym;
+ nsdef->size += sym->size;
+ }
+
+ return nsdef;
+}
+
+/*-----------------------------------------------------------------*/
+/* parseModule - creates a module with a given name */
+/*-----------------------------------------------------------------*/
+module *parseModule (char *s, bool createName )
+{
+ module *nmod ;
+ char buffer[512];
+
+ nmod = Safe_calloc(1, sizeof(module));
+
+ addSet (&modules, nmod);
+
+ /* create copy file name */
+ nmod->name = s;
+
+ if (createName)
+ {
+ 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* moduleWithName - finds and returns a module with a given name */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(moduleWithName)
+{
+ module *mod = item;
+ V_ARG(char *, s);
+ V_ARG(module **, rmod);
+
+ if (*rmod)
+ return 0;
+
+ if (strcmp(mod->name, s) == 0)
+ {
+ *rmod = mod;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* moduleWithCName - finds and returns a module with a given c_name*/
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(moduleWithCName)
+{
+ module *mod = item;
+ V_ARG(char *, s);
+ V_ARG(module **, rmod);
+
+ if (*rmod)
+ return 0;
+
+ if (strcmp(mod->c_name, s) == 0)
+ {
+ *rmod = mod;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* moduleWithAsmName - finds & returns a module with given asm_name*/
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(moduleWithAsmName)
+{
+ module *mod = item;
+ V_ARG(char *, s);
+ V_ARG(module **, rmod);
+
+ if (*rmod)
+ return 0;
+
+ if (strcmp(mod->asm_name, s) == 0)
+ {
+ *rmod = mod;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* structWithName - returns a structure with a given name */
+/*-----------------------------------------------------------------*/
+structdef *structWithName (char *s)
+{
+ int i;
+ structdef *nsdef ;
+
+ /* 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];
+ }
+ }
+
+ 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;
+ return nsdef;
+}
+
+/*-----------------------------------------------------------------*/
+/* symWithRName - look for symbol with mangled name = parm */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(symWithRName)
+{
+ symbol *sym = item;
+ V_ARG(char *, s);
+ V_ARG(symbol **, rsym);
+
+ if (*rsym)
+ return 0;
+
+ if (strcmp(sym->rname, s) == 0)
+ {
+ *rsym = sym;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* funcWithRName - look for function with name */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(funcWithRName)
+{
+ function *func = item;
+ V_ARG(char *,s);
+ V_ARG(function **,rfunc);
+
+ if (*rfunc)
+ return 0;
+
+ if (strcmp(func->sym->rname,s) == 0)
+ {
+ *rfunc = func;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* symLocal - local symbol respecting blocks & levels */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(symLocal)
+{
+ symbol *sym = item;
+ V_ARG(char *, name);
+ V_ARG(char *, sname);
+ V_ARG(int, block);
+ V_ARG(int, level);
+ 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;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* symGlobal - return global symbol of name */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(symGlobal)
+{
+ symbol *sym = item;
+ V_ARG(char *, name);
+ V_ARG(symbol **, rsym);
+
+ if (*rsym)
+ return 0;
+
+ /* simple :: global & name matches */
+ if (sym->scopetype == 'G' &&
+ strcmp(sym->name, name) == 0)
+ {
+ *rsym = sym;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* symLookup - determine symbol from name & context */
+/*-----------------------------------------------------------------*/
+symbol *symLookup (char *name, context *ctxt)
+{
+ symbol *sym = NULL;
+
+ if ((ctxt) && (ctxt->func) &&
+ (ctxt->func->sym) && (ctxt->func->sym->name))
+ {
+ char *sname = gc_strcat(ctxt->func->mod->name, ".", ctxt->func->sym->name);
+ /* first try & find a local variable for the given name */
+ if ( applyToSet(symbols, symLocal,
+ name,
+ sname,
+ ctxt->block,
+ ctxt->level,
+ &sym))
+ {
+ Safe_free(sname);
+ return sym;
+ }
+ Safe_free(sname);
+ 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;
+
+ /* cannot find return null */
+ return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* lnkFuncEnd - link record for end of function */
+/*-----------------------------------------------------------------*/
+static void lnkFuncEnd (char *s)
+{
+ char sname[128], *bp = sname;
+ function *func;
+
+ /* copy till we get to a ':' */
+ while ( *s != ':' )
+ *bp++ = *s++;
+ bp -= 1;
+ *bp = '\0';
+
+ func = NULL;
+ if (!applyToSet(functions,funcWithRName,sname,&func))
+ return ;
+
+ s++;
+ sscanf(s,"%x",&func->sym->eaddr);
+
+ Dprintf(D_symtab, ("symtab: ead %s(0x%x)\n",func->sym->name,func->sym->eaddr));
+}
+
+/*-----------------------------------------------------------------*/
+/* lnkSymRec - record for a symbol */
+/*-----------------------------------------------------------------*/
+static void lnkSymRec (char *s)
+{
+ char *bp, save_ch ;
+ symbol *sym;
+
+ /* search to a ':' */
+ for ( bp = s; *bp && *bp != ':'; bp++ );
+ save_ch = *--bp;
+ *bp = '\0';
+
+ sym = NULL;
+ 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));
+}
+
+/*-----------------------------------------------------------------*/
+/* lnkAsmSrc - process linker record for asm sources */
+/*-----------------------------------------------------------------*/
+static void lnkAsmSrc (char *s)
+{
+ char mname[128], *bp = mname;
+ int line ;
+ unsigned addr;
+ module *mod = NULL;
+
+ /* input will be of format
+ filename$<line>:<address> */
+ while (*s != '$' && *s != '.')
+ *bp++ = *s++;
+ *bp = '\0';
+ /* skip to line stuff */
+ while (*s != '$')
+ s++;
+
+ if (!applyToSet(modules, moduleWithName, mname, &mod))
+ return ;
+
+ if (sscanf(s, "$%d:%x", &line, &addr) != 2)
+ return ;
+
+ line--;
+ if (line < mod->nasmLines)
+ {
+ mod->asmLines[line]->addr = addr;
+ Dprintf(D_symtab, ("symtab: asm %s(%d:0x%x) %s", mod->asm_name, line, addr, mod->asmLines[line]->src));
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* lnkCSrc - process linker output for c source */
+/*-----------------------------------------------------------------*/
+static void lnkCSrc (char *s)
+{
+ char mname[128], *bp = mname;
+ int block,level,line;
+ unsigned int addr;
+ module *mod ;
+
+ /* input will be of format
+ filename.ext$<line>$<level>$<block>:<address> */
+ /* get the module name */
+ while (*s != '$' )
+ *bp++ = *s++;
+ *bp = '\0';
+ /* skip the extension */
+ while (*s != '$')
+ s++;
+
+ if (sscanf(s,"$%d$%d$%d:%x", &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);
+ }
+
+ line--;
+ /* 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* parseLnkRec - parses a linker generated record */
+/*-----------------------------------------------------------------*/
+void parseLnkRec (char *s)
+{
+ /* 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 */
+ case 'A':
+ lnkAsmSrc(s+2);
+ break;
+
+ case 'X':
+ lnkFuncEnd(s+1);
+ break;
+
+ default :
+ lnkSymRec(s);
+ break;
+ }
+}