+ {
+ 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);
+}
+
+
+//
+// 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;
+ }
+ // 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