Warning when libfile not found and path is null
[fw/sdcc] / link / z80 / lklibr.c
index e5999621c60bec1eb467cfdd7433fdd3da9b8f39..eb4cd98da98e8cfee0cee2d915a385b89d520dd2 100644 (file)
  * Extensions: P. Felber
  */
 
+#define EQ(A,B) !strcmp((A),(B))
+#define MAXLINE 254 /*when using fgets*/
+
 #include <stdio.h>
 #include <string.h>
-#include <alloc.h>
+#include <stdlib.h>
 #include "aslink.h"
 
+#ifdef OTHERSYSTEM
+#ifdef SDK
+#ifdef UNIX
+    #define LKDIRSEP '/'
+    #define LKDIRSEPSTR "/"
+#else /* UNIX */
+       #define LKDIRSEP '\\'
+       #define LKDIRSEPSTR "\\"
+#endif /* UNIX */
+#else /* SDK */
+       #define LKDIRSEP '\\'
+       #define LKDIRSEPSTR "\\"
+#endif /* SDK */
+#endif
+
+#ifdef __CYGWIN__
+void ToCygWin(char * filspc)
+{
+    char posix_path[PATH_MAX];
+    void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
+    cygwin_conv_to_full_posix_path(filspc, posix_path);
+    strcpy(filspc, posix_path);
+}
+#endif
+
 /*)Module      lklibr.c
  *
  *     The module lklibr.c contains the functions which
@@ -48,7 +76,7 @@ typedef struct slibrarysymbol mlibrarysymbol;
 typedef struct slibrarysymbol *pmlibrarysymbol;
 
 struct slibrarysymbol {
-       char name[40];
+       char name[NCPS];
        pmlibrarysymbol next;
 };
 
@@ -59,8 +87,9 @@ struct slibraryfile {
        int loaded;
        char *libspc;
        char *str;
-       char relfil[80];
-       char filename[80];
+       char relfil[FILSPC];
+       char filename[FILSPC];
+    long offset; //if > 0, the embedded file offset in the library file libspc
        pmlibrarysymbol symbols;
        pmlibraryfile next;
 };
@@ -126,6 +155,7 @@ addpath()
  *     global variables:
  *             lbpath  *lbphead        The pointer to the first
  *                                     path structure
+ *      ip a pointer to the library name
  *
  *      functions called:
  *             VOID    addfile()       lklibr.c
@@ -141,19 +171,28 @@ VOID
 addlib()
 {
        struct lbpath *lbph;
+    int foundcount=0;
 
        unget(getnb());
 
-       if (lbphead == NULL) {
-               addfile(NULL,ip);
-               return;
-       }       
-       for (lbph=lbphead; lbph; lbph=lbph->next) {
-               addfile(lbph->path,ip);
+       if (lbphead == NULL)
+    {
+               foundcount+=addfile(NULL, ip);
        }
+    else
+    {
+           for (lbph=lbphead; lbph; lbph=lbph->next)
+        {
+                   foundcount+=addfile(lbph->path,ip);
+           }
+    }
+    if(foundcount==0)
+    {
+        printf("\n?ASlink-Warning-Couldn't find library '%s'", ip);
+    }
 }
 
-/*)Function    VOID    addfile(path,libfil)
+/*)Function    int     addfile(path,libfil)
  *
  *             char    *path           library path specification
  *             char    *libfil         library file specification
@@ -185,72 +224,108 @@ addlib()
  *
  *     side effects:
  *             An lbname structure may be created.
+ *
+ *  return:
+ *      1: the library was found
+ *      0: the library was not found
  */
 
