home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * output.c
- * Copyright © 1992 Niklas Röjemo
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "error.h"
- #include "ChunkFile.h"
- #include "AofFile.h"
- #include "symbol.h"
- #include "output.h"
- #include "area.h"
- #include "riscos.h"
- #include "endian.h"
- #include "version.h"
-
- static FILE *objfile;
- extern char *ObjFileName;
-
- #define FIX(n) ((3+(int)n)&~3)
- #define EXTRA(n) (FIX(n)-n)
-
- static char *message = MESSAGE;
-
- #define MAXNAME 256
- static char outname[MAXNAME];
-
- void outputInit(char *outfile)
- {
- if(outfile && strcmp(outfile,"-")) {
- strncpy(outname,toriscos(outfile,"os",'o'),MAXNAME);
- if((objfile = fopen(outname,"wb")) == NULL) {
- error(ErrorAbort,FALSE,"As can't write %s",outfile);
- }
- } else {
- outname[0] = 0;
- objfile = stdout;
- }
- }
-
- void outputFinish(void)
- {
- if(objfile != stdout)
- fclose(objfile);
- }
-
- void outputRemove(void)
- {
- if(outname[0])
- remove(outname);
- }
-
- int countAreas(Symbol *ap)
- {
- int i = 0;
- while(ap) {
- ap->used = i++;
- ap = ap->area.info->next;
- }
- return i;
- }
-
- int sizeAreas(Symbol *ap, AofHeader *op)
- {
- int size = 0;
- for(; ap; ap = ap->area.info->next)
- if(!(ap->area.info->type & AREA_UDATA))
- size += ourword(op->entry[ap->used].Size) +
- 8*ourword(op->entry[ap->used].noRelocations);
- return size;
- }
-
- void outputAof(void)
- {
- ChunkFileHeader *chunkFile;
- AofHeader *objHeader;
- int noareas = countAreas(areaHead);
- int cfhsize = chunkFileHeaderSize(5);
- int ohsize = aofHeaderSize(noareas);
- int offset = cfhsize;
- Symbol *ap;
- int pad;
-
- if((chunkFile = malloc(cfhsize))==0)
- errorLine(0,ErrorSerious,FALSE,"Out of memory when allocating chunkFileHeader");
- chunkFile->ChunkField = ChunkFileID;
- chunkFile->maxChunks = chunkFile->noChunks = 5;
-
- if((objHeader = malloc(ohsize))==0)
- errorLine(0,ErrorSerious,FALSE,"Internal outputAof: Out of memory when allocating objHeader");
-
- for(ap = areaHead; ap; ap = ap->area.info->next) {
- objHeader->entry[ap->used].Type = ap->area.info->type;
- objHeader->entry[ap->used].Size = FIX(ap->value.ValueInt.i);
- if((objHeader->entry[ap->used].noRelocations = relocFix(ap)) != 0 &&
- objHeader->entry[ap->used].Type & AREA_UDATA)
- errorLine(0,ErrorSerious,FALSE,"Internal outputAof: Relocations in uninitsialised area.");
- objHeader->entry[ap->used].Unused = 0;
- }
-
- objHeader->Type = AofHeaderID;
- objHeader->Version = 150;
- objHeader->noAreas = noareas;
- objHeader->noSymbols = symbolFix();
- objHeader->EntryArea = areaEntry?areaEntry->used+1:0;
- objHeader->EntryOffset = areaEntry?areaEntryOffset:0;
- for(ap = areaHead; ap; ap = ap->area.info->next)
- objHeader->entry[ap->used].Name = ap->offset;
-
- chunkFile->entry[0].ChunkIDPrefix = ChunkID_OBJ;
- chunkFile->entry[0].ChunkIDType = ChunkID_OBJ_HEAD;
- chunkFile->entry[0].FileOffset = offset;
- chunkFile->entry[0].Size = ohsize;
- offset += chunkFile->entry[0].Size;
-
- chunkFile->entry[1].ChunkIDPrefix = ChunkID_OBJ;
- chunkFile->entry[1].ChunkIDType = ChunkID_OBJ_IDFN;
- chunkFile->entry[1].FileOffset = offset;
- chunkFile->entry[1].Size = FIX(strlen(message)+1);
- offset += chunkFile->entry[1].Size;
-
- chunkFile->entry[2].ChunkIDPrefix = ChunkID_OBJ;
- chunkFile->entry[2].ChunkIDType = ChunkID_OBJ_STRT;
- chunkFile->entry[2].FileOffset = offset;
- chunkFile->entry[2].Size = FIX(symbolStringSize());
- offset += chunkFile->entry[2].Size;
-
- chunkFile->entry[3].ChunkIDPrefix = ChunkID_OBJ;
- chunkFile->entry[3].ChunkIDType = ChunkID_OBJ_SYMT;
- chunkFile->entry[3].FileOffset = offset;
- chunkFile->entry[3].Size = objHeader->noSymbols*16;
- offset += chunkFile->entry[3].Size;
-
- chunkFile->entry[4].ChunkIDPrefix = ChunkID_OBJ;
- chunkFile->entry[4].ChunkIDType = ChunkID_OBJ_AREA;
- chunkFile->entry[4].FileOffset = offset;
- chunkFile->entry[4].Size = sizeAreas(areaHead,objHeader);
- offset += chunkFile->entry[4].Size;
-
- /******** File header ***********/
- if(cfhsize != fwrite((void *)chunkFile,1,cfhsize,objfile)) {
- errorLine(0,ErrorSerious,FALSE,"Internal outputAof: Error when writing chunk file header.");
- exit(-1);
- }
- /******** Chunk 0 Header ********/
- if(ourword(chunkFile->entry[0].Size) !=
- fwrite((void *)objHeader,1,ourword(chunkFile->entry[0].Size),objfile)) {
- errorLine(0,ErrorSerious,FALSE,"Internal outputAof: Error when writing chunk header.");
- exit(-1);
- }
- /******** Chunk 1 Identification *********/
- if(ourword(chunkFile->entry[1].Size) !=
- fwrite((void *)message,1,ourword(chunkFile->entry[1].Size),objfile)) {
- errorLine(0,ErrorSerious,FALSE,"Internal outputAof: Error when writing identification.");
- exit(-1);
- }
- /******** Chunk 2 String Table ***********/
- if(4 != fwrite((void *)&chunkFile->entry[2].Size,1,4,objfile)) {
- errorLine(0,ErrorSerious,FALSE,"Internal outputAof: Error when writing string table size.");
- exit(-1);
- }
- symbolStringOutput(objfile);
- for(pad = EXTRA(symbolStringSize()); pad; pad--)
- fputc(0,objfile);
-
- /******** Chunk 3 Symbol Table ***********/
- symbolSymbolOutput(objfile);
-
- /******** Chunk 4 Area *****************/
- for(ap = areaHead; ap; ap = ap->area.info->next) {
- if(!(ap->area.info->type & AREA_UDATA)) {
- if(ourword(objHeader->entry[ap->used].Size) !=
- fwrite((void *)ap->area.info->image,1,ourword(objHeader->entry[ap->used].Size),objfile)){
- errorLine(0,ErrorSerious,FALSE,"Internal outputAof: Error when writing %s image.",ap->str);
- exit(-1);
- }
- relocOutput(objfile, ap);
- }
- }
- }
-