// Include source file ("!source" or "!src"). Has to be re-entrant. static enum eos_t PO_source(void) {// Now GotByte = illegal char FILE* fd; char local_gotbyte; input_t new_input, *outer_input; // Enter new nesting level. // Quit program if recursion too deep. if(--source_recursions_left < 0) Throw_serious_error("Too deeply nested. Recursive \"!source\"?"); // Read file name. Quit function on error. if(Input_read_filename(TRUE)) return(SKIP_REMAINDER); // If file could be opened, parse it. Otherwise, complain. if((fd = fopen(GLOBALDYNABUF_CURRENT, FILE_READBINARY))) { char *filename = (char *) safe_malloc(GlobalDynaBuf->size); // MPi: Arrays must be a constant expression strcpy(filename, GLOBALDYNABUF_CURRENT); outer_input = Input_now;// remember old input local_gotbyte = GotByte;// CAUTION - ugly kluge Input_now = &new_input;// activate new input Parse_and_close_file(fd, filename); Input_now = outer_input;// restore previous input GotByte = local_gotbyte;// CAUTION - ugly kluge free(filename); } else Throw_error(exception_cannot_open_input_file); // Leave nesting level source_recursions_left++; return(ENSURE_EOS); }
// Tidy up before exiting by saving label dump int ACME_finalize(int exit_code) { FILE* fd; if(labeldump_filename) { #if defined(USE_FOPEN_S) errno_t err = fopen_s(&fd,labeldump_filename, FILE_WRITETEXT); if(ferr(fd,err)) { #else fd = fopen(labeldump_filename, FILE_WRITETEXT); if(fd) { #endif Label_dump_all(fd); fclose(fd); } else { fprintf(stderr, "Error: Cannot open label dump file \"%s\".\n", labeldump_filename); exit_code = EXIT_FAILURE; } } if(vicelabeldump_filename) { #if defined(USE_FOPEN_S) errno_t err = fopen_s(&fd,vicelabeldump_filename, FILE_WRITETEXT); if(ferr(fd,err)) { #else fd = fopen(vicelabeldump_filename, FILE_WRITETEXT); if(fd) { #endif Label_dump_all_vice(fd); fclose(fd); } else { fprintf(stderr, "Error: Cannot open label dump file \"%s\".\n", vicelabeldump_filename); exit_code = EXIT_FAILURE; } } return(exit_code); } // Save output file static void save_output_file(void) { FILE* fd; #if defined(USE_FOPEN_S) errno_t err; #endif // if no output file chosen, tell user and do nothing if(output_filename == NULL) { fputs("No output file specified (use the \"-o\" option or the \"!to\" pseudo opcode).", stderr); return; } #if defined(USE_FOPEN_S) err = fopen_s(&fd,output_filename, FILE_WRITETEXT); if((fd == NULL) | (err != NULL)) { #else fd = fopen(output_filename, FILE_WRITEBINARY); if(fd == NULL) { #endif fprintf(stderr, "Error: Cannot open output file \"%s\".\n", output_filename); return; } Output_save_file(fd); fclose(fd); } // Perform a single pass. Returns number of "NeedValue" type errors. static int perform_pass(void) { FILE* fd; int i; // call modules' "pass init" functions CPU_passinit(default_cpu);// set default cpu values (PC undefined) Output_passinit(start_addr);// call after CPU_passinit(), to define PC Encoding_passinit(); // set default encoding Section_passinit(); // set initial zone (untitled) // init variables pass_undefined_count = 0; // no "NeedValue" errors yet pass_real_errors = 0; // no real errors yet // Process toplevel files for(i = 0; i<toplevel_src_count; i++) { #if defined(USE_FOPEN_S) errno_t err = fopen_s(&fd,toplevel_sources[i], FILE_READBINARY); if(ferr(fd,err)) #else fd = fopen(toplevel_sources[i], FILE_READBINARY); if(fd) #endif Parse_and_close_file(fd, toplevel_sources[i]); else { fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources[i]); pass_real_errors++; } } if(pass_real_errors) exit(ACME_finalize(EXIT_FAILURE)); else Output_end_segment(); return(pass_undefined_count); } // do passes until done (or errors occured). Return whether output is ready. static bool do_actual_work(void) { int undefined_prev, // "NeedValue" errors of previous pass undefined_curr; // "NeedValue" errors of current pass if(Process_verbosity > 1) puts("First pass."); pass_count = 0; undefined_curr = perform_pass(); // First pass // now pretend there has been a pass before the first one undefined_prev = undefined_curr + 1; // As long as the number of "NeedValue" errors is decreasing but // non-zero, keep doing passes. while(undefined_curr && (undefined_curr < undefined_prev)) { pass_count++; undefined_prev = undefined_curr; if(Process_verbosity > 1) puts("Further pass."); undefined_curr = perform_pass(); } // If still errors (unsolvable by doing further passes), // perform additional pass to find and show them if(undefined_curr == 0) return(TRUE); if(Process_verbosity > 1) puts("Further pass needed to find error."); ALU_throw_errors(); // activate error output (CAUTION - one-way!) pass_count++; perform_pass(); // perform pass, but now show "value undefined" return(FALSE); }