-VOID
-addfile(path,libfil)
-char *path;
-char *libfil;
+int addfile(char * path, char * libfil)
 {
        FILE *fp;
        char *str;
        struct lbname *lbnh, *lbn;
+    int libfilinc=0;
 
-       if ((path != NULL) && (strchr(libfil,':') == NULL)){
+       if (path != NULL)
+    {
                str = (char *) new (strlen(path) + strlen(libfil) + 6);
-               strcpy(str,path);
-#ifdef OTHERSYSTEM
-#ifdef SDK
-#ifdef UNIX
-               if (str[strlen(str)-1] != '/') {
-                       strcat(str,"/");
-#else /* UNIX */
-               if (str[strlen(str)-1] != '\\') {
-                       strcat(str,"\\");
-#endif /* UNIX */
-#else /* SDK */
-               if (str[strlen(str)-1] != '\\') {
-                       strcat(str,"\\");
-#endif /* SDK */
+               strcpy(str, path);
+
+        if (str[strlen(str)-1] != LKDIRSEP)
+        {
+                       strcat(str, LKDIRSEPSTR);
                }
-#endif
-       } else {
+       }
+    else
+    {
                str = (char *) new (strlen(libfil) + 5);
        }
-#ifdef OTHERSYSTEM
-#ifdef SDK
-#ifdef UNIX
-       if (libfil[0] == '/') { libfil++; }
-#else /* UNIX */
-       if (libfil[0] == '\\') { libfil++; }
-#endif /* UNIX */
-#else /* SDK */
-       if (libfil[0] == '\\') { libfil++; }
-#endif /* SDK */
-#endif
-       strcat(str,libfil);
-       if(strchr(str,FSEPX) == NULL) {
+
+       if (libfil[0] == LKDIRSEP)
+    {
+        libfil++;
+        libfilinc=1;
+    }
+       
+    strcat(str, libfil);
+
+       if(strchr(libfil, FSEPX) == NULL)
+    {
                sprintf(&str[strlen(str)], "%clib", FSEPX);
        }
-       if ((fp = fopen(str, "r")) != NULL) {
+
+    fp=fopen(str, "r");
+    if(fp == NULL)
+    {
+        /*Ok, that didn't work.  Try with the 'libfil' name only*/
+        if(libfilinc) libfil--;
+        fp=fopen(libfil, "r");
+        if(fp != NULL) 
+        {
+            /*Bingo!  'libfil' is the absolute path of the library*/
+            strcpy(str, libfil);
+            path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
+        }
+    }
+
+    if(path==NULL)
+    {
+        /*'path' can not be null since it is needed to find the '.o' 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'.*/
+        int j;
+        path = (char *) new (strlen(str));
+        strcpy(path, str);
+        for(j=strlen(path)-1; j>=0; j--)
+        {
+            if((path[j]=='\\')||(path[j]=='/'))
+            {
+                strcpy(libfil, &path[j+1]);
+                path[j+1]=0;
+                break;
+            }
+        }
+        if(j<=0) path[0]=0;
+    }
+
+       if (fp != NULL)
+    {
                fclose(fp);
                lbnh = (struct lbname *) new (sizeof(struct lbname));
-               if (lbnhead == NULL) {
+               if (lbnhead == NULL)
+        {
                        lbnhead = lbnh;
-               } else {
+               }
+        else
+        {
                        lbn = lbnhead;
                        while (lbn->next)
                                lbn = lbn->next;
                        lbn->next = lbnh;
                }
-               if ((path != NULL) && (strchr(libfil,':') == NULL)){
-                       lbnh->path = path;
-               }
+
+               lbnh->path = path;
                lbnh->libfil = (char *) new (strlen(libfil) + 1);
-               strcpy(lbnh->libfil,libfil);
+               strcpy(lbnh->libfil, libfil);
                lbnh->libspc = str;
-       } else {
+        return 1;
+       }
+    else
+    {
                free(str);
+        return 0;
        }
 }
 
@@ -323,6 +398,43 @@ search()
        }
 }
 
+/*Load a .rel file embedded in a sdcclib file*/
+void LoadRel(FILE * libfp, char * ModName)
+{
+       char str[NINPUT+2];
+       int state=0;
+
+       while (fgets(str, NINPUT, libfp) != NULL)
+       {
+               str[NINPUT+1] = '\0';
+               chop_crlf(str);
+               switch(state)
+               {
+                       case 0:
+                               if(EQ(str, "<FILE>"))
+                               {
+                                       fgets(str, NINPUT, libfp);
+                                       str[NINPUT+1] = '\0';
+                                       chop_crlf(str);
+                                       if(EQ(str, ModName)) state=1;
+                                       else
+                                       {
+                                               printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
+                                               lkexit(1);
+                                       }
+                               }
+                       break;
+                       case 1:
+                               if(EQ(str, "<REL>")) state=2;
+                       break;
+                       case 2:
+                               if(EQ(str, "</REL>")) return;
+                               ip = str;
+                               link();
+                       break;
+               }
+       }
+}
 
 /*)Function    VOID    fndsym(name)
  *
@@ -398,9 +510,7 @@ search()
 #ifdef INDEXLIB
 
 /* First entry in the library object symbol cache */
-mlibraryfile libr = {
-      0, "", NULL, NULL
-};
+mlibraryfile libr;
 
 int fndsym( char *name )
 {
@@ -420,6 +530,7 @@ int fndsym( char *name )
                ThisSym = ThisLibr->symbols->next;
 
                while (ThisSym) {
+            //printf("ThisSym->name=%s\n", ThisSym->name);
                        if (!strcmp(ThisSym->name, name)) {
                                if (!ThisLibr->loaded) {
                                        /* Object file is not loaded - add it to the list */
@@ -436,7 +547,16 @@ int fndsym( char *name )
                                        lbfh->filspc = ThisLibr->str;
                                        lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
                                        strcpy(lbfh->relfil,ThisLibr->relfil);
-                                       loadfile(lbfh->filspc);
+                    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*/
+                                           loadfile(lbfh->filspc);
+                    }
                                        ThisLibr->loaded=1;
                                }
                                return (1);     /* Found the symbol, return */
@@ -446,13 +566,113 @@ int fndsym( char *name )
                ThisLibr=ThisLibr->next; /* Next library in list */
        }
        return 0;       /* Failure - symbol not found in any library */
-};
+}
+
+pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
+{
+       char ModName[NCPS]="";
+       char FLine[MAXLINE+1];
+       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*/
+                                       This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
+                                       if (This->next == NULL)
+                    {
+                                               printf("panic: can't allocate memory.\n");
+                                               exit(-1);
+                                       }
+
+                                       This=This->next;
+                                       This->next = NULL;
+                                       This->loaded=-1; /*Kind of useless, but...*/
+                    This->offset=FileOffset+IndexOffset;
+                                       This->libspc=PathLib;
+                                       strcpy(This->relfil, ModName);
+
+                    #ifdef SDK
+                    sprintf(This->filename, "%s%s%co", DirLib, ModName, FSEPX);
+                    #else /* SDK */
+                    sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
+                    #endif /* SDK */
+
+                    This->str=This->filename;
+
+                                       ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
+                                       ThisSym->next = NULL;
+                               }
+                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*/
+                                       ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
+                                       ThisSym=ThisSym->next;
+                                       if (ThisSym == NULL)
+                    {
+                                               printf("panic: can't allocate memory.\n");
+                                               exit(-2);
+                                       }
+                                       ThisSym->next=NULL;
+                                       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()
+int buildlibraryindex(void)
 {
        FILE *libfp, *fp;
        struct lbname *lbnh;
@@ -478,9 +698,9 @@ int buildlibraryindex()
 
 /*2*/                  while (fgets(relfil, NINPUT, libfp) != NULL) {
                                relfil[NINPUT+1] = '\0';
-                               relfil[strlen(relfil) - 1] = '\0';
+                               chop_crlf(relfil);
                                if (path != NULL) {
-                                       str = (char *)malloc(strlen(path)+strlen(relfil)+6);
+                                       str = (char *)new(strlen(path)+strlen(relfil)+6);
                                        strcpy(str,path);
 #ifdef OTHERSYSTEM
 #ifdef SDK
@@ -498,8 +718,20 @@ int buildlibraryindex()
                                        }
 #endif
                                } else {
-                                       str = (char *)malloc(strlen(relfil) + 5);
+                                       str = (char *)new(strlen(relfil) + 5);
                                }
+
+                if(strcmp(relfil, "<SDCCLIB>")==0)
+                           {
+                    /*Get the built in index of a library*/
+                                   This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
+                                   free(str);
+                                   fclose(libfp);
+                                   break; /*get the index for next library*/
+                           }
+                
+                /*From here down, build the index for the original library
+                format*/
 #ifdef SDK
 #ifdef UNIX
                                if (relfil[0] == '/') {
@@ -523,15 +755,16 @@ int buildlibraryindex()
 /*3*/                          if ((fp = fopen(str, "r")) != NULL) {
 
                                        /* Opened OK - create a new libraryfile object for it */
-                                       This->next = (pmlibraryfile)malloc( sizeof( mlibraryfile ));
+                                       This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
                                        if (This->next == NULL) {
-                                               printf("panic: cant allocate memory.\n");
+                                               printf("panic: can't allocate memory.\n");
                                                exit(-1);
                                        }
 
                                        This=This->next;
                                        This->next = NULL;
                                        This->loaded=-1;
+                    This->offset=-1; /*There should be a rel file*/
 
                                        strcpy( This->filename, str );
 
@@ -571,7 +804,7 @@ int buildlibraryindex()
                                                ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
                                                ThisSym=ThisSym->next;
                                                if (ThisSym == NULL) {
-                                                       printf("panic: cant allocate memory.\n");
+                                                       printf("panic: can't allocate memory.\n");
                                                        exit(-2);
                                                }
                                                This->loaded=0;
@@ -592,6 +825,127 @@ int buildlibraryindex()
 }
 #else /* INDEXLIB */
 
+
+/*Check for a symbol in a SDCC library.  If found, add the embedded .rel.
+The library must be created with the SDCC librarian 'sdcclib' since the
+linking process depends on the correct file offsets embedded in the library
+file.*/
+
+int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
+{
+       struct lbfile *lbfh, *lbf;
+       char ModName[NCPS]="";
+       char FLine[MAXLINE+1];
+       int state=0;
+       long IndexOffset=0, FileOffset;
+
+       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;
+                               }
+                else if(EQ(FLine, "</INDEX>"))
+                               {
+                                       /*Reached the end of the index.  The symbol is not in this library.*/
+                                       return 0;
+                               }
+            break;
+            case 2:
+                if(EQ(FLine, "</MODULE>"))
+                               {
+                                       /*The symbol is not in this module, try the next one*/
+                    state=1;
+                               }
+                else
+                               {
+                                       /*Check if this is the symbol we are looking for.*/
+                                       if (strncmp(SymName, FLine, NCPS)==0)
+                                       {
+                                               /*The symbol is in this module.*/
+
+                                               /*As in the original library format, it is assumed that the .rel
+                                               files reside in the same directory as the lib files.*/
+                                               strcat(DirLib, ModName);
+                        #ifdef SDK
+                                   sprintf(&DirLib[strlen(DirLib)], "%co", FSEPX);
+                        #else /* SDK */
+                                   sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
+                        #endif /* SDK */
+
+                                               /*If this module has been loaded already don't load it again.*/
+                                               lbf = lbfhead;
+                                               while (lbf)
+                                               {
+                                                       if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
+                                                       lbf=lbf->next;
+                                               }
+                                               
+                                               /*Add the embedded file to the list of files to be loaded in
+                                               the second pass.  That is performed latter by the function
+                                               library() below.*/
+                                               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 = PathLib;
+                                               lbfh->filspc = DirLib;
+                                               lbfh->relfil = (char *) new (strlen(ModName) + 1);
+                                               strcpy(lbfh->relfil, ModName);
+                                               /*Library embedded file, so lbfh->offset must be >=0*/
+                                               lbfh->offset = IndexOffset+FileOffset;
+                                               
+                                               /*Jump to where the .rel begins and load it.*/
+                                               fseek(libfp, lbfh->offset, SEEK_SET);
+                                               LoadRel(libfp, ModName);
+
+                                               return 1; /*Found the symbol, so success!*/
+                                       }
+                               }
+            break;
+                       
+                       default:
+                               return 0; /*It should never reach this point, but just in case...*/
+                       break;
+        }
+    }
+
+       return 0; /*The symbol is not in this library*/
+}
+
 int
 fndsym(name)
 char *name;
@@ -604,6 +958,7 @@ char *name;
        char symname[NINPUT];
        char *path,*str;
        char c;
+       int result;
 
        /*
         * Search through every library in the linked list "lbnhead".
@@ -625,7 +980,7 @@ char *name;
 
 /*2*/          while (fgets(relfil, NINPUT, libfp) != NULL) {
                    relfil[NINPUT+1] = '\0';
-                   relfil[strlen(relfil) - 1] = '\0';
+                   chop_crlf(relfil);
                    if (path != NULL) {
                        str = (char *) new (strlen(path)+strlen(relfil)+6);
                        strcpy(str,path);
@@ -647,6 +1002,20 @@ char *name;
                    } else {
                        str = (char *) new (strlen(relfil) + 5);
                    }
+
+            /*See if this is a library with embedded files*/
+                       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,
+                               check the next library in the list*/
+                               break; 
+                       }
+
+                       /*From here down is the support for libraries in the original format*/
 #ifdef SDK
 #ifdef UNIX
                    if (relfil[0] == '/') {
@@ -660,7 +1029,7 @@ char *name;
                    } else {
                        strcat(str,relfil);
                    }
-                   if(strchr(str,FSEPX) == NULL) {
+                   if(strchr(relfil,FSEPX) == NULL) {
 #ifdef SDK
                        sprintf(&str[strlen(str)], "%co", FSEPX);
 #else /* SDK */
@@ -717,6 +1086,7 @@ char *name;
                        lbfh->libspc = lbnh->libspc;
                        lbfh->filspc = str;
                        lbfh->relfil = (char *) new (strlen(relfil) + 1);
+                       lbfh->offset = -1; /*Stand alone rel file*/
                        strcpy(lbfh->relfil,relfil);
                        fclose(fp);
                        fclose(libfp);
@@ -737,6 +1107,22 @@ char *name;
 }
 #endif /* INDEXLIB */
 
+void loadfile_SdccLib(char * libspc, char * module, long offset)
+{
+       FILE *fp;
+
+#ifdef __CYGWIN__
+    ToCygWin(libspc);
+#endif
+
+       if ((fp = fopen(libspc,"r")) != NULL)
+       {
+               fseek(fp, offset, SEEK_SET);
+               LoadRel(fp, module);
+               fclose(fp);
+       }
+}
+
 /*)Function    VOID    library()
  *
  *     The function library() links all the library object files
@@ -760,8 +1146,18 @@ library()
 {
        struct lbfile *lbfh;
 
-       for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
-               loadfile(lbfh->filspc);
+       for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
+       {
+               if(lbfh->offset<0)
+               {
+                       /*Stand alone rel file (original lib format)*/
+                       loadfile(lbfh->filspc);
+               }
+               else
+               {
+                       /*rel file embedded in lib (new lib format)*/
+                       loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
+               }
        }
 }
 
@@ -798,6 +1194,10 @@ char *filspc;
        char str[NINPUT+2];
        int i;
 
+#ifdef __CYGWIN__
+    ToCygWin(filspc);
+#endif
+
        if ((fp = fopen(filspc,"r")) != NULL) {
                while (fgets(str, NINPUT, fp) != NULL) {
                        str[NINPUT+1] = '\0';
@@ -809,4 +1209,9 @@ char *filspc;
                }
                fclose(fp);
        }
+    else
+    {
+        printf("Couldn't find file %s\n", filspc);
+        exit(-4);
+    }
 }