/* ------------------------------------------------------------------------- */ /* "files" : File handling, memory, command-line memory settings, */ /* fatal errors (and error throwback on Acorn Archimedes) */ /* */ /* Part of Inform release 5 */ /* */ /* ------------------------------------------------------------------------- */ #include "header.h" int override_error_line=0; int32 malloced_bytes=0; Sourcefile InputFiles[MAX_INCLUSION_DEPTH]; int input_file; int total_files_read; int total_sl_count; int include_path_set; char Source_Name[100], Code_Name[100], include_path[130]; static char home_directory[128]; /* ------------------------------------------------------------------------- */ /* NB: Arguably temporary files should be made using "tmpfile" in */ /* the ANSI C libraries, but we do it by hand since tmpfile is unusual. */ /* ------------------------------------------------------------------------- */ #ifdef USE_TEMPORARY_FILES FILE *Temp1_fp=NULL, *Temp2_fp=NULL; #ifdef ARCHIMEDES static char tname_b[128]; char tname_pre[128]; static char *temporary_name(int i) { sprintf(tname_b, "%sInfTemp%d", tname_pre, i); return(tname_b); } #endif #endif /* ------------------------------------------------------------------------- */ /* Line numbering, fatal errors */ /* ------------------------------------------------------------------------- */ extern int current_source_line(void) { if (input_file==0) return -1; return(InputFiles[input_file-1].source_line); } extern void advance_line(void) { InputFiles[input_file-1].source_line++; InputFiles[input_file-1].line_start = InputFiles[input_file-1].chars_read; total_sl_count++; } extern void declare_systemfile(void) { InputFiles[input_file-1].sys_flag=1; } extern int is_systemfile(void) { return InputFiles[input_file-1].sys_flag; } extern void print_error_line(void) { int j, flag=0; char *p; int i=override_error_line; p=InputFiles[input_file-1].filename; if (i==0) i=forerrors_line; else override_error_line=0; if (error_format==0) { if (input_file>1) printf("\"%s\", ", p); printf("line %d: ", i); } else { for (j=0; p[j]!=0; j++) if ((p[j]=='/') || (p[j]=='.')) flag=1; printf("%s", p); if (flag==0) printf("%s",Source_Extension); printf("(%d): ", i); } } extern void fatalerror(char *s) { print_error_line(); printf("Fatal error: %s\n",s); #ifdef ARC_THROWBACK throwback(0, s); throwback_end(); #endif #ifdef MAC_FACE asm_free_arrays(); express_free_arrays(); inputs_free_arrays(); symbols_free_arrays(); tables_free_arrays(); zcode_free_arrays(); free_remaining_arrays(); my_free(&all_text,"transcription text"); longjmp(mac_env,1); #endif exit(1); } static void couldntopen(char *m, char *fn) { char err_buffer[128]; sprintf(err_buffer, "%s \"%s\"", m, fn); fatalerror(err_buffer); } /* ------------------------------------------------------------------------- */ /* The memory manager */ /* ------------------------------------------------------------------------- */ extern void memoryerror(char *s, int32 size) { char fe_buff[128]; sprintf(fe_buff, "The memory setting %s (which is %ld at present) has been \ exceeded. Try running Inform again with $%s= on the \ command line.",s,(long int) size,s); fatalerror(fe_buff); } #ifdef PC_QUICKC extern void *my_malloc(int32 size, char *whatfor) { char _huge *c; if (memout_mode==1) printf("Allocating %ld bytes for %s\n",size,whatfor); c=(char _huge *)halloc(size,1); malloced_bytes+=size; if (c==0) fatalerror("Couldn't hallocate memory"); return(c); } extern void *my_calloc(int32 size, int32 howmany, char *whatfor) { void _huge *c; if (memout_mode==1) printf("Allocating %d bytes: array (%ld entries size %ld) for %s\n", size*howmany,howmany,size,whatfor); c=(void _huge *)halloc(howmany*size,1); malloced_bytes+=size*howmany; if (c==0) fatalerror("Couldn't hallocate memory for an array"); return(c); } #else extern void *my_malloc(int32 size, char *whatfor) { char *c; c=malloc((size_t) size); malloced_bytes+=size; if (c==0) fatalerror("Couldn't allocate memory"); if (memout_mode==1) printf("Allocating %ld bytes for %s at (%08lx)\n", (long int) size,whatfor,(long int) c); return(c); } extern void *my_calloc(int32 size, int32 howmany, char *whatfor) { void *c; c=calloc(howmany,(size_t) size); malloced_bytes+=size*howmany; if (c==0) fatalerror("Couldn't allocate memory for an array"); if (memout_mode==1) printf("Allocating %ld bytes: array (%ld entries size %ld) \ for %s at (%08lx)\n", ((long int)size) * ((long int)howmany), (long int)howmany,(long int)size,whatfor, (long int) c); return(c); } #endif extern void my_free(void *pointer, char *whatitwas) { if (memout_mode==1) printf("Freeing memory for %s\n",whatitwas); if (*(int **)pointer != NULL) { if (memout_mode==1) printf("Freeing memory for %s\n",whatitwas); #ifdef PC_QUICKC hfree(*(int **)pointer); #else free(*(int **)pointer); #endif *(int **)pointer = NULL; } } /* ------------------------------------------------------------------------- */ /* Dealing with source code files */ /* ------------------------------------------------------------------------- */ #ifdef ARC_THROWBACK char throwback_name[128*MAX_INCLUSION_DEPTH]; #endif #ifdef ARCHIMEDES #define FN_SEP '.' #else #define FN_SEP '/' #endif extern void load_sourcefile(char *story_name, int style_flag) { char name[128]; int i, flag=0; if (input_file==MAX_INCLUSION_DEPTH) { fatalerror("Too many files have included each other: \ increase #define MAX_INCLUSION_DEPTH"); } strcpy(InputFiles[input_file].filename,story_name); InputFiles[input_file].sys_flag=0; InputFiles[input_file].chars_read=0; InputFiles[input_file].file_no=total_files_read+1; if (debugging_file==1) { write_debug_byte(1); write_debug_byte(total_files_read+1); write_debug_string(story_name); } for (i=0; story_name[i]!=0; i++) if ((story_name[i]=='/') || (story_name[i]=='.')) flag=1; if (style_flag==1) flag=0; if (flag==0) { if (input_file>0) { if (style_flag==0) { if (include_path_set==1) sprintf(name,"%s%c%s%s", include_path, FN_SEP, story_name, Include_Extension); else sprintf(name,"%s%s%s", Include_Prefix, story_name, Include_Extension); } else sprintf(name,"%s%s%s", home_directory,story_name,Source_Extension); } else sprintf(name,"%s%s%s", Source_Prefix,story_name,Source_Extension); } else strcpy(name,story_name); if (input_file==0) { strcpy(home_directory, name); for (i=strlen(home_directory)-1; ((i>0)&&(home_directory[i]!=FN_SEP));i--) ; if (i!=0) i++; home_directory[i]=0; } if (debugging_file==1) write_debug_string(name); #ifdef ARC_THROWBACK strcpy(throwback_name+128*input_file, name); #endif InputFiles[input_file].handle = fopen(name,"r"); if (InputFiles[input_file].handle==NULL) { sprintf(sub_buffer, "Couldn't open input file \"%s\"",name); fatalerror(sub_buffer); } InputFiles[input_file++].source_line = 1; total_files_read++; if ((ltrace_mode!=0)||(trace_mode!=0)) { printf("\nOpening file \"%s\"\n",name); } } static int32 chars_kept; static void write_cr(void) { write_debug_address(chars_kept); } static void close_sourcefile(void) { int i; if (ferror(InputFiles[input_file-1].handle)) fatalerror("I/O failure: couldn't read from source file"); if (debugging_file==1) { write_debug_byte(16); write_debug_byte(InputFiles[input_file-1].file_no); write_cr(); i=InputFiles[input_file-1].source_line; write_debug_byte(i/256); write_debug_byte(i%256); } fclose(InputFiles[--input_file].handle); if ((ltrace_mode!=0)||(trace_mode!=0)) printf("\nClosing file\n"); if (input_file>=1) InputFiles[input_file-1].source_line--; } extern void close_all_source(void) { while (input_file>0) close_sourcefile(); } static int32 last_char_marker= -1; static int last_char; extern int file_char(int32 marker) { if (marker==last_char_marker) return(last_char); last_char_marker=marker; if (input_file==0) return(0); last_char=fgetc(InputFiles[input_file-1].handle); InputFiles[input_file-1].chars_read++; if (last_char==EOF) { close_sourcefile(); if (input_file==0) last_char=0; else last_char='\n'; } return(last_char); } extern int file_end(int32 marker) { int i; i=file_char(marker); if (i==0) return(1); return(0); } /* ------------------------------------------------------------------------- */ /* Outputting the final story file, with checksums worked out, from storage */ /* (and closing of the text transcript file, if present) */ /* ------------------------------------------------------------------------- */ static int c_low=0, c_high=0; extern void add_to_checksum(void *address) { unsigned char *p; p=(unsigned char *) address; c_low+=((int) *p); if (c_low>=256) { c_low-=256; if (++c_high==256) c_high=0; } } extern void output_file(void) { FILE *fout; char *actual_name; int i; #ifdef ARC_THROWBACK char *newname; #endif #ifdef US_POINTERS unsigned char *t; #else char *t; #endif char *t2; int32 length, blanks=0, size=0; if (process_filename_flag==0) { #ifdef ARC_THROWBACK newname=Code_Name; for (i=0; Code_Name[i]!=0; i++) if ((Code_Name[i]=='.')) newname=Code_Name+i+1; #define VFNAME newname #else #define VFNAME Code_Name #endif switch(actual_version) { case 3: sprintf(sub_buffer,"%s%s%s", Code_Prefix,VFNAME,Code_Extension); break; case 4: sprintf(sub_buffer,"%s%s%s", V4Code_Prefix,VFNAME,V4Code_Extension); break; case 5: sprintf(sub_buffer,"%s%s%s", V5Code_Prefix,VFNAME,V5Code_Extension); break; case 6: sprintf(sub_buffer,"%s%s%s", V6Code_Prefix,VFNAME,V6Code_Extension); break; case 7: sprintf(sub_buffer,"%s%s%s", V7Code_Prefix,VFNAME,V7Code_Extension); break; case 8: sprintf(sub_buffer,"%s%s%s", V8Code_Prefix,VFNAME,V8Code_Extension); break; } actual_name=sub_buffer; } else actual_name=Code_Name; fout=fopen(actual_name,"wb"); if (fout==NULL) couldntopen("Couldn't open output file",actual_name); #ifndef USE_TEMPORARY_FILES for (t=zcode; t0) { fputc(0,fout); blanks--; } if (ferror(fout)) fatalerror("I/O failure: couldn't write to story file"); fclose(fout); if (statistics_mode==2) printf("%d bytes written to '%s'\n",length,actual_name); #ifdef ARCHIMEDES if (actual_version == 3) sprintf(buffer,"settype %s 063",actual_name); if (actual_version == 4) sprintf(buffer,"settype %s 064",actual_name); if (actual_version == 5) sprintf(buffer,"settype %s 065",actual_name); if (actual_version == 6) sprintf(buffer,"settype %s 066",actual_name); if (actual_version == 7) sprintf(buffer,"settype %s 067",actual_name); if (actual_version == 8) sprintf(buffer,"settype %s 068",actual_name); system(buffer); #endif if (transcript_mode==1) { fout=fopen(Transcript_Name,"wb"); if (fout==NULL) couldntopen("Couldn't open transcript file", Transcript_Name); #ifdef MACINTOSH for (t2=all_text; t2