]> Shamusworld >> Repos - rln/blobdiff - rln.c
Fix to test to see if include paths actually exist.
[rln] / rln.c
diff --git a/rln.c b/rln.c
index 1dd7520a77f5489966c7030a8cf8b229c9ac3da7..23b2fea77f8df642a65f53f03cb118a47c32f0c8 100644 (file)
--- a/rln.c
+++ b/rln.c
@@ -1,7 +1,6 @@
 //
-// RLN - Reboot's Linker for the Atari Jaguar Console System
-// RLN.C - Application Code
-// Copyright (C) 199x, Allan K. Pratt, 2014 Reboot & Friends
+// RLN - Reboot's Linker for the Atari Jaguar console system
+// Copyright (C) 199x, Allan K. Pratt, 2014-2018 Reboot & Friends
 //
 
 #include "rln.h"
@@ -23,7 +22,7 @@ unsigned sflag = 0;                                   // Output only global symbols
 unsigned vflag = 0;                                    // Verbose flag
 unsigned wflag = 0;                                    // Show warnings flag
 unsigned zflag = 0;                                    // Suppress banner flag
-unsigned pflag = 0, uflag = 0;         // Unimplemented flags
+unsigned pflag = 0, uflag = 0;         // Unimplemented flags (partial link, don't abort on unresolved symbols)
 unsigned hd = 0;                                       // Index of next file handle to fill
 unsigned secalign = 7;                         // Section Alignment (8=phrase)
 unsigned tbase = 0;                                    // TEXT base address
@@ -34,9 +33,7 @@ unsigned dataoffset = 0;                      // COF DATA segment offset
 unsigned bssoffset = 0;                                // COF BSS segment offset
 unsigned displaybanner = 1;                    // Display version banner
 unsigned symoffset = 0;                                // Symbol table offset in output file
-unsigned dosymi = 0;                           // Dosym() processing iterator
 unsigned dbgsymbase = 0;                       // Debug symbol base address
-//unsigned symtrunc = 0;                       // Symbol truncation -i and -ii
 int noheaderflag = 0;                          // No header flag for ABS files
 int hflags;                                                    // Value of the arg to -h option
 int ttype, dtype, btype;                       // Type flag: 0, -1, -2, -3, -4
@@ -54,9 +51,6 @@ struct OFILE * plist = NULL;          // Object image list pointer
 struct OFILE * plast;                          // Last object image list pointer
 struct OFILE * olist = NULL;           // Pointer to first object file in list
 struct OFILE * olast;                          // Pointer to last object file in list
-char obj_fname[16384][FNLEN];          // Object file names
-unsigned obj_segsize[16384][3];                // Object file seg sizes; TEXT,DATA,BSS
-unsigned obj_index = 0;                                // Object file index/count
 char * arPtr[512];
 uint32_t arIndex = 0;
 struct HREC * htable[NBUCKETS];                // Hash table
@@ -77,6 +71,10 @@ struct HREC * LookupHREC(char *);
 char * PathTail(char *);
 void ShowHelp(void);
 void ShowVersion(void);
+int OSTLookup(char * sym);
+int OSTAdd(char * name, int type, long value);
+int ProcessFiles(void);
+int doargs(int argc, char * argv[]);
 
 
 //
@@ -143,7 +141,7 @@ int DoSymbols(struct OFILE * ofile)
        int index;
        int j;
        struct HREC * hptr;
-       unsigned tsoSave, dsoSave, bsoSave;
+       uint32_t tsoSave, dsoSave, bsoSave;
 
        // Point to first symbol record in the object file
        char * symptr = (ofile->o_image + 32
@@ -155,33 +153,9 @@ int DoSymbols(struct OFILE * ofile)
        // Point to end of symbol record in the object file
        char * symend = symptr + ofile->o_header.ssize;
 
-       // Search through object segment size table to accumulated segment sizes to
-       // ensure the correct offsets are used in the resulting COF file.
-       int ssidx = -1;
-       unsigned tsegoffset = 0, dsegoffset = 0, bsegoffset = 0;
-
-       // Search for object file name
-       for(j=0; j<(int)obj_index; j++)
-       {
-               if (!strcmp(ofile->o_name, obj_fname[j]))
-               {
-                       // Object file name found
-                       ssidx = j;
-                       break;
-               }
-
-               // Accumulate segment sizes
-               tsegoffset += obj_segsize[j][0];
-               dsegoffset += obj_segsize[j][1];
-               bsegoffset += obj_segsize[j][2];
-       }
-
-       if (ssidx == -1)
-       {
-               printf("DoSymbols(): Object file missing from obj_fname: %s\n",
-                       ofile->o_name);
-               return 1;
-       }
+       uint32_t tsegoffset = ofile->segBase[TEXT];
+       uint32_t dsegoffset = ofile->segBase[DATA];
+       uint32_t bsegoffset = ofile->segBase[BSS];
 
        // Save segment vars, so we can restore them if needed
        tsoSave = tsegoffset, dsoSave = dsegoffset, bsoSave = bsegoffset;
@@ -224,42 +198,14 @@ int DoSymbols(struct OFILE * ofile)
                                continue;
                        }
 
