+ struct HREC * uptr;
+
+ // Process the unresolved symbols list. This may involve pulling in symbols
+ // from any included .a units. Such units are lazy linked by default; we
+ // generally don't want everything they provide, just what's referenced.
+ for(uptr=unresolved; uptr!=NULL; )
+ {
+ if (vflag > 1)
+ printf("LookupHREC(%s) => ", uptr->h_sym);
+
+ struct HREC * htemp = LookupHREC(uptr->h_sym);
+
+ if (htemp != NULL)
+ {
+ // Found it in the symbol table!
+ if (vflag > 1)
+ printf("%s in %s (=$%06X)\n", (isglobal(htemp->h_type) ? "global" : "common"), htemp->h_ofile->o_name, htemp->h_value);
+
+ // Mark the .o unit that the symbol is in as seen & remove from the
+ // unresolved list
+ htemp->h_ofile->o_flags |= O_USED;
+ uptr = RemoveUnresolvedSymbol(uptr);
+ }
+ else
+ {
+ if (vflag > 1)
+ printf("NULL\n");
+
+ // Check to see if the unresolved symbol is on the AR symbol list.
+ htemp = LookupARHREC(uptr->h_sym);
+
+ // If the unresolved symbol is in a .o unit that is unused, we can
+ // drop it; same if the unresolved symbol is in the exported AR
+ // symbol list. Otherwise, go to the next unresolved symbol.
+ if (!(uptr->h_ofile->o_flags & O_USED) || (htemp != NULL))
+ uptr = RemoveUnresolvedSymbol(uptr);
+ else
+ uptr = uptr->h_next;
+
+ // Now that we've possibly deleted the symbol from unresolved list
+ // that was also in the AR list, we add the symbols from this .o
+ // unit to the symbol table, mark the .o unit as used, and restart
+ // scanning the unresolved list as there is a good possibility that
+ // the symbols in the unit we're adding has unresolved symbols as
+ // well.
+ if (htemp != NULL)
+ {
+ htemp->h_ofile->o_flags |= O_USED;
+ AddSymbols(htemp->h_ofile);
+ uptr = unresolved;
+ }
+ }
+ }
+
+ // Show files used if the user requests it.
+ if (vflag > 1)
+ {
+ printf("Files used:\n");
+ struct OFILE * filePtr = olist;
+
+ while (filePtr != NULL)
+ {
+ if (filePtr->o_flags & O_USED)
+ {
+ printf(" %s%s%s\n", filePtr->o_name, (filePtr->isArchiveFile ? ":" : ""), (filePtr->isArchiveFile ? filePtr->o_arname : nullStr));
+ }
+
+ filePtr = filePtr->o_next;
+ }
+ }
+
+ return 0;
+}
+
+
+//
+// Extract filename from path
+//
+char * PathTail(char * name)
+{
+ // Find last occurance of PATH_DELIMETER
+ char * temp = strrchr(name, PATH_DELIMITER);
+
+ // Return what was passed in if path delimiter was not found
+ if (temp == NULL)
+ return name;
+
+ return temp + 1;
+}
+
+
+//
+// Add input file to processing list
+//
+int AddToProcessingList(char * ptr, char * fname, char * arname, uint8_t arFile, uint32_t tSize, uint32_t dSize, uint32_t bSize)
+{
+ if (plist == NULL)
+ {
+ // First time object record allocation
+ plist = new_ofile();
+ plast = plist;
+ }
+ else
+ {
+ // Next object record allocation
+ plast->o_next = new_ofile();
+ plast = plast->o_next;
+ }
+
+ if (plast == NULL)
+ {
+ printf("Out of memory.\n"); // Error if memory allocation fails
+ return 1;
+ }
+
+ // Discard paths from filenames...
+ fname = PathTail(fname);
+ arname = PathTail(arname);
+
+ // Check for filename length errors...
+ if (strlen(fname) > (FNLEN - 1))
+ {
+ printf("File name too long: %s (sorry!)\n", fname);
+ return 1;
+ }
+
+ if (strlen(arname) > (FNLEN - 1))
+ {
+ printf("AR file name too long: %s (sorry!)\n", arname);
+ return 1;
+ }
+
+ strcpy(plast->o_name, fname); // Store filename sans path
+ strcpy(plast->o_arname, arname); // Store archive name sans path
+ plast->o_image = ptr; // Store data pointer
+ 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
+}
+
+
+//
+// Process in binary include files and add them to the processing list. This
+// routine takes in the binary file and creates an 'object' file in memory.
+// Sym1/Sym2 point to the start and end of data.
+//
+// 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)
+// Symbols ...... (strlen(sym1) + 1) + (strlen(sym2) + 1)
+// Terminate .... 4 bytes (0x00000000)
+//
+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
+ int sym1len = strlen(sym1) + 1; // Get sym1 length + null termination
+ int sym2len = strlen(sym2) + 1; // Get sym2 length + null termination
+ long size = 32 + dsize + 24 + 4 + sym1len + sym2len + 4;
+
+ // Use calloc so the header & fixups initialize to zero
+ // Allocate object image memory
+ if ((ptr = calloc(size, 1)) == NULL)
+ {
+ printf("Out of memory while including %s\n", fname);
+ close(handle);
+ return 1;
+ }
+
+ // Read in binary data
+ if (read(handle, ptr + 32, fsize) != fsize)
+ {
+ printf("File read error on %s\n", fname);
+ close(handle);
+ free(ptr);
+ return 1;
+ }
+
+ close(handle);
+
+ // Build this image's dummy header
+ PutLong(ptr, 0x00000107); // Magic number
+
+ if (segment)
+ {
+ PutLong(ptr+4, dsize); // Text size
+ PutLong(ptr+8, 0L); // Data size
+ symtype = 0x05000000;
+ tSize = dsize;
+ }
+ else
+ {
+ PutLong(ptr+4, 0L); // Text size
+ PutLong(ptr+8, dsize); // Data size
+ symtype = 0x07000000;
+ dSize = dsize;
+ }
+
+ PutLong(ptr+12, 0L); // BSS size
+ PutLong(ptr+16, 24); // Symbol table size
+ PutLong(ptr+20, 0L); // Entry point
+ PutLong(ptr+24, 0L); // TEXT relocation size
+ PutLong(ptr+28, 0L); // DATA relocation size
+
+ sptr = ptr + 32 + dsize; // Set sptr to symbol table location
+
+ PutLong(sptr, 4L); // String offset of symbol1
+ PutLong(sptr+4, symtype); // Symbol type
+ PutLong(sptr+8, 0x00000000); // Symbol has no value (START)
+ PutLong(sptr+12, 4L + (sym2len - 1)); // String offset of symbol2
+ PutLong(sptr+16, symtype); // Symbol type
+ PutLong(sptr+20, dsize); // Symbol is data size (END)
+
+ sptr = ptr + 32 + dsize + 24; // Set sptr to symbol table size loc
+
+ PutLong(sptr, sym1len + 4L); // Size of symbol table
+
+ sptr = ptr + 32 + dsize + 24 + 4; // Set sptr to symbol table location
+
+ for(i=0; i<(sym1len-1); i++) // Write symbol1 to string table
+ sptr[i] = *sym1++;
+
+ sptr += (sym1len - 1); // Step past symbol string
+ *sptr = '\0'; // Terminate symbol string
+ sptr += 1; // Step past termination
+
+ for(i=0; i<(sym2len-1); i++) // Write symbol2 to string table
+ sptr[i] = *sym2++;
+
+ sptr += (sym2len - 1); // Step past symbol string
+ *sptr = '\0'; // Terminate symbol string
+ sptr += 1; // Step past termination
+
+ PutLong(sptr, 0L); // Terminating long for object file
+
+ return AddToProcessingList(ptr, fname, nullStr, 0, tSize, dSize, bSize);
+}
+
+
+//
+// Takes a file name, gets in its image, puts it on plist. The image may
+// already be in memory: If so, the ptr arg is non-null. If so, the file is
+// already closed. Note that the file is already open (from DoFile()). RETURNS
+// a pointer to the OFILE structure for this file, so you can diddle its flags
+// (DoFile sets O_USED for files on the command line).
+//
+int LoadObject(char * fname, int fd, char * ptr)
+{
+ uint32_t tSize = 0, dSize = 0, bSize = 0;
+
+ if (ptr == NULL)
+ {
+ long size = FileSize(fd);
+
+ // Allocate memory for file data
+ ptr = malloc(size);
+
+ if (ptr == NULL)
+ {
+ printf("Out of memory while processing %s\n", fname);
+ close(fd);
+ return 1;
+ }
+
+ // Read in file data
+ if (read(fd, ptr, size) != size)
+ {
+ printf("File read error on %s\n", fname);
+ close(fd);
+ free(ptr);
+ return 1;
+ }
+
+ 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)
+ return AddToProcessingList(ptr, fname, nullStr, 0, tSize, dSize, bSize);
+}
+
+uint32_t SymTypeAlcToAout(uint32_t alcType)
+{
+ uint32_t type = T_UNDF;
+
+ // Symbol type mappings here are derived from comparing Alcyon and BSD
+ // object files generated by MADMAC using the "size" utility from jag_utils
+ // (https://github.com/cubanismo/jag_utils) and the old PC/DOS Atari SDK.
+ //
+ // In BSD/a.out:
+ //
+ // 1) text | global text == text relocatable symbol in this file
+ // 2) data | global data == data relocatable symbol in this file
+ // 3) BSS | global BSS == bss relocatable symbol in this file
+ // 4) ABS | global ABS == non-relocatable symbol in this file
+ // 4) <none> | global <none> == undefined global symbol (extern)
+ //
+ // In DRI/Alcyon:
+ //
+ // 1) Everything seems to be marked defined.
+ // 2) There is an explicit "external" bit. It appears to be mutually
+ // exclusive with the "global" bit, at least in MADMAC's output.
+ // 3) There are separate "equated" and "equated reg" type bits that
+ // both represent ABS/non-relocatable values.
+ if ((alcType & ALCSYM_EQUATED) ||
+ (alcType & ALCSYM_EQUATED_REG))
+ type |= T_ABS;
+ else if (alcType & ALCSYM_TEXT)
+ type |= T_TEXT;
+ else if (alcType & ALCSYM_DATA)
+ type |= T_DATA;
+ else if (alcType & ALCSYM_BSS)
+ type |= T_BSS;
+
+ if ((alcType & ALCSYM_GLOBAL) ||
+ (alcType & ALCSYM_EXTERN))
+ type |= T_GLBL;
+
+ return type;
+}
+
+int LoadAlcyon(char * fname, int fd)
+{
+ char *ptr, *sptr, *aout, *saout, *traout, *strPtr;
+ char *trelptr, *drelptr, *relend;
+ struct ALCHEADER hdr;
+ struct ALCSYM *alcSyms;
+ long size = FileSize(fd);
+ size_t symStrLen;
+ size_t strOff;
+ uint32_t numSyms, numTRel, numDRel, i, j;
+
+ // Validate the file is at least large enough to contain a valid header
+ if (size < 0x1c)
+ {
+ printf("Alcyon object file %s too small to contain header\n", fname);
+ return 1;
+ }
+
+ // Allocate memory for file data
+ ptr = malloc(size);
+
+ if (ptr == NULL)
+ {
+ printf("Out of memory while processing %s\n", fname);
+ close(fd);
+ return 1;
+ }
+
+ // Read in file data
+ if (read(fd, ptr, size) != size)
+ {
+ printf("File read error on %s\n", fname);
+ close(fd);
+ free(ptr);
+ return 1;
+ }
+
+ close(fd);
+
+ hdr.magic = GetWord(ptr);
+ hdr.tsize = GetLong(ptr + 2);
+ hdr.dsize = GetLong(ptr + 6);
+ hdr.bsize = GetLong(ptr + 10);
+ hdr.ssize = GetLong(ptr + 14);
+
+ // Construct a BSD-style/aout object file in memory from the Alcyon data
+ numSyms = hdr.ssize / 14;
+
+ alcSyms = calloc(numSyms, sizeof(*alcSyms));
+ if (alcSyms == NULL)
+ {
+ printf("Out of memory while processing %s\n", fname);
+ free(ptr);
+ return 1;
+ }
+
+ sptr = ptr + 0x1c + hdr.tsize + hdr.dsize;
+ trelptr = sptr + hdr.ssize;
+ drelptr = trelptr + hdr.tsize;
+ relend = drelptr + hdr.dsize;
+
+ if (relend - ptr > size)
+ {
+ printf("Alcyon object file %s truncated: Header wants %ldB, file is %ldB\n",
+ fname, relend - ptr, size);
+ return 1;
+ }
+
+ for (i = 0, symStrLen = 0; i < numSyms; i++)
+ {
+ memcpy(alcSyms[i].name, sptr, 8);
+ alcSyms[i].type = GetWord(sptr + 8);
+ alcSyms[i].value = GetLong(sptr + 10);
+ symStrLen += strnlen((char *)alcSyms[i].name, 8) + 1;
+ sptr += 14;
+ }
+
+ for (i = 0, numTRel = 0; trelptr + i < drelptr; i += 2)
+ {
+ uint16_t rel = GetWord(trelptr + i);
+ if ((rel != ALCREL_ABS) &&
+ (rel != ALCREL_LONG))
+ numTRel++;
+ }
+
+ for (i = 0, numDRel = 0; drelptr + i < relend; i += 2)
+ {
+ uint16_t rel = GetWord(drelptr + i);
+ if ((rel != ALCREL_ABS) &&
+ (rel != ALCREL_LONG))
+ numDRel++;
+ }
+
+ aout = malloc(32 + /* header */
+ hdr.tsize +
+ hdr.dsize +
+ numTRel * 8 + /* Text section relocations */
+ numDRel * 8 + /* Data section relocations */
+ numSyms * 12 + /* symbol table */
+ 4 + symStrLen + /* string table size + strings */
+ 4 /* NULL-terminator for file */);
+ if (aout == NULL)
+ {
+ printf("Out of memory while processing %s\n", fname);
+ free(alcSyms);
+ free(ptr);
+ return 1;
+ }
+
+ // Construct the BSD/a.out header.
+ PutLong(aout, 0x00000107); // Magic number
+
+ PutLong(aout+4, hdr.tsize); // Text size
+ PutLong(aout+8, hdr.dsize); // Data size
+ PutLong(aout+12, hdr.bsize); // BSS size
+ PutLong(aout+16, numSyms * 12); // Symbol table size
+ PutLong(aout+20, 0L); // Entry point
+
+ PutLong(aout+24, numTRel * 8); // TEXT relocation size
+ PutLong(aout+28, numDRel * 8); // DATA relocation size
+
+ // Copy the raw text and data segments
+ memcpy(aout + 32, ptr + 0x1c, hdr.tsize);
+ memcpy(aout + 32 + hdr.tsize, ptr + 0x1c + hdr.tsize, hdr.dsize);
+
+ // Set traout to the start of the relocation tables
+ traout = aout + 32 + hdr.tsize + hdr.dsize;
+
+ // Set saout to symbol table location
+ saout = traout + numTRel * 8 + numDRel * 8 ;
+
+ // Convert the text and data relocations to a.out format
+ for (i = 0; trelptr + i < relend; i += 2)
+ {
+ uint16_t rel = GetWord(trelptr + i);
+ uint16_t relFlags = rel & 7;
+ uint32_t aoutflags = BSDREL_ABS;
+ uint32_t valoffset = 0;
+ char *const valaddr = aout + 32 + i;
+ const uint32_t reladdr = (trelptr + i >= drelptr) ? i - hdr.tsize : i;
+
+ if (relFlags == ALCREL_LONG)
+ {
+ i += 2;
+ rel = GetWord(trelptr + i);
+ relFlags = rel & 7;
+ }
+ else
+ {
+ aoutflags |= BSDREL_WORD;
+ }
+
+ if (relFlags == ALCREL_ABS)
+ continue;
+
+ switch (relFlags) {
+ case ALCREL_EXTPCREL:
+ aoutflags &= ~BSDREL_ABS;
+ aoutflags |= BSDREL_PCREL;
+ /* Fall through */
+ case ALCREL_EXTABS:
+ aoutflags |= BSDREL_GLOBAL;
+ aoutflags |= (ALCREL_SYMIDX(rel) << BSDREL_SYMIDX_SHIFT);
+ break;
+ case ALCREL_TEXT:
+ aoutflags |= BSDREL_SEG_TEXT;
+ break;
+ case ALCREL_DATA:
+ aoutflags |= BSDREL_SEG_DATA;
+ valoffset = hdr.tsize;
+ break;
+ case ALCREL_BSS:
+ aoutflags |= BSDREL_SEG_BSS;
+ valoffset = hdr.tsize + hdr.dsize;
+ break;
+
+ default:
+ printf("Invalid Alcyon relocation flags: 0x%02x\n", relFlags);
+ free(alcSyms);
+ free(ptr);
+ free(aout);
+ return 1;
+ }
+
+ if (valoffset != 0)
+ {
+ if (aoutflags & BSDREL_WORD)
+ {
+ valoffset += GetWord(valaddr);
+ PutWord(valaddr, (uint16_t)valoffset);
+ }
+ else
+ {
+ valoffset += GetLong(valaddr);
+ PutLong(valaddr, valoffset);
+ }
+ }
+
+ PutLong(traout, reladdr);
+ PutLong(traout+4, aoutflags);
+ traout += 8;
+ }
+
+ // Done with the Alcyon data.
+ free(ptr);
+ ptr = NULL;
+ sptr = NULL;
+
+ // Set strPtr to string table location and write string table size
+ strPtr = saout + numSyms * 12;
+ PutLong(strPtr, 4 + symStrLen);
+
+ for (i = 0, strOff = 4; i < numSyms; i++)
+ {
+ PutLong(saout, strOff); // String offset of symbol
+ PutLong(saout+4, SymTypeAlcToAout(alcSyms[i].type)); // Symbol type
+ PutLong(saout+8, alcSyms[i].value); // Symbol value
+ saout += 12;
+
+ for (j = 0; j < 8 && alcSyms[i].name[j] != '\0'; j++)
+ *(strPtr + strOff + j) = alcSyms[i].name[j];
+ strOff += j; // Step past string
+ *(strPtr + strOff) = '\0'; // Terminate symbol string
+ strOff++; // Step past termination
+ }
+
+ PutLong(strPtr + strOff, 0L); // Terminating long for object file
+
+ // Done with the Alcyon symbol table.
+ free(alcSyms);
+
+ // Now add this image to the list of pending ofiles (plist)
+ return AddToProcessingList(aout, fname, nullStr, 0, hdr.tsize, hdr.dsize, hdr.bsize);
+}
+
+//
+// What it says on the tin: check for a .o suffix on the passed in string
+//
+uint8_t HasDotOSuffix(char * s)
+{
+ char * temp = strrchr(s, '.');
+
+ if ((temp == NULL) || (strncmp(temp, ".o", 2) != 0))
+ return 0;
+
+ return 1;
+}
+
+
+//
+// Process an ar archive file (*.a)
+//
+int LoadArchive(char * fname, int fd)
+{
+ // Read in the archive file to memory and process
+ long size = FileSize(fd);
+ char * ptr = malloc(size);
+ char * endPtr = ptr + size;
+ char * longFilenames = NULL;
+
+ if (ptr == NULL)
+ {
+ printf("Out of memory while processing %s\n", fname);
+ close(fd);
+ return 1;
+ }
+
+ if (read(fd, ptr, size) != size)
+ {
+ printf("File read error on %s\n", fname);
+ close(fd);
+ free(ptr);
+ return 1;
+ }
+
+ close(fd);
+
+ // Save the pointer for later...
+ arPtr[arIndex++] = ptr;
+ char objName[FNLEN];
+ char objSize[11];
+ int i;
+//printf("\nProcessing AR file \"%s\"...\n", fname);
+ ptr += 8;
+
+ // Loop through all objects in the archive and process them
+ do
+ {
+ memset(objName, 0, 17);
+ objSize[10] = 0;
+
+ for(i=0; i<16; i++)
+ {
+// if ((ptr[i] == '/') || (ptr[i] == ' '))
+ if ((ptr[i] == ' ') && (i != 0))
+ {
+ objName[i] = 0;
+ break;
+ }
+
+ objName[i] = ptr[i];
+ }
+
+ for(i=0; i<10; i++)
+ {
+ if (ptr[48 + i] == ' ')
+ {
+ objSize[i] = 0;
+ break;
+ }
+
+ objSize[i] = ptr[48 + i];
+ }
+
+ // Check to see if a long filename was requested
+ // N.B.: " " is for GNU archives, and "/" is for BSD archives
+ if ((objName[0] == 0x20) || (objName[0] == '/'))
+ {
+ uint32_t fnSize = atoi(objName + 1);
+
+ if (longFilenames != NULL)
+ {
+ i = 0;
+ char * currentFilename = longFilenames + fnSize;
+
+ while (*currentFilename != 0x0A)
+ objName[i++] = *currentFilename++;
+
+ objName[i] = 0;
+ }
+ }
+
+ if ((strncmp(objName, "ARFILENAMES/", 12) == 0) || (strncmp(objName, "//", 2) == 0))
+ {
+ longFilenames = ptr + 60;
+ }
+ else if (HasDotOSuffix(objName))
+ {
+
+ // Strip off any trailing forward slash at end of object name
+ int lastChar = strlen(objName) - 1;
+
+ if (objName[lastChar] == '/')
+ objName[lastChar] = 0;
+
+//printf("Processing object \"%s\" (size == %i, obj_index == %i)...\n", objName, atoi(objSize), 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, tSize, dSize, bSize))
+ return 1;
+ }
+
+ uint32_t size = atoi(objSize);
+ size += (size & 0x01 ? 1 : 0);
+ ptr += 60 + size;
+ }
+ while (ptr < endPtr);
+
+ return 0;
+}
+
+
+//
+// Process files (*.o, *.a) passed in on the command line
+//
+int ProcessFiles(void)
+{
+ int i;
+ char magic[8]; // Magic header number (4 bytes for *.o, 8 for *.a)
+
+ // Process all file handles
+ for(i=0; i<(int)hd; i++)
+ {
+ // Verbose mode information
+ if (vflag == 1)
+ printf("Read file %s%s\n", name[i], (hflag[i] ? " (include)" : ""));
+
+ if (!hflag[i])
+ {
+ // Attempt to read file magic number (OBJECT/ARCHIVE FILES)
+ if (read(handle[i], magic, 8) != 8)
+ {
+ printf("Error reading file %s\n", name[i]);
+ close(handle[i]);
+ return 1;
+ }
+
+ lseek(handle[i], 0L, 0); // Reset to start of input file
+
+ // Look for RMAC/MAC/GCC (a.out) object files
+ if ((GetLong(magic) & 0xFFFF) == 0x0107)
+ {
+ // Process input object file
+ if (LoadObject(name[i], handle[i], 0L))
+ return 1;
+ }
+ // Look for DRI Alcyon C (and old MAC) object files
+ else if (GetWord(magic) == 0x601A)
+ {
+ // Process Alcyon object file.
+ if (LoadAlcyon(name[i], handle[i]))
+ return 1;
+ }
+ // Otherwise, look for an object archive file
+ else if (strncmp(magic, "!<arch>\x0A", 8) == 0)
+ {
+ if (LoadArchive(name[i], handle[i]))
+ return 1;
+ }
+ else
+ {
+ // Close file and error
+ printf("%s is not a supported object or archive file\n", name[i]);
+ printf("Magic == [%02X][%02X][%02X][%02X]\n", magic[0], magic[1], magic[2], magic[3]);
+ close(handle[i]);
+ return 1;
+ }
+ }
+ else
+ {
+ // INCLUDE FILES
+ // If hflag[i] is 1, include this in the data segment; if 2, put it
+ // in text segment
+ if (LoadInclude(name[i], handle[i], hsym1[i], hsym2[i], hflag[i] - 1))
+ return 1;
+ }
+ }
+
+ // Free include, symbol & object handles
+ for(i=0; i<(int)hd; i++)
+ {
+ free(name[i]);
+
+ if (hflag[i])
+ {
+ free(hsym1[i]);
+ free(hsym2[i]);
+ }
+ }
+
+ // Reset next handle indicator
+ hd = 0;
+ return 0;
+}
+
+
+//
+// Load newargv with pointers to arguments found in the buffer
+//
+int parse(char * buf, char * newargv[])
+{
+ int i = 1;
+
+ if (vflag)
+ printf("begin parsing\n");
+
+ while (1)