* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[fw/sdcc] / as / mcs51 / lklibr.c
index e880d7a6e23e164dbbdb7f74a902fef80ab16d0a..c08b8580d22c4e46274831c27c04088a2b5e3144 100644 (file)
 #define EQ(A,B) !strcmp((A),(B))
 #define MAXLINE 254 /*when using fgets*/
 
-#if defined(__APPLE__) && defined(__MACH__)
-#include <sys/types.h>
-#include <sys/malloc.h>
-#else
-#include <malloc.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include "aslink.h"
 
 /*)Module      lklibr.c
  *
  */
 
+#ifdef INDEXLIB
+typedef struct slibrarysymbol mlibrarysymbol;
+typedef struct slibrarysymbol *pmlibrarysymbol;
+
+struct slibrarysymbol {
+       char * name; /*Warning: allocate memory before using*/
+       pmlibrarysymbol next;
+};
+
+typedef struct slibraryfile mlibraryfile;
+typedef struct slibraryfile *pmlibraryfile;
+
+struct slibraryfile {
+       int loaded;
+       char * libspc;
+       char * relfil; /*Warning: allocate memory before using*/
+       char * filename; /*Warning: allocate memory before using*/
+    long offset; //if > 0, the embedded file offset in the library file libspc
+       pmlibrarysymbol symbols;
+       pmlibraryfile next;
+};
+
+/* First entry in the library object symbol cache */
+pmlibraryfile libr=NULL;
+
+int buildlibraryindex();
+void freelibraryindex (void);
+#endif /* INDEXLIB */
+
 /*)Function    VOID    addpath()
  *
  *     The function addpath() creates a linked structure containing
@@ -126,16 +150,20 @@ addlib()
 
        unget(getnb());
 
-       if (lbphead == NULL) {
-               addfile(NULL,ip);
-               return;
-       }       
-       for (lbph=lbphead; lbph; lbph=lbph->next) {
-               foundcount+=addfile(lbph->path,ip);
+       if (lbphead == NULL)
+    {
+               foundcount=addfile(NULL, ip);
        }
-    if(foundcount==0)
+    else
+    {
+           for (lbph=lbphead; lbph; lbph=lbph->next)
+        {
+                   foundcount+=addfile(lbph->path, ip);
+           }
+    }
+    if(foundcount == 0)
     {
-        printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
+        fprintf(stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip);
     }
 }
 
@@ -234,7 +262,7 @@ int addfile(char * path, char * libfil)
 
     if(path==NULL)
     {
-        /*'path' can not be null since it is needed to find the '.o' files associated with
+        /*'path' can not be null since it is needed to find the '.rel' files associated with
         the library.  So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
         That way putting 'path' and 'libfil' together will result into the original filepath
         as contained in 'str'.*/
@@ -352,7 +380,7 @@ search()
 }
 
 /*Load a .rel file embedded in a sdcclib file*/
-void LoadRel(FILE * libfp, char * ModName)
+void LoadRel(char * libfname, FILE * libfp, char * ModName)
 {
        char str[NINPUT+2];
        int state=0;
@@ -372,7 +400,8 @@ void LoadRel(FILE * libfp, char * ModName)
                                        if(EQ(str, ModName)) state=1;
                                        else
                                        {
-                                               printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
+                                               fprintf(stderr, "?Aslink-Error-Bad offset in library file %s(%s)\n",
+                            libfname, ModName);
                                                lkexit(1);
                                        }
                                }
@@ -518,7 +547,7 @@ int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
                                                
                                                /*Jump to where the .rel begins and load it.*/
                                                fseek(libfp, lbfh->offset, SEEK_SET);
-                                               LoadRel(libfp, ModName);
+                                               LoadRel(PathLib, libfp, ModName);
 
                                                /* if cdb information required & .adb file present */
                                                if (dflag && dfp)
@@ -611,6 +640,408 @@ int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
  *             is linked.
  */
 