-                       // Search through object segment size table to obtain segment sizes
-                       // for the object that has the required external/global as a local
-                       // symbol. As each object is interrogated the segment sizes are
-                       // accumulated to ensure the correct offsets are used in the
-                       // resulting COF file. This is effectively 'done again' only as we
-                       // are working with a different object file.
-                       ssidx = -1;
-                       tsegoffset = dsegoffset = bsegoffset = 0;
-
-                       // Search for object filename
-                       for(j=0; j<(int)obj_index; j++)
-                       {
-                               if (!strcmp(hptr->h_ofile->o_name, obj_fname[j]))
-                               {
-                                       ssidx = j;      // Symbol object filename
-                                       break;
-                               }
-
-                               // Accumulate segment sizes
-                               tsegoffset += obj_segsize[j][0];
-                               dsegoffset += obj_segsize[j][1];
-                               bsegoffset += obj_segsize[j][2];
-                       }
-
-                       if (ssidx == -1)
-                       {
-                               printf("DoSymbols(): Object file missing from obj_fname: '%s:%s' symbol: '%s' (%s)\n",
-                                       hptr->h_ofile->o_name, hptr->h_ofile->o_arname,
-                                       symend + index, ofile->o_name);
-                               return 1;
-                       }
+                       tsegoffset = hptr->h_ofile->segBase[TEXT];
+                       dsegoffset = hptr->h_ofile->segBase[DATA];
+                       bsegoffset = hptr->h_ofile->segBase[BSS];
 
                        // Update type with global type
                        type = hptr->h_type;
 
-                       // Remove external flag if absolute
+                       // Remove global flag if absolute
                        if (type == (T_GLBL | T_ABS))
                                type = T_ABS;
 
@@ -294,15 +240,19 @@ int DoSymbols(struct OFILE * ofile)
 
                // Process and update the value dependent on whether the symbol is a
                // debug symbol or not
-               // N.B.: These are currently not supported
+               // N.B.: Debug symbols are currently not supported
                if (type & 0xF0000000)
                {
                        // DEBUG SYMBOL
                        // Set the correct debug symbol base address (TEXT segment)
+#if 0
                        dbgsymbase = 0;
 
                        for(j=0; (unsigned)j<dosymi; j++)
                                dbgsymbase += obj_segsize[j][0];
+#else
+                       dbgsymbase = ofile->segBase[TEXT];
+#endif
 
                        switch (type & 0xFF000000)
                        {
@@ -373,9 +323,6 @@ int DoSymbols(struct OFILE * ofile)
                }
        }
 
-       // Increment dosymi processsing
-       dosymi++;
-
        return 0;
 }
 
@@ -642,8 +589,12 @@ int RelocateSegment(struct OFILE * ofile, int flag)
        unsigned glblreloc;             // Global relocation flag
        unsigned absreloc;              // Absolute relocation flag
        unsigned relreloc;              // Relative relocation flag
+       unsigned wordreloc;             // Relocate word only flag
+       unsigned opreloc;               // Relocate OP data address only flag
        unsigned swcond;                // Switch statement condition
        unsigned relocsize;             // Relocation record size
+       unsigned saveBits;              // OP data leftover bits save
+       unsigned saveBits2;
 
        // If there is no TEXT relocation data for the selected object file segment
        // then update the COF TEXT segment offset allowing for the phrase padding
@@ -721,8 +672,10 @@ int RelocateSegment(struct OFILE * ofile, int flag)
                addr = GetLong(rptr);
                rflg = GetLong(rptr + 4);
                glblreloc = (rflg & 0x00000010 ? 1 : 0);// Set global relocation flag
-               absreloc = (rflg & 0x00000040 ? 1 : 0); // Set absolute relocation flag
-               relreloc = (rflg & 0x000000A0 ? 1 : 0); // Set relative relocation flag
+               absreloc  = (rflg & 0x00000040 ? 1 : 0); // Set absolute relocation flag
+               relreloc  = (rflg & 0x000000A0 ? 1 : 0); // Set relative relocation flag
+               wordreloc = (rflg & 0x00000002 ? 1 : 0); // Set word relocation flag
+               opreloc   = (rflg & 0x00000004 ? 1 : 0); // Set OP relocation flag
 
                // Additional processing required for global relocations
                if (glblreloc)
@@ -739,9 +692,22 @@ int RelocateSegment(struct OFILE * ofile, int flag)
                        newdata = GetLong(ost + ((ssidx - 1) * 12) + 8);
                }
 
-               // Obtain the existing long word segment data and flip words if the
-               // relocation flags indicate it relates to a RISC MOVEI instruction
-               olddata = GetLong(sptr + addr);
+               // Obtain the existing long word (or word) segment data and flip words
+               // if the relocation flags indicate it relates to a RISC MOVEI
+               // instruction
+               olddata = (wordreloc ? GetWord(sptr + addr) : GetLong(sptr + addr));
+
+               // If it's a OP QUAD relocation, get the data out of the DATA bits.
+               // Note that because we can't afford to lose the bottom 3 bits of the
+               // relocation record, we lose 3 off the top--which means the maximum
+               // this can store is $1FFFF8 (vs. $FFFFF8).
+               if (opreloc)
+               {
+                       saveBits2 = (GetLong(sptr + addr + 8) & 0xE0000000) >> 8; // Upper 3 of data addr
+                       saveBits = olddata & 0x7FF;
+                       olddata = (olddata & 0xFFFFF800) >> 11;
+                       olddata |= saveBits2; // Restore upper 3 bits of data addr
+               }
 
                if (rflg & 0x01)
                        olddata = _SWAPWORD(olddata);
@@ -760,7 +726,7 @@ int RelocateSegment(struct OFILE * ofile, int flag)
                                break;
                        case 0x00000400:          // TEXT segment relocation record
                                // SCPCD : the symbol point to a text segment, we should use the textoffset
