/* Pre-process the various assembly source files to create a single file for assembly, that has everything where it needs to live. */ #include #include #include #include #include #include #define DO_ERROR(X) { retVal=-1; fprintf(stderr,"%s:%d:%s():%s\n",__FILE__,__LINE__,__func__,X); break; } #define MAX_FILES (128*1024) typedef struct source_file { char *file; int address; // For getting routine sizes from first run of ophis int low_addr; int high_addr; int size; // For knowing when we have output the various routines int written; } source_file; source_file source_files[MAX_FILES]; int source_count=0; static int compare_source(const void* a, const void* b) { source_file* aa = (source_file*)a; source_file* bb = (source_file*)b; if (aa->addressaddress) return -1; if (aa->address>bb->address) return 1; return strcmp(aa->file,bb->file); } int dump_file(FILE *out,const char *name) { int retVal=0; FILE *f=NULL; do { f=fopen(name,"r"); if (!f) DO_ERROR("Failed to read file for input"); char line[8192]; while(!feof(f)) { line[0]=0; fgets(line,8192,f); fprintf(out,"%s",line); } } while(0); if (f) fclose(f); return retVal; } void usage(void) { fprintf(stderr,"usage: preprocess [-d ]\n"); } int main(int argc,char **argv) { int retVal=0; DIR *d=NULL; char *directory="."; struct dirent *de=NULL; do { int opt; while ((opt=getopt(argc,argv,"d:")) != -1) { switch(opt) { case 'd': directory=optarg; break; default: usage(); exit(-1); } } // Get list of files d=opendir(directory); if (!d) DO_ERROR("opendir() failed"); while((de=readdir(d))!=NULL) { if (strlen(de->d_name)>2) { if (de->d_name[0]!='.'&&de->d_name[0]!='#') // ignore temp files etc if (!strcmp(&de->d_name[strlen(de->d_name)-2],".s")) { if (strcmp(de->d_name,"combined.s")) { if (source_count>=MAX_FILES) DO_ERROR("Too many source files. Increase MAX_FILES?"); source_files[source_count].file=strdup(de->d_name); source_files[source_count].address=-1; source_count++; } } } } if (retVal) break; closedir(d); d=NULL; fprintf(stderr,"Found %d source files\n",source_count); // Now get routine addresses of everything for(int i=0;i=address) if (source_files[i].addressbiggest_size) { if (source_files[i].size<=space) { biggest_size=source_files[i].size; biggest=i; } } } } // Check if done if (next_fixed_routine==-1&&biggest==-1) break; fprintf(stderr,"At address $%04x, next allocated address is $%04X. Current space is %d bytes\n", address,next_allocated_address,space); if (biggest>-1) fprintf(stderr,"Biggest floating routine that fits is '%s' (%d bytes)\n", source_files[biggest].file,biggest_size); if (biggest==-1) { // Nothing else fits here. So write next_fixed_routine fprintf(stderr,"Writing file %s\n",source_files[next_fixed_routine].file); fprintf(out,"\n; Source file %s @ $%04X\n",source_files[next_fixed_routine].file,address); fprintf(out,"\t.checkpc $%04x\n\t.advance $%04x,$00\n", next_allocated_address,next_allocated_address); char filename[8192]; snprintf(filename,8192,"%s/%s",directory,source_files[next_fixed_routine].file); if (dump_file(out,filename)) DO_ERROR("Could not dump fixed address routine"); source_files[next_fixed_routine].written=1; address=next_allocated_address+source_files[next_fixed_routine].size; } else { fprintf(out,"\n; Source file %s @ $%04x\n",source_files[biggest].file,address); fprintf(stderr,"Writing file %s\n",source_files[biggest].file); char filename[8192]; snprintf(filename,8192,"%s/%s",directory,source_files[biggest].file); if (dump_file(out,filename)) DO_ERROR("Could not dump floating routine"); source_files[biggest].written=1; address+=source_files[biggest].size; } } fclose(out); if (retVal) break; for(int i=0;i