+#ifdef INDEXLIB
+
+int fndsym( char *name )
+{
+       struct lbfile *lbfh, *lbf;
+       pmlibraryfile ThisLibr;
+       pmlibrarysymbol ThisSym = NULL;
+
+    pmlibraryfile FirstFound;
+    int numfound=0;
+
+       /* Build the index if this is the first call to fndsym */
+       if (libr==NULL) buildlibraryindex();
+       
+       /* Iterate through all library object files */
+       ThisLibr = libr;
+    FirstFound = libr; /*So gcc stops whining*/
+       while (ThisLibr)
+    {
+               /* Iterate through all symbols in an object file */
+               ThisSym = ThisLibr->symbols;
+
+               while (ThisSym)
+        {
+                       if (!strcmp(ThisSym->name, name))
+            {
+                               if ((!ThisLibr->loaded) && (numfound==0))
+                {
+                                       /* Object file is not loaded - add it to the list */
+                                       lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+                                       if (lbfhead == NULL)
+                    {
+                                               lbfhead = lbfh;
+                                       }
+                    else
+                    {
+                                               lbf = lbfhead;
+                                               while (lbf->next)
+                                               lbf = lbf->next;
+                                               lbf->next = lbfh;
+                                       }
+                                       lbfh->libspc = ThisLibr->libspc;
+                                       lbfh->filspc = ThisLibr->filename;
+                                       lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
+                                       strcpy(lbfh->relfil, ThisLibr->relfil);
+                    lbfh->offset = ThisLibr->offset;
+                    if(lbfh->offset>0)
+                    { /*For an embedded object file in a library*/
+                        void loadfile_SdccLib(char * libspc, char * module, long offset);
+                        loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
+                    }
+                    else
+                    { /*For a stand alone object file*/
+                                               /* if cdb information required & adb file present */
+                                               if (dflag && dfp)
+                                               {
+                                                       FILE *xfp = afile(lbfh->filspc, "adb",0);
+                                                       if (xfp)
+                                                       {
+                                                               SaveLinkedFilePath(lbfh->filspc);
+                                                               copyfile(dfp, xfp);
+                                                               fclose(xfp);
+                                                       }
+                                               }
+                        loadfile(lbfh->filspc);
+                    }
+                                       ThisLibr->loaded=1;
+                               }
+
+                if(numfound==0)
+                {
+                    numfound++;
+                    FirstFound=ThisLibr;
+                }
+                else
+                {
+                    char absPath1[PATH_MAX];
+                    char absPath2[PATH_MAX];
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+                    int j;
+
+                    _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
+                    _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
+                    for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower((unsigned char)absPath1[j]);
+                    for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower((unsigned char)absPath2[j]);
+#else
+                    realpath(FirstFound->libspc, absPath1);
+                    realpath(ThisLibr->libspc, absPath2);
+#endif
+                    if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
+                    {
+                        if(numfound==1)
+                        {
+                            fprintf(stderr, "?Aslink-Warning-Definition of public symbol '%s'"
+                                   " found more than once:\n", name);
+                            fprintf(stderr, "   Library: '%s', Module: '%s'\n",
+                                    FirstFound->libspc, FirstFound->relfil);
+                        }
+                        fprintf(stderr, "   Library: '%s', Module: '%s'\n",
+                                ThisLibr->libspc, ThisLibr->relfil);
+                        numfound++;
+                    }
+                }
+                       }
+                       ThisSym=ThisSym->next;  /* Next sym in library */
+               }
+               ThisLibr=ThisLibr->next; /* Next library in list */
+       }
+       return numfound;
+}
+
+pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
+{
+       char ModName[NCPS]="";
+       char FLine[MAXLINE+1];
+    char buff[PATH_MAX];
+       int state=0;
+       long IndexOffset=0, FileOffset;
+    pmlibrarysymbol ThisSym = NULL;
+
+       while(!feof(libfp))
+    {
+        FLine[0]=0;
+        fgets(FLine, MAXLINE, libfp);
+        chop_crlf(FLine);
+
+        switch(state)
+        {
+            case 0:
+                if(EQ(FLine, "<INDEX>"))
+                {
+                                       /*The next line has the size of the index*/
+                    FLine[0]=0;
+                    fgets(FLine, MAXLINE, libfp);
+                    chop_crlf(FLine);
+                                       IndexOffset=atol(FLine);
+                                       state=1;
+                }
+            break;
+            case 1:
+                if(EQ(FLine, "<MODULE>"))
+                               {
+                                       /*The next line has the name of the module and the offset
+                                       of the corresponding embedded file in the library*/
+                    FLine[0]=0;
+                    fgets(FLine, MAXLINE, libfp);
+                    chop_crlf(FLine);
+                                       sscanf(FLine, "%s %ld", ModName, &FileOffset);
+                                       state=2;
+
+                    /*Create a new libraryfile object for this module*/
+                    if(libr==NULL)
+                    {
+                        libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
+                    }
+                    else
+                    {
+                                           This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
+                                           This=This->next;
+                    }
+                                       This->next = NULL;
+                                       This->loaded=-1;
+                    This->offset=FileOffset+IndexOffset;
+                                       This->libspc=PathLib;
+                    
+                    This->relfil=(char *)new(strlen(ModName)+1);
+                                       strcpy(This->relfil, ModName);
+                    
+                    sprintf(buff, "%s%s%crel", DirLib, ModName, FSEPX);
+                    This->filename=(char *)new(strlen(buff)+1);
+                    strcpy(This->filename, buff);
+                    
+                    This->symbols=ThisSym=NULL; /*Start a new linked list of symbols*/
+                               }
+                else if(EQ(FLine, "</INDEX>"))
+                               {
+                                       return This; /*Finish, get out of here*/
+                               }
+            break;
+            case 2:
+                if(EQ(FLine, "</MODULE>"))
+                               {
+                                       This->loaded=0;
+                                       /*Create the index for the next module*/
+                    state=1;
+                               }
+                else
+                               {
+                                       /*Add the symbols*/
+                    if(ThisSym==NULL) /*First symbol of the current module*/
+                    {
+                                           ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+                    }
+                    else
+                    {
+                                           ThisSym->next = (pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+                                       ThisSym=ThisSym->next;
+                    }
+                                       ThisSym->next=NULL;
+                    ThisSym->name=(char *)new(strlen(FLine)+1);
+                                       strcpy(ThisSym->name, FLine);
+                }
+            break;
+                       
+                       default:
+                               return This; /*State machine should never reach this point, but just in case...*/
+                       break;
+        }
+    }
+
+       return This; /*State machine should never reach this point, but just in case...*/
+}
+
+
+/* buildlibraryindex - build an in-memory cache of the symbols contained in
+ *                     the libraries
+ */
+int buildlibraryindex(void)
+{
+       FILE *libfp, *fp;
+       struct lbname *lbnh;
+       char relfil[NINPUT+2], str[PATH_MAX], *path;
+       char buf[NINPUT+2], c;
+       char symname[NINPUT+2];
+       pmlibraryfile This=NULL;
+       pmlibrarysymbol ThisSym;
+
+       /*
+        * Search through every library in the linked list "lbnhead".
+        */
+
+    for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
+    {
+               if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
+               {
+                       fprintf(stderr, "?Aslink-Error-Cannot open library file %s\n",
+                               lbnh->libspc);
+                       lkexit(1);
+               }
+               path = lbnh->path;
+
+               /*
+                * Read in a line from the library file.
+                * This is the relative file specification
+                * for a .REL file in this library.
+                */
+
+        while (fgets(relfil, NINPUT, libfp) != NULL)
+        {
+            relfil[NINPUT+1] = '\0';
+            chop_crlf(relfil);
+            if (path != NULL)
+            {
+                               strcpy(str, path);
+#ifdef OTHERSYSTEM
+                               if (str[strlen(str)-1] != '/')
+                               {
+                                       strcat(str,"/");
+                               }
+#endif
+                       }
+            else
+            {
+                strcpy(str, "");
+                       }
+
+            if(strcmp(relfil, "<SDCCLIB>")==0)
+                       {
+                /*Get the built in index of this library*/
+                               This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
+                               break; /*get the index for next library*/
+                       }
+                
+            /*From here down, build the index for the original library format*/
+
+                       if (relfil[0] == '\\')
+            {
+                               strcat(str,relfil+1);
+                       }
+            else
+            {
+                               strcat(str,relfil);
+                       }
+
+            if(strchr(relfil, FSEPX) == NULL)
+            {
+                               sprintf(&str[strlen(str)], "%crel", FSEPX);
+                       }
+               
+            if ((fp = fopen(str, "r")) != NULL)
+            {
+                /* Opened OK - create a new libraryfile object for it */
+                if(libr==NULL)
+                {
+                    libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
+                }
+                else
+                {
+                                       This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
+                               This=This->next;
+                }
+                           This->next = NULL;
+                           This->loaded=-1;
+                This->offset=-1; /*We have a stand alone .rel file*/
+                               This->libspc = lbnh->libspc;
+                
+                This->relfil=(char *)new(strlen(relfil)+1);
+                               strcpy(This->relfil, relfil);
+                
+                This->filename=(char *)new(strlen(str)+1);
+                               strcpy(This->filename, str);
+
+                /*Start a new linked list of symbols for this module:*/
+                This->symbols=ThisSym=NULL;
+
+                               /*
+                                * Read in the object file.  Look for lines that
+                                * begin with "S" and end with "D".  These are
+                                * symbol table definitions.  If we find one, see
+                                * if it is our symbol.  Make sure we only read in
+                                * our object file and don't go into the next one.
+                                */
+               
+                               while (fgets(buf, NINPUT, fp) != NULL)
+                {
+                                       buf[NINPUT+1] = '\0';
+                                       buf[strlen(buf) - 1] = '\0';
+
+                                       /*
+                                        * Skip everything that's not a symbol record.
+                                        */
+                                       if (buf[0] != 'S') continue;
+
+                                       /*
+                                        * When a 'T line' is found terminate file scan.
+                                        * All 'S line's preceed 'T line's in .REL files.
+                                        */
+                                       if (buf[0] == 'T') break;
+
+                                       sscanf(buf, "S %s %c", symname, &c);
+
+                                       /* If it's an actual symbol, record it */
+                               if (c == 'D')
+                    {
+                        if(ThisSym==NULL)
+                        {
+                                           ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+                        }
+                        else
+                        {
+                                                   ThisSym->next=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+                                                   ThisSym=ThisSym->next;
+                        }
+                                               This->loaded=0;
+                                               ThisSym->next=NULL;
+                        ThisSym->name=(char *)new(strlen(symname)+1);
+                                               strcpy(ThisSym->name, symname);
+                                       }
+                               } /* Closes while - read object file */
+                               fclose(fp);
+                       } /* Closes if object file opened OK */
+            else
+            {
+                           fprintf(stderr, "?Aslink-Warning-Cannot open library module %s\n", str);
+            }
+               } /* Ends while - processing all in libr */
+               fclose(libfp);
+       } /* Ends good open of libr file */
+       return 0;
+}
+
+/*Release all memory allocated for the in-memory library index*/
+void freelibraryindex (void)
+{
+       pmlibraryfile ThisLibr, ThisLibr2Free;
+       pmlibrarysymbol ThisSym, ThisSym2Free;
+
+       ThisLibr = libr;
+
+    while (ThisLibr)
+    {
+               ThisSym = ThisLibr->symbols;
+
+               while (ThisSym)
+        {
+            free(ThisSym->name);
+            ThisSym2Free=ThisSym;
+            ThisSym=ThisSym->next;
+            free(ThisSym2Free);
+        }
+        free(ThisLibr->filename);
+        free(ThisLibr->relfil);
+        ThisLibr2Free=ThisLibr;
+        ThisLibr=ThisLibr->next;
+        free(ThisLibr2Free);
+    }
+    
+    libr=NULL;
+}
+
+#else /* INDEXLIB */
+
 int
 fndsym(name)
 char *name;
@@ -633,7 +1064,7 @@ char *name;
        {
                if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
                {
-                       fprintf(stderr, "Cannot open library file %s\n",
+                       fprintf(stderr, "?Aslink-Error-Cannot open library file %s\n",
                                lbnh->libspc);
                        lkexit(1);
                }
@@ -668,7 +1099,6 @@ char *name;
                        if(strcmp(relfil, "<SDCCLIB>")==0)
                        {
                                result=SdccLib(lbnh->libspc, libfp, str, name);
-                               fclose(libfp);
                                if(result) return(1); /*Found the symbol*/
                                free(str);
                                /*The symbol is not in the current library,
@@ -772,6 +1202,8 @@ char *name;
        return(0);
 }
 
+#endif /*INDEXLIB*/
+
 void loadfile_SdccLib(char * libspc, char * module, long offset)
 {
        FILE *fp;
@@ -779,7 +1211,7 @@ void loadfile_SdccLib(char * libspc, char * module, long offset)
        if ((fp = fopen(libspc,"r")) != NULL)
        {
                fseek(fp, offset, SEEK_SET);
-               LoadRel(fp, module);
+               LoadRel(libspc, fp, module);
                fclose(fp);
        }
 }
@@ -820,6 +1252,9 @@ library()
                        loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
                }
        }
+#ifdef INDEXLIB
+    freelibraryindex();
+#endif
 }
 
 /*)Function    VOID    loadfile(filspc)
@@ -864,3 +1299,4 @@ char *filspc;
                fclose(fp);
        }
 }
+