-                                       newdata = tbase + textoffset + olddata;
+                               newdata = tbase + textoffset + olddata;
 
                                break;
                        case 0x00000600:          // DATA segment relocation record
@@ -791,7 +757,21 @@ int RelocateSegment(struct OFILE * ofile, int flag)
                        if (rflg & 0x01)
                                newdata = _SWAPWORD(newdata);
 
-                       PutLong(sptr + addr, newdata);
+                       if (wordreloc)
+                               PutWord(sptr + addr, newdata);
+                       else if (opreloc)
+                       {
+                               if (vflag > 1)
+                                       printf("OP reloc: oldata=$%X, newdata=$%X\n", olddata, newdata);
+
+                               newdata = ((newdata & 0x00FFFFF8) << 8) | saveBits;
+                               PutLong(sptr + addr, newdata);
+                               // Strip out extraneous data hitchhikers from 2nd phrase...
+                               newdata = GetLong(sptr + addr + 8) & 0x007FFFFF;
+                               PutLong(sptr + addr + 8, newdata);
+                       }
+                       else
+                               PutLong(sptr + addr, newdata);
                }
                else if (relreloc)
                {
@@ -1095,7 +1075,7 @@ int WriteOutputFile(struct OHEADER * header)
        struct OFILE * otemp;                           // Object file pointer
        int i, j;                                                       // Iterators
        char himage[0x168];                                     // Header image (COF = 0xA8)
-       unsigned tsoff, dsoff, bsoff;           // Segment offset values
+       uint32_t tsoff, dsoff, bsoff;           // Segment offset values
        unsigned index, type, value;            // Symbol table index, type and value
        short abstype;                                          // ABS symbol type
        char symbol[14];                                        // Symbol record for ABS files
@@ -1107,11 +1087,11 @@ int WriteOutputFile(struct OHEADER * header)
        if (strchr(ofile, '.') == NULL)
        {
                if (aflag && cflag)
-                       strcat(ofile, ".cof");          // COF files
+                       strcat(ofile, ".cof");          // COF files (a type of abs)
                else if (aflag && !cflag)
                        strcat(ofile, ".abs");          // ABS files
                else
-                       strcat(ofile, ".o");            // Object files (partial linking etc)
+                       strcat(ofile, ".o");            // Object files (partial linking, etc)
        }
 
        FILE * fd = fopen(ofile, "wb");         // Attempt to open output file
@@ -1130,10 +1110,10 @@ int WriteOutputFile(struct OHEADER * header)
 
                // Process each object file segment size to obtain a cumulative segment
                // size for both the TEXT and DATA segments
-               for(i=0; i<(int)obj_index; i++)
+               for(otemp=olist; otemp!=NULL; otemp=otemp->o_next)
                {
-                       dsoff += obj_segsize[i][0];     // Adding TEXT segment sizes
-                       bsoff += obj_segsize[i][0] + obj_segsize[i][1]; // Adding TEXT and DATA segment sizes
+                       dsoff += otemp->segSize[TEXT];
+                       bsoff += otemp->segSize[TEXT] + otemp->segSize[DATA];
                }
 
                // Currently this only builds a COF absolute file. Conditionals and
@@ -1214,18 +1194,20 @@ int WriteOutputFile(struct OHEADER * header)
        }
 
        // Write the header, but not if noheaderflag
-       // Absolute (ABS) header
-       if (!cflag)
+       if (!noheaderflag)
        {
-               if (!noheaderflag)
+               // Absolute (ABS) header
+               if (!cflag)
+               {
                        if (fwrite(himage, 36, 1, fd) != 1)
                                goto werror;
-       }
-       // Absolute (COF) header
-       else
-       {
-               if (fwrite(himage, 168, 1, fd) != 1)
-                       goto werror;
+               }
+               // Absolute (COF) header
+               else
+               {
+                       if (fwrite(himage, 168, 1, fd) != 1)
+                               goto werror;
+               }
        }
 
        // Write the TEXT segment of each object file
@@ -1272,7 +1254,12 @@ int WriteOutputFile(struct OHEADER * header)
                }
        }
 
-       if (!noheaderflag)
+//wha? if (!noheaderflag)
+       // This isn't quite right, but it's closer...
+       // (the l and s flags tell the linker to output local & global symbols
+       //  in the symbol table, so it seems there's some other thing that's a
+       // default set somewhere. Not 100% sure. Setting -s kills -l, BTW...)
+       if (lflag || sflag)
        {
                // Write the symbols table and string table
                // Absolute (COF) symbol/string table
@@ -1336,8 +1323,8 @@ int WriteOutputFile(struct OHEADER * header)
                                case 0x08000000: abstype = (short)ABST_DEFINED | ABST_BSS;                break;
                                case 0x09000000: abstype = (short)ABST_DEFINED | ABST_GLOBAL | ABST_BSS;  break;
                                default:
-                                       printf("warning (WriteOutputFile): ABS, cannot determine symbol type ($%08X)\n", type);
-                                       type = 0;
+                                       printf("warning (WriteOutputFile): ABS, cannot determine symbol type ($%08X) [%s]\n", type, symbol);
+//                                     type = 0;
                                        break;
                                }
 
@@ -1351,10 +1338,9 @@ int WriteOutputFile(struct OHEADER * header)
                }
        }
 
-       // Close the file
        if (fclose(fd))
        {
-               printf("Close error on output file %s\n",ofile);
+               printf("Close error on output file %s\n", ofile);
                return 1;
        }
 
