Added preliminary ar (*.a) archive support.

This commit is contained in:
Shamus Hammons 2014-12-15 11:49:54 -06:00
parent a1f6a3912c
commit 062df8602b
2 changed files with 227 additions and 131 deletions

337
rln.c
View File

@ -53,9 +53,11 @@ 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[512][FNLEN]; // Object file names
unsigned obj_segsize[512][3]; // Object file seg sizes; TEXT,DATA,BSS
char obj_fname[2048][FNLEN]; // Object file names
unsigned obj_segsize[2048][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
struct HREC * unresolved = NULL; // Pointer to unresolved hash list
struct HREC * lookup(char *); // Hash lookup
@ -148,17 +150,15 @@ void putword(uint8_t * dest, uint16_t val)
//
// Obtain a File's Size
// Find passed in file's length in bytes
// N.B.: This also resets the file's pointer to the start of the file
//
long FSIZE(int fd)
long FileSize(int fd)
{
unsigned temp, hold;
long size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
temp = lseek(fd, 0L, SEEK_CUR);
hold = lseek(fd, 0L, SEEK_END);
lseek(fd, 0L, SEEK_SET);
return hold;
return size;
}
@ -191,8 +191,8 @@ int dosym(struct OFILE * ofile)
// Point to end of symbol record in the object file
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.
// Search through object segment size table to accumulated segment sizes to
// ensure the correct offsets are used in the resulting COF file.
ssidx = -1; // Initialise segment index
tsegoffset = dsegoffset = bsegoffset = 0; // Initialise segment offsets
@ -386,7 +386,7 @@ int dosym(struct OFILE * ofile)
//
// Free Up Hash Records
// Free up hash memory
//
void hash_free(void)
{
@ -472,14 +472,16 @@ int ost_add(char * name, int type, long value)
}
else
{
// If next symbol record exceeds current allocation then expand symbol table.
// If next symbol record exceeds current allocation then expand symbol
// table.
ost_offset_p = (ost_ptr - ost);
ost_offset_e = (ost_end - ost);
// 3 x int (12)
if ((ost_ptr + 12) > ost_end)
{
if ((ost = realloc(ost, (unsigned)(ost_end + OST_BLOCK))) == NULL)
#warning "!!! Bad logic in realloc call !!!"
if ((ost = realloc(ost, (ost_end + OST_BLOCK))) == NULL)
{
printf("OST memory reallocation error.\n");
return -1;
@ -494,7 +496,8 @@ int ost_add(char * name, int type, long value)
if ((oststr_ptr + (slen + 1 + 4)) > oststr_end)
{
if ((oststr = realloc(oststr, (unsigned)(oststr_end + OST_BLOCK))) == NULL)
#warning "!!! Bad logic in realloc call !!!"
if ((oststr = realloc(oststr, (oststr_end + OST_BLOCK))) == NULL)
{
printf("OSTSTR memory reallocation error.\n");
return -1;
@ -864,7 +867,7 @@ void pathadd(char * s)
//
int tryopen(char ** p_name)
{
char * name = *p_name; // Filename
char * name = * p_name; // Filename
char * tmpbuf, * lastdot; // Buffer and 'dot' pointers
int fd, hasdot; // File descriptor and 'has dot' flag
@ -893,7 +896,7 @@ int tryopen(char ** p_name)
// Try the libdir only if the name isn't already anchored
if (*name != '/' && *name != '\\' && !strchr(name, ':'))
{
strcpy(tmpbuf,libdir);
strcpy(tmpbuf, libdir);
// Add a trailing path char if there isn't one already
pathadd(tmpbuf);
strcat(tmpbuf, name);
@ -943,8 +946,8 @@ void put_name(struct OFILE * p)
//
int dofile(char * fname, int flag, char * sym)
{
int fd; // File descriptor
int temp; // Temporary storage
int fd;
int temp;
// Verbose information
if (vflag)
@ -960,7 +963,7 @@ int dofile(char * fname, int flag, char * sym)
// Reached maximum file handles
if (hd == NHANDLES)
{
if (flush_handles())
if (ProcessObjectFiles())
return 1;
}
@ -1029,10 +1032,10 @@ int dofile(char * fname, int flag, char * sym)
//
int segmentpad(FILE * fd, long segsize, int value)
{
long padsize; // Number of pad bytes needed
int i; // Good 'ol iterator
char padarray[32]; // Array of padding bytes
char * padptr; // Pointer to array
long padsize; // Number of pad bytes needed
int i; // Good 'ol iterator
char padarray[32]; // Array of padding bytes
char * padptr; // Pointer to array
// Determine the number of padding bytes that are needed
padsize = (segsize + secalign) & ~secalign;
@ -1051,11 +1054,11 @@ int segmentpad(FILE * fd, long segsize, int value)
symoffset += padsize;
if (fwrite(padarray, padsize, 1, fd) != 1) // Write padding bytes
if (fwrite(padarray, padsize, 1, fd) != 1) // Write padding bytes
return 1;
}
return 0; // All done
return 0;
}
@ -1225,7 +1228,7 @@ int write_ofile(struct OHEADER * header)
}
// Write the DATA segment of each object file
for(otemp = olist; otemp != NULL; otemp = otemp->o_next)
for(otemp=olist; otemp!=NULL; otemp=otemp->o_next)
{
osize = otemp->o_header.dsize;
@ -1475,7 +1478,6 @@ int atolx(char * string, int * value)
// Stuff the (long) value of a string into the value argument. RETURNS TRUE if
// the string doesn't parse. Parses only as a hex string.
//
//int getval(char * string, long * value)
int getval(char * string, int * value)
{
return atolx(string, value);
@ -1495,12 +1497,13 @@ struct OHEADER * make_ofile()
struct OFILE * otemp, * oprev, * ohold; // Object file list pointers
struct OHEADER * header; // Output header pointer
textsize = datasize = bsssize = 0; // Initialise cumulative segment sizes
// Initialize cumulative segment sizes
textsize = datasize = bsssize = 0;
// For each object file, accumulate the sizes of the segments but remove
// those object files which are unused
oprev = NULL; // Init previous obj file list ptr
otemp = olist; // Set temp pointer to object file list
oprev = NULL; // Init previous obj file list ptr
otemp = olist; // Set temp pointer to object file list
while (otemp != NULL)
{
@ -1522,11 +1525,14 @@ struct OHEADER * make_ofile()
}
else
{
oprev -> o_next = otemp->o_next;
oprev->o_next = otemp->o_next;
}
ohold = otemp;
free(ohold->o_image);
if (!ohold->isArchiveFile)
free(ohold->o_image);
free(ohold);
}
else
@ -1627,8 +1633,11 @@ struct OHEADER * make_ofile()
ohold = otemp;
if (ohold->o_image) free(ohold->o_image);
free(ohold);
if (ohold->o_image)
if (!ohold->isArchiveFile)
free(ohold->o_image);
free(ohold);
}
else
{
@ -1672,7 +1681,7 @@ struct OHEADER * make_ofile()
hash_free(); // Done with global symbol hash tables
return (ret ? (unsigned)NULL : header);
return (ret ? (struct OHEADER *)NULL : header);
}
@ -1694,7 +1703,7 @@ int add_to_hlist(struct HREC ** hptr, char * sym, struct OFILE * ofile, long val
// Shamus: Moar testing...
if (vflag > 1)
{
printf("add_to_hlist(): hptr=$%08X, sym=\"%s\", ofile=$%08X, value=$%X, type=$%X\n", (unsigned int)hptr, sym, (unsigned int)ofile, value, type);
printf("add_to_hlist(): hptr=$%08X, sym=\"%s\", ofile=$%08X, value=$%X, type=$%X\n", hptr, sym, ofile, value, type);
}
for(i=0; i<SYMLEN; i++)
@ -1725,9 +1734,9 @@ add_unresolved(char * sym, struct OFILE * ofile)
//
// Generate and Return Hash Value
// Generate hash value
//
int dohash(char * s)
int DoHash(char * s)
{
int i = (s[0] + s[1] + s[2] + s[3] + s[4] + s[5] + s[6] + s[7] + s[8]
+ s[9] + s[10] + s[11] + s[12] + s[13] + s[14]) % NBUCKETS;
@ -1736,11 +1745,11 @@ int dohash(char * s)
//
// Lookup a Symbol in the Hash Table
// Lookup a symbol in the hash table
//
struct HREC * lookup(char * sym)
{
struct HREC * hptr = htable[dohash(sym)]; // Hash index to record based on sym
struct HREC * hptr = htable[DoHash(sym)]; // Hash index to record based on sym
char symbol[SYMLEN]; // Temporary symbol storage
memset(symbol, 0, SYMLEN); // Clean string for comparison
@ -1763,7 +1772,7 @@ struct HREC * lookup(char * sym)
//
// Add Symbol to the Hash Table
// Add symbol to the hash table
//
int hash_add(char * sym, long type, long value, struct OFILE * ofile)
{
@ -1778,7 +1787,7 @@ int hash_add(char * sym, long type, long value, struct OFILE * ofile)
if ((hptr = lookup(sym)) == NULL)
{
return add_to_hlist(&htable[dohash(sym)], sym, ofile, value, type);
return add_to_hlist(&htable[DoHash(sym)], sym, ofile, value, type);
}
// Already there!
@ -1917,7 +1926,7 @@ int add_symbols(struct OFILE * Ofile)
//
// Process Object File for Symbols
// Process object file for symbols
//
int doobj(char * fname, char * ptr, char * aname, int flags)
{
@ -1957,6 +1966,7 @@ int doobj(char * fname, char * ptr, char * aname, int flags)
Ofile->o_bbase = 0;
Ofile->o_flags = flags;
Ofile->o_image = ptr;
Ofile->isArchiveFile = 0;
// Don't do anything if this is just an ARCHIVE marker, just add the file
// to the olist
@ -2006,7 +2016,7 @@ int doobj(char * fname, char * ptr, char * aname, int flags)
//
// Remove Elements from Unresolved List which are Resolvable
// Remove elements from unresolved list which are resolvable
//
int dolist(void)
{
@ -2065,11 +2075,10 @@ int dolist(void)
//
// Extract Filename from Path
// Extract filename from path
//
char * path_tail(char * name)
{
// char * temp = MAX(strrchr(name, '/'), MAX(strrchr(name, ':'), strrchr(name, '\\')));
char * temp = strrchr(name, PATH_DELIMITER);
// Return what was passed in if path delimiter was not found
@ -2081,24 +2090,24 @@ char * path_tail(char * name)
//
// Add Input File to Processing List
// Add input file to processing list
//
int pladd(char * ptr, char * fname)
int AddToProcessingList(char * ptr, char * fname, uint8_t arFile)
{
if (plist == NULL)
{
plist = new_ofile(); // First time object record allocation
plast = plist; // Update last object record pointer
plist = new_ofile(); // First time object record allocation
plast = plist; // Update last object record pointer
}
else
{
plast->o_next = new_ofile(); // Next object record allocation
plast = plast->o_next; // Update last object record pointer
plast->o_next = new_ofile(); // Next object record allocation
plast = plast->o_next; // Update last object record pointer
}
if (plast == NULL)
{
printf("Out of memory.\n"); // Error if memory allocation fails
printf("Out of memory.\n"); // Error if memory allocation fails
return 1;
}
@ -2110,12 +2119,13 @@ int pladd(char * ptr, char * fname)
}
strcpy(plast->o_name, path_tail(fname)); // Store filename, not path
*plast->o_arname = 0; // No archive name for this file
plast->o_image = ptr; // Store data pointer
plast->o_flags = O_USED; // File is used
plast->o_next = NULL; // Initialise next record pointer
*plast->o_arname = 0; // No archive name for this file
plast->o_image = ptr; // Store data pointer
plast->o_flags = O_USED; // File is used
plast->o_next = NULL; // Initialise next record pointer
plast->isArchiveFile = arFile; // Shamus: Temp until can sort out
return 0; // Return without errors
return 0; // Return without errors
}
@ -2134,18 +2144,18 @@ int pladd(char * ptr, char * fname)
//
int doinclude(char * fname, int handle, char * sym1, char * sym2, int segment)
{
long fsize, dsize, size; // File, DATA segment and image sizes
char * ptr, * sptr; // Data pointers
int i; // Iterators
int sym1len = 0; // Symbol 1 length
int sym2len = 0; // Symbol 2 length
long fsize, dsize, size; // File, DATA segment and image sizes
char * ptr, * sptr; // Data pointers
int i; // Iterators
int sym1len = 0; // Symbol 1 length
int sym2len = 0; // Symbol 2 length
unsigned symtype = 0;
fsize = FSIZE(handle); // Get size of include file
dsize = (fsize + secalign) & ~secalign; // Round up to a alignment boundary
fsize = FileSize(handle); // Get size of include file
dsize = (fsize + secalign) & ~secalign; // Round up to a alignment boundary
sym1len = strlen(sym1) + 1; // Get sym1 length + null termination
sym2len = strlen(sym2) + 1; // Get sym2 length + null termination
sym1len = strlen(sym1) + 1; // Get sym1 length + null termination
sym2len = strlen(sym2) + 1; // Get sym2 length + null termination
size = 32 + dsize + 24 + 4 + sym1len + sym2len + 4;
@ -2167,17 +2177,17 @@ int doinclude(char * fname, int handle, char * sym1, char * sym2, int segment)
return 1;
}
close(handle); // Close file
close(handle);
strcpy(obj_fname[obj_index], path_tail(fname));
// Build this image's dummy header
putlong(ptr, 0x00000107); // Magic number
putlong(ptr, 0x00000107); // Magic number
if (segment)
{
putlong(ptr+4, dsize); // Text size
putlong(ptr+8, 0L); // Data size
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;
@ -2185,54 +2195,54 @@ int doinclude(char * fname, int handle, char * sym1, char * sym2, int segment)
}
else
{
putlong(ptr+4, 0L); // Text size
putlong(ptr+8, dsize); // Data size
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;
}
obj_index++; // Increment object count
obj_index++; // Increment object count
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
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
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)
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
sptr = ptr + 32 + dsize + 24; // Set sptr to symbol table size loc
putlong(sptr, sym1len + 4L); // Size of symbol table
putlong(sptr, sym1len + 4L); // Size of symbol table
sptr = ptr + 32 + dsize + 24 + 4; // Set sptr to symbol table location
sptr = ptr + 32 + dsize + 24 + 4; // Set sptr to symbol table location
for(i=0; i<(sym1len-1); i++) // Write symbol1 to string table
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
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
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
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
putlong(sptr, 0L); // Terminating long for object file
return pladd(ptr, fname);
return AddToProcessingList(ptr, fname, 0);
}
@ -2243,13 +2253,11 @@ int doinclude(char * fname, int handle, char * sym1, char * sym2, int segment)
// 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 doobject(char * fname, int fd, char * ptr)
int DoObject(char * fname, int fd, char * ptr)
{
long size; // File size
if (ptr == NULL)
{
size = FSIZE(fd); // Get size of input object file
long size = FileSize(fd);
// Allocate memory for file data
if ((ptr = malloc(size)) == NULL)
@ -2280,18 +2288,98 @@ int doobject(char * fname, int fd, char * ptr)
// Now add this image to the list of pending ofiles (plist)
// This routine is shared by doinclude after it builds the image
return pladd(ptr, fname);
return AddToProcessingList(ptr, fname, 0);
}
//
// Process an ar archive file (*.a)
//
int DoArchive(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;
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[17];
char objSize[11];
int i;
// Loop through all objects in the archive and process them
do
{
objName[16] = objSize[10] = 0;
for(i=0; i<16; i++)
{
if (ptr[i] == '/')
{
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];
}
if (objName[0] != 0)
{
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++;
if (AddToProcessingList(ptr + 60, objName, 1))
return 1;
}
uint32_t size = atoi(objSize);
size += (size & 0x01 ? 1 : 0);
ptr += 60 + size;
}
while (ptr < endPtr);
return 0;
}
//
// Process In Outstanding Object Files
// Process files (*.o, *.a) passed in on the command line
//
int flush_handles(void)
int ProcessObjectFiles(void)
{
int i; // Iterator
char magic[4]; // Magic header number
// unsigned test;
char magic[8]; // Magic header number
// Process all handles
for(i=0; i<(int)hd; i++)
@ -2303,8 +2391,9 @@ int flush_handles(void)
}
if (!hflag[i])
{ // Attempt to read file magic number
// OBJECT FILES
{
// Attempt to read file magic number
// OBJECT/ARCHIVE FILES
if (read(handle[i], magic, 4) != 4)
{
printf("Error reading file %s\n", name[i]);
@ -2313,19 +2402,24 @@ int flush_handles(void)
}
lseek(handle[i], 0L, 0); // Reset to start of input file
// test = getlong(magic); printf("Magic Number is 0x%08X\n", test);
// Look for RMAC/MAC/GCC ($20107) object files
if ((getlong(magic) == 0x00000107) || (getlong(magic) == 0x00020107))
{
// Process input object file
if (doobject(name[i], handle[i], 0L))
if (DoObject(name[i], handle[i], 0L))
return 1;
}
// Otherwise, look for an object archive file
else if (strncmp(magic, "!<arch>\0x0A", 8) == 0)
{
if (DoArchive(name[i], handle[i]))
return 1;
}
else
{
// Close file and error
printf("%s is not a supported object file\n", name[i]);
printf("%s is not a supported object or archive file\n", name[i]);
close(handle[i]);
return 1;
}
@ -2359,7 +2453,7 @@ int flush_handles(void)
//
// Load newargv with Pointers to Arguments Found in the Buffer
// Load newargv with pointers to arguments found in the buffer
//
int parse(char * buf, char * newargv[])
{
@ -2459,7 +2553,7 @@ int docmdfile(char * fname)
return 1;
}
size = FSIZE(fd);
size = FileSize(fd);
if ((ptr = malloc(size + 1)) == NULL)
{
@ -2916,7 +3010,7 @@ int main(int argc, char * argv[])
}
// Process in specified files/objects
if (flush_handles())
if (ProcessObjectFiles())
{
errflag = 1;
rln_exit();
@ -3001,7 +3095,8 @@ int main(int argc, char * argv[])
errflag = 1;
}
if (mflag) // Display the loaded symbols map
// Display the loaded symbols map
if (mflag)
if (write_map(header))
errflag = 1;
@ -3018,7 +3113,7 @@ int main(int argc, char * argv[])
//printf("BIG_ENDIAN = %i, LITTLE_ENDIAN = %i\n", BIG_ENDIAN, LITTLE_ENDIAN);
free(header); // Free allocated memory
rln_exit(); // Perform application exit
free(header);
rln_exit();
}

21
rln.h
View File

@ -51,8 +51,8 @@
#endif
#define MAJOR 1 // Major version number
#define MINOR 2 // Minor version number
#define PATCH 3 // Patch release number
#define MINOR 3 // Minor version number
#define PATCH 0 // Patch release number
#ifdef WIN32
#define PLATFORM "Win32" // Release platform - Windows
@ -75,13 +75,13 @@
// Macro to swap the 16-bit words of a 32-bit integer
#define _SWAPWORD(x) (((unsigned)(x) >> 16) | ((unsigned)(x) << 16))
#define FARGSIZE 1024 // Number of chars in filename argument
#define FNLEN 1024 // Size of a file name
#define NHANDLES 256 // Number of open file handles at once
#define OST_BLOCK 0x400000 // Output symbol table block (4MB)
#define DSTSEG_D 1 // Include file destination seg (DATA)
#define DSTSEG_T 2 // Include file destination seg (TEXT)
#define MAXARGS 256 // Max number of args in a command file
#define FARGSIZE 1024 // Number of chars in filename argument
#define FNLEN 1024 // Size of a file name
#define NHANDLES 256 // Number of open file handles at once
#define OST_BLOCK 0x400000 // Output symbol table block (4MB)
#define DSTSEG_D 1 // Include file destination seg (DATA)
#define DSTSEG_T 2 // Include file destination seg (TEXT)
#define MAXARGS 256 // Max number of args in a command file
// Headers
@ -97,7 +97,7 @@
struct OHEADER
{
uint32_t magic; // $0107 for .o, $601B for abs
uint32_t magic; // $0107 for .o, $601B for .abs
uint32_t tsize;
uint32_t dsize;
uint32_t bsize;
@ -148,6 +148,7 @@ struct OFILE
uint16_t o_flags; // Flags (see O_*)
struct OHEADER o_header; // Header of this file
uint8_t * o_image; // Image of this file
uint8_t isArchiveFile; // Temporary extra flag
};
#define new_ofile() (struct OFILE *)malloc((uint32_t)sizeof(struct OFILE))