@@ -1508,9 +1494,9 @@ int GetHexValue(char * string, int * value)
 // Create one big .o file from the images already in memory, returning a
 // pointer to an OHEADER. Note that the oheader is just the header for the
 // output (plus some other information). The text, data, and fixups are all
-// still in the ofile images hanging off the global `olist'.
+// still in the ofile images hanging off the global 'olist'.
 //
-struct OHEADER * MakeOutputFile()
+struct OHEADER * MakeOutputObject()
 {
        unsigned tptr, dptr, bptr;      // Bases in runtime model
        int ret = 0;                            // Return value
@@ -1523,65 +1509,45 @@ struct OHEADER * MakeOutputFile()
        // those object files which are unused
        struct OFILE * oprev = NULL;    // Init previous obj file list ptr
        struct OFILE * otemp = olist;   // Set temp pointer to object file list
-       int i = 0;
 
        while (otemp != NULL)
        {
-               // UNUSED !!!!! (it's !O_ARCHIVE, so this code executes.)
-               if (!(otemp->o_flags & O_ARCHIVE))
+               // If the object is unused, discard it...
+               if ((otemp->o_flags & O_USED) == 0)
                {
-                       if ((otemp->o_flags & O_USED) == 0)
+                       if (wflag)
                        {
-                               if (wflag)
-                               {
-                                       printf("Unused object file ");
-                                       WriteARName(otemp);
-                                       printf(" discarded.\n");
-                               }
-
-                               // Drop the entry from the linked list
-                               if (oprev == NULL)
-                                       olist = otemp->o_next;
-                               else
-                                       oprev->o_next = otemp->o_next;
-
-                               // Free the object entry if it's not an archive file
-                               if (!otemp->isArchiveFile)
-                                       free(otemp->o_image);
-
-                               // Also need to remove them from the obj_* tables too :-P
-                               // N.B.: Would probably be worthwhile to remove crap like this
-                               //       and stuff it into the OFILE structure...
-                               if (wflag)
-                                       printf("»-> removing %s... (index == %i, len == %i)\n", obj_fname[i], i, obj_index - 1);
+                               printf("Unused object file ");
+                               WriteARName(otemp);
+                               printf(" discarded.\n");
+                       }
 
-                               int k;
+                       // Drop the entry from the linked list
+                       if (oprev == NULL)
+                               olist = otemp->o_next;
+                       else
+                               oprev->o_next = otemp->o_next;
 
-                               for(k=i; k<obj_index-1; k++)
-                               {
-                                       memcpy(obj_fname[k], obj_fname[k + 1], FNLEN);
-                                       obj_segsize[k][0] = obj_segsize[k + 1][0];
-                                       obj_segsize[k][1] = obj_segsize[k + 1][1];
-                                       obj_segsize[k][2] = obj_segsize[k + 1][2];
-                               }
+                       // Free the object entry if it's not an archive file
+                       if (!otemp->isArchiveFile)
+                               free(otemp->o_image);
+               }
+               else
+               {
+                       // Save accumulated addresses in the object
+                       otemp->segBase[TEXT] = textsize;
+                       otemp->segBase[DATA] = datasize;
+                       otemp->segBase[BSS]  = bsssize;
 
-                               obj_index--;
-                               i--;
-                       }
-                       else
-                       {
-                               // Increment total of segment sizes ensuring requested
-                               // alignment
-                               textsize += (otemp->o_header.tsize + secalign) & ~secalign;
-                               datasize += (otemp->o_header.dsize + secalign) & ~secalign;
-                               bsssize  += (otemp->o_header.bsize + secalign) & ~secalign;
-                               oprev = otemp;
-                       }
+                       // Increment total of segment sizes ensuring requested alignment
+                       textsize += (otemp->o_header.tsize + secalign) & ~secalign;
+                       datasize += (otemp->o_header.dsize + secalign) & ~secalign;
+                       bsssize  += (otemp->o_header.bsize + secalign) & ~secalign;
+                       oprev = otemp;
                }
 
                // Go to next object file list pointer
                otemp = otemp->o_next;
-               i++;
        }
 
        // Update base addresses and inject the symbols _TEXT_E, _DATA_E and _BSS_E
@@ -1602,7 +1568,7 @@ struct OHEADER * MakeOutputFile()
        }
        else
        {
-               // DATA is independant of TEXT
+               // DATA is independent of TEXT
                dbase = dval;
 
                if (!bval)
@@ -1613,6 +1579,7 @@ struct OHEADER * MakeOutputFile()
                        bbase = bval;
        }
 
+       // Inject segment end labels, for C compilers that expect this shite
        OSTAdd("_TEXT_E", 0x05000000, tbase + textsize);
        OSTAdd("_DATA_E", 0x07000000, dbase + datasize);
        OSTAdd("_BSS_E",  0x09000000, bbase + bsssize);
@@ -1634,16 +1601,11 @@ struct OHEADER * MakeOutputFile()
        while (otemp != NULL)
        {
                otemp->o_tbase = tptr;
-
-               // Do rest only for non-ARCHIVE markers
-               if (!(otemp->o_flags & O_ARCHIVE))
-               {
-                       otemp->o_dbase = dptr;
-                       otemp->o_bbase = bptr;
-                       tptr += (otemp->o_header.tsize + secalign) & ~secalign;
-                       dptr += (otemp->o_header.dsize + secalign) & ~secalign;
-                       bptr += (otemp->o_header.bsize + secalign) & ~secalign;
-               }
+               otemp->o_dbase = dptr;
+               otemp->o_bbase = bptr;
+               tptr += (otemp->o_header.tsize + secalign) & ~secalign;
+               dptr += (otemp->o_header.dsize + secalign) & ~secalign;
+               bptr += (otemp->o_header.bsize + secalign) & ~secalign;
 
                // For each symbol, (conditionally) add it to the ost
                // For ARCHIVE markers, this adds the symbol for the file & returns
@@ -1652,27 +1614,8 @@ struct OHEADER * MakeOutputFile()
                if (DoSymbols(otemp))
                        return NULL;
 
-               if (otemp->o_flags & O_ARCHIVE)
-               {
-                       struct OFILE * oNext = otemp->o_next;
-
-                       // Now that the archive is marked, remove it from list
-                       if (oprev == NULL)
-                               olist = otemp->o_next;
-                       else
-                               oprev->o_next = otemp->o_next;
-
-                       if (otemp->o_image && !otemp->isArchiveFile)
-                               free(otemp->o_image);
-
-                       free(otemp);
-                       otemp = oNext;
-               }
-               else
-               {
-                       oprev = otemp;
-                       otemp = otemp->o_next;
-               }
+               oprev = otemp;
+               otemp = otemp->o_next;
        }
 
        // Places all the externs, globals etc into the output symbol table
@@ -1684,7 +1627,7 @@ struct OHEADER * MakeOutputFile()
 
        if (header == NULL)
        {
-               printf("MakeOutputFile: out of memory!\n");
+               printf("MakeOutputObject: out of memory!\n");
                return NULL;
        }
 
@@ -1702,11 +1645,8 @@ struct OHEADER * MakeOutputFile()
        // with the error condition
        for(otemp=olist; otemp!=NULL; otemp=otemp->o_next)
        {
-               if (!(otemp->o_flags & O_ARCHIVE))
-               {
-                       ret |= RelocateSegment(otemp, T_TEXT); // TEXT segment relocations
-                       ret |= RelocateSegment(otemp, T_DATA); // DATA segment relocations
-               }
+               ret |= RelocateSegment(otemp, T_TEXT); // TEXT segment relocations
+               ret |= RelocateSegment(otemp, T_DATA); // DATA segment relocations
        }
 
        // Done with global symbol hash tables
@@ -1920,8 +1860,7 @@ int AddSymbols(struct OFILE * Ofile)
                }
                else if (type == T_GLBL)
                {
-                       // External symbol that is *not* in the current unit
-                       // N.B.: Also, could be common symbol *in* current unit...!
+                       // Global symbol that may or may not be in the current unit
                        hptr = LookupHREC(sstr + index);
 
                        if (hptr != NULL)
@@ -1929,8 +1868,8 @@ int AddSymbols(struct OFILE * Ofile)
                        // Otherwise, *maybe* add to unresolved list
                        else
                        {
-                               // Check to see if this is a common symbol; if so, try to add
-                               // it to the hash list...
+                               // Check to see if this is a common symbol; if so, add it to
+                               // the hash list...
                                if (value != 0)
                                {
                                        // Actually, we need to convert this to a BSS symbol,
@@ -1938,6 +1877,7 @@ int AddSymbols(struct OFILE * Ofile)
                                        // add it to the hash list
                                        uint32_t bssLocation = Ofile->o_header.tsize + Ofile->o_header.dsize + Ofile->o_header.bsize;
                                        Ofile->o_header.bsize += value;
+                                       Ofile->segSize[BSS] += value;
                                        type |= T_BSS;
                                        value = bssLocation;
                                        PutLong(sfix + 4, type);
@@ -1948,9 +1888,9 @@ int AddSymbols(struct OFILE * Ofile)
 
                                        if (AddSymbolToHashList(&htable[GetHash(sstr + index)],
                                                sstr + index, Ofile, value, type))
-                                               return 1;
+                                               return 1;                               // Error if addition failed
                                }
-                               // Check for built-in externals...
+                               // Make sure it's not a built-in external...
                                else if ((strcmp(sstr + index, "_TEXT_E") != 0)
                                        && (strcmp(sstr + index, "_DATA_E") != 0)
                                        && (strcmp(sstr + index, "_BSS_E") != 0))
@@ -2047,7 +1987,7 @@ int DoItem(struct OFILE * obj)
        }
 
        // Check archive name length
-       if (strlen(obj->o_arname) > FNLEN - 1)
+       if (strlen(obj->o_arname) > (FNLEN - 1))
        {
                printf("Archive name too long: %s\n", obj->o_arname);
                return 1;
@@ -2064,45 +2004,42 @@ int DoItem(struct OFILE * obj)
        Ofile->o_flags = obj->o_flags;
        Ofile->o_image = obj->o_image;
        Ofile->isArchiveFile = obj->isArchiveFile;
+       Ofile->segSize[TEXT] = obj->segSize[TEXT];
+       Ofile->segSize[DATA] = obj->segSize[DATA];
+       Ofile->segSize[BSS]  = obj->segSize[BSS];
        char * ptr = obj->o_image;
 
-       // Don't do anything if this is just an ARCHIVE marker, just add the file
-       // to the olist
-       // (Shamus: N.B.: it does no such ARCHIVE thing ATM)
-       if (!(obj->o_flags & O_ARCHIVE))
-       {
-               Ofile->o_header.magic = GetLong(ptr);
-               Ofile->o_header.tsize = GetLong(ptr + 4);
-               Ofile->o_header.dsize = GetLong(ptr + 8);
-               Ofile->o_header.bsize = GetLong(ptr + 12);
-               Ofile->o_header.ssize = GetLong(ptr + 16);
-               Ofile->o_header.absrel.reloc.tsize = GetLong(ptr + 24);
-               Ofile->o_header.absrel.reloc.dsize = GetLong(ptr + 28);
-
-               // Round BSS off to alignment boundary
-               Ofile->o_header.bsize = (Ofile->o_header.bsize + secalign) & ~secalign;
+       Ofile->o_header.magic = GetLong(ptr);
+       Ofile->o_header.tsize = GetLong(ptr + 4);
+       Ofile->o_header.dsize = GetLong(ptr + 8);
+       Ofile->o_header.bsize = GetLong(ptr + 12);
+       Ofile->o_header.ssize = GetLong(ptr + 16);
+       Ofile->o_header.absrel.reloc.tsize = GetLong(ptr + 24);
+       Ofile->o_header.absrel.reloc.dsize = GetLong(ptr + 28);
 
-               if ((Ofile->o_header.dsize & 7) && wflag)
-               {
-                       printf("Warning: data segment size of ");
-                       WriteARName(Ofile);
-                       printf(" is not a phrase multiple\n");
-               }
+       // Round BSS off to alignment boundary (??? isn't this already done ???)
+       Ofile->o_header.bsize = (Ofile->o_header.bsize + secalign) & ~secalign;
 
-               // Check for odd segment sizes
-               if ((Ofile->o_header.tsize & 1) || (Ofile->o_header.dsize & 1)
-                       || (Ofile->o_header.bsize & 1))
-               {
-                       printf("Error: odd-sized segment in ");
-                       WriteARName(Ofile);
-                       printf("; link aborted.\n");
-                       return 1;
-               }
+       if ((Ofile->o_header.dsize & 7) && wflag)
+       {
+               printf("Warning: data segment size of ");
+               WriteARName(Ofile);
+               printf(" is not a phrase multiple\n");
+       }
 
-               if (AddSymbols(Ofile))
-                       return 1;
+       // Check for odd segment sizes
+       if ((Ofile->o_header.tsize & 1) || (Ofile->o_header.dsize & 1)
+               || (Ofile->o_header.bsize & 1))
+       {
+               printf("Error: odd-sized segment in ");
+               WriteARName(Ofile);
+               printf("; link aborted.\n");
+               return 1;
        }
 
+       if (AddSymbols(Ofile))
+               return 1;
+
        // Add this file to the olist
        if (olist == NULL)
                olist = Ofile;
@@ -2229,7 +2166,7 @@ char * PathTail(char * name)
 //
 // Add input file to processing list
 //
-int AddToProcessingList(char * ptr, char * fname, char * arname, uint8_t arFile)
+int AddToProcessingList(char * ptr, char * fname, char * arname, uint8_t arFile, uint32_t tSize, uint32_t dSize, uint32_t bSize)
 {
        if (plist == NULL)
        {
@@ -2250,19 +2187,19 @@ int AddToProcessingList(char * ptr, char * fname, char * arname, uint8_t arFile)
                return 1;
        }
 
+       // Discard paths from filenames...
        fname = PathTail(fname);
        arname = PathTail(arname);
 
-       if (strlen(fname) > FNLEN - 1)
+       // Check for filename length errors...
+       if (strlen(fname) > (FNLEN - 1))
        {
-               // Error on excessive filename length
                printf("File name too long: %s (sorry!)\n", fname);
                return 1;
        }
 
-       if (strlen(arname) > FNLEN - 1)
+       if (strlen(arname) > (FNLEN - 1))
        {
-               // Error on excessive filename length
                printf("AR file name too long: %s (sorry!)\n", arname);
                return 1;
        }
@@ -2273,6 +2210,9 @@ int AddToProcessingList(char * ptr, char * fname, char * arname, uint8_t arFile)
        plast->o_flags = (arFile ? 0 : O_USED); // File is used if NOT in archive
        plast->o_next = NULL;                           // Initialise next record pointer
        plast->isArchiveFile = arFile;          // Shamus: Temp until can sort it out
+       plast->segSize[TEXT] = tSize;
+       plast->segSize[DATA] = dSize;
+       plast->segSize[BSS]  = bSize;
 
        return 0;                                                       // Return without errors
 }
@@ -2286,8 +2226,8 @@ int AddToProcessingList(char * ptr, char * fname, char * arname, uint8_t arFile)
 // Image size for include files is:
 // Header ....... 32 bytes
 // Data ......... dsize
-// Sym Fixups ... 2 * 12 bytes
-// Symbol Size .. 4 bytes (Value to include symbols and terminating null)
+// Sym fixups ... 2 * 12 bytes
+// Symbol size .. 4 bytes (Value to include symbols and terminating null)
 // Symbols ...... (strlen(sym1) + 1) + (strlen(sym2) + 1)
 // Terminate .... 4 bytes (0x00000000)
 //
@@ -2296,6 +2236,7 @@ int LoadInclude(char * fname, int handle, char * sym1, char * sym2, int segment)
        char * ptr, * sptr;
        int i;
        unsigned symtype = 0;
+       uint32_t tSize = 0, dSize = 0, bSize = 0;
 
        long fsize = FileSize(handle);          // Get size of include file
        long dsize = (fsize + secalign) & ~secalign;    // Align size to boundary
@@ -2323,8 +2264,6 @@ int LoadInclude(char * fname, int handle, char * sym1, char * sym2, int segment)
 
        close(handle);
 
-       strcpy(obj_fname[obj_index], PathTail(fname));
-
        // Build this image's dummy header
        PutLong(ptr, 0x00000107);              // Magic number
 
@@ -2333,22 +2272,16 @@ int LoadInclude(char * fname, int handle, char * sym1, char * sym2, int segment)
                PutLong(ptr+4, dsize);             // Text size
                PutLong(ptr+8, 0L);                // Data size
                symtype = 0x05000000;
-               obj_segsize[obj_index][0] = dsize;
-               obj_segsize[obj_index][1] = 0;
-               obj_segsize[obj_index][2] = 0;
+               tSize = dsize;
        }
        else
        {
                PutLong(ptr+4, 0L);                // Text size
                PutLong(ptr+8, dsize);             // Data size
                symtype = 0x07000000;
-               obj_segsize[obj_index][0] = 0;
-               obj_segsize[obj_index][1] = dsize;
-               obj_segsize[obj_index][2] = 0;
+               dSize = dsize;
        }
 
-       obj_index++;                           // Increment object count
-
        PutLong(ptr+12, 0L);                   // BSS size
        PutLong(ptr+16, 24);                   // Symbol table size
        PutLong(ptr+20, 0L);                   // Entry point
@@ -2386,7 +2319,7 @@ int LoadInclude(char * fname, int handle, char * sym1, char * sym2, int segment)
 
        PutLong(sptr, 0L);                     // Terminating long for object file
 
-       return AddToProcessingList(ptr, fname, nullStr, 0);
+       return AddToProcessingList(ptr, fname, nullStr, 0, tSize, dSize, bSize);
 }
 
 
@@ -2399,6 +2332,8 @@ int LoadInclude(char * fname, int handle, char * sym1, char * sym2, int segment)
 //
 int LoadObject(char * fname, int fd, char * ptr)
 {
+       uint32_t tSize = 0, dSize = 0, bSize = 0;
+
        if (ptr == NULL)
        {
                long size = FileSize(fd);
@@ -2422,19 +2357,14 @@ int LoadObject(char * fname, int fd, char * ptr)
                        return 1;
                }
 
-               // SCPCD: get the name of the file instead of all pathname
-               strcpy(obj_fname[obj_index], PathTail(fname));
-               obj_segsize[obj_index][0] = (GetLong(ptr + 4) + secalign) & ~secalign;
-               obj_segsize[obj_index][1] = (GetLong(ptr + 8) + secalign) & ~secalign;
-               obj_segsize[obj_index][2] = (GetLong(ptr + 12) + secalign) & ~secalign;
-               obj_index++;
-
-               close(fd);                                            // Close file
+               tSize = (GetLong(ptr + 4)  + secalign) & ~secalign;
+               dSize = (GetLong(ptr + 8)  + secalign) & ~secalign;
+               bSize = (GetLong(ptr + 12) + secalign) & ~secalign;
+               close(fd);
        }
 
        // Now add this image to the list of pending ofiles (plist)
-       // This routine is shared by LoadInclude after it builds the image
-       return AddToProcessingList(ptr, fname, nullStr, 0);
+       return AddToProcessingList(ptr, fname, nullStr, 0, tSize, dSize, bSize);
 }
 
 
@@ -2518,7 +2448,8 @@ int LoadArchive(char * fname, int fd)
                }
 
                // Check to see if a long filename was requested
-               if (objName[0] == 0x20)
+               // N.B.: " " is for GNU archives, and "/" is for BSD archives
+               if ((objName[0] == 0x20) || (objName[0] == '/'))
                {
                        uint32_t fnSize = atoi(objName + 1);
 
@@ -2548,13 +2479,11 @@ int LoadArchive(char * fname, int fd)
                                objName[lastChar] = 0;
 
 //printf("Processing object \"%s\" (size == %i, obj_index == %i)...\n", objName, atoi(objSize), obj_index);
-                       strcpy(obj_fname[obj_index], objName);
-                       obj_segsize[obj_index][0] = (GetLong(ptr + 60 + 4) + secalign) & ~secalign;
-                       obj_segsize[obj_index][1] = (GetLong(ptr + 60  + 8) + secalign) & ~secalign;
-                       obj_segsize[obj_index][2] = (GetLong(ptr + 60  + 12) + secalign) & ~secalign;
-                       obj_index++;
+                       uint32_t tSize = (GetLong(ptr + 60 + 4)  + secalign) & ~secalign;
+                       uint32_t dSize = (GetLong(ptr + 60 + 8)  + secalign) & ~secalign;
+                       uint32_t bSize = (GetLong(ptr + 60 + 12) + secalign) & ~secalign;
 
-                       if (AddToProcessingList(ptr + 60, objName, fname, 1))
+                       if (AddToProcessingList(ptr + 60, objName, fname, 1, tSize, dSize, bSize))
                                return 1;
                }
 
@@ -2952,8 +2881,8 @@ int doargs(int argc, char * argv[])
                                // handle -i (Truncation)
                                else
                                {
-                                       if (strlen(isym) > 7)
-                                               isym[7] = '\0';
+                                       if (strlen(isym) > 8)
+                                               isym[8] = '\0';
                                }
 
                                // Place include files in the DATA segment only
@@ -3092,9 +3021,15 @@ void ShowVersion(void)
 {
        if (displaybanner)// && vflag)
        {
-               printf("\nReboot's Linker for Atari Jaguar\n");
-               printf("Copyright (c) 199x Allan K. Pratt, 2014 Reboot\n");
-               printf("V%i.%i.%i %s (%s)\n\n", MAJOR, MINOR, PATCH, __DATE__, PLATFORM);
+               printf(
+               "      _\n"
+               " _ __| |_ ___\n"
+               "| '__| | '_  \\\n"
+               "| |  | | | | |\n"
+               "|_|  |_|_| |_|\n"
+               "\nReboot's Linker for Atari Jaguar\n"
+               "Copyright (c) 199x Allan K. Pratt, 2014-2018 Reboot\n"
+               "V%i.%i.%i %s (%s)\n\n", MAJOR, MINOR, PATCH, __DATE__, PLATFORM);
        }
 }
 
@@ -3118,10 +3053,11 @@ void ShowHelp(void)
        printf("   -d                      wait for key after link\n");
        printf("   -e                      output COF absolute file\n");
        printf("   -g                      output source-level debugging\n");
-       printf("   -i <fname> <label>      incbin <fname> and set <label>\n");
+       printf("   -i <fname> <label>      incbin <fname> and set <label> (trunc to 8 chars)\n");
+       printf("   -ii <fname> <label>     incbin <fname> and set <label> (no truncation)\n");
        printf("   -l                      add local symbols\n");
        printf("   -m                      produce load symbols map\n");
-       printf("   -n                      output no file header to .abs file\n");
+       printf("   -n                      output no file header to absolute file\n");
        printf("   -o <fname>              set output name\n");
        printf("   -r<size>                section alignment size\n");
        printf("                           w: word (2 bytes)\n");
@@ -3129,7 +3065,7 @@ void ShowHelp(void)
        printf("                           p: phrase (8 bytes, default alignment)\n");
        printf("                           d: double phrase (16 bytes)\n");
        printf("                           q: quad phrase (32 bytes)\n");
-       printf("   -s                      output only global symbols\n");
+       printf("   -s                      output only global symbols (supresses -l)\n");
        printf("   -u                      allow unresolved symbols (experimental)\n");
        printf("   -v                      set verbose mode\n");
        printf("   -w                      show linker warnings\n");
@@ -3144,7 +3080,6 @@ void ShowHelp(void)
 void ExitLinker(void)
 {
        char tempbuf[128];
-       char * c;
 
        // Display link status if verbose mode
        if (vflag)
@@ -3154,7 +3089,7 @@ void ExitLinker(void)
        if (waitflag)
        {
                printf("\nPress the [RETURN] key to continue. ");
-               c = fgets(tempbuf, 128, stdin);
+               char * c = fgets(tempbuf, 128, stdin);
        }
 
        exit(errflag);
@@ -3163,14 +3098,10 @@ void ExitLinker(void)
 
 int main(int argc, char * argv[])
 {
-       char * s = NULL;                                // String pointer for "getenv"
-       struct HREC * utemp;                    // Temporary hash record pointer
-       struct OHEADER * header;                // Pointer to output header structure
-
        cmdlnexec = argv[0];                    // Obtain executable name
-       s = getenv("RLNPATH");
+       char * s = getenv("RLNPATH");   // Attempt to obtain env variable
 
-       if (s)                                                  // Attempt to obtain env variable
+       if (s)
                strcpy(libdir, s);                      // Store it if found
 
        // Initialize some vars
@@ -3184,9 +3115,24 @@ int main(int argc, char * argv[])
                ExitLinker();
        }
 
+       // Check to see if include paths actually exist
+       if (strlen(libdir) > 0)
+       {
+               DIR * test = opendir(libdir);
+
+               if (test == NULL)
+               {
+                       printf("Invalid include path: %s\n", libdir);
+                       errflag = 1;
+                       ExitLinker();
+               }
+
+               closedir(test);
+       }
+
        if (!zflag && !vflag)
        {
-               ShowVersion();                  // Display version information
+               ShowVersion();                          // Display version information
                versflag = 1;                           // We've dumped the version banner
        }
 
@@ -3219,7 +3165,7 @@ int main(int argc, char * argv[])
                // Don't list them if two -u's or more
                if (uflag < 2)
                {
-                       utemp = unresolved;
+                       struct HREC * utemp = unresolved;
 
                        while (utemp != NULL)
                        {
@@ -3237,8 +3183,8 @@ int main(int argc, char * argv[])
                }
        }
 
-       // Make one output file from input objs
-       header = MakeOutputFile();
+       // Make one output object from input objects
+       struct OHEADER * header = MakeOutputObject();
 
        if (header == NULL)
        {
@@ -3249,27 +3195,20 @@ int main(int argc, char * argv[])
        // Partial linking
        if (pflag)
        {
-               printf("TO DO:Partial linking\n");
+               printf("TO DO: Partial linking\n");
                errflag = 1;
        }
        // Relocatable linking
        else if (!aflag)
        {
-               printf("TO DO:Relocatable linking\n");
+               printf("TO DO: Relocatable linking\n");
                errflag = 1;
        }
        // Absolute linking
        else
        {
                if (vflag)
-               {
-                       printf("Absolute linking ");
-
-                       if (cflag)
-                               printf("(COF)\n"); 
-                       else
-                               printf("(ABS)\n");
-               }
+                       printf("Absolute linking (%s)\n", (cflag ? "COF" : "ABS"));
 
                if (vflag > 1)
                        printf("Header magic is 0x%04X\n", (unsigned int)header->magic);