X-Git-Url: https://jxself.org/git/?p=inform.git;a=blobdiff_plain;f=src%2Ftables.c;fp=src%2Ftables.c;h=103f6f91e432566d96b63bf53f085c805113c9e5;hp=0000000000000000000000000000000000000000;hb=81ffe9a7de1db0b3a318a053b38882d1b7ab304c;hpb=d1090135a32de7b38b48c55d4e21f95da4c405bc diff --git a/src/tables.c b/src/tables.c new file mode 100644 index 0000000..103f6f9 --- /dev/null +++ b/src/tables.c @@ -0,0 +1,1945 @@ +/* ------------------------------------------------------------------------- */ +/* "tables" : Constructs the story file or module (the output) up to the */ +/* end of dynamic memory, gluing together all the required */ +/* tables. */ +/* */ +/* Copyright (c) Graham Nelson 1993 - 2018 */ +/* */ +/* This file is part of Inform. */ +/* */ +/* Inform is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 3 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Inform is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Inform. If not, see https://gnu.org/licenses/ */ +/* */ +/* ------------------------------------------------------------------------- */ + +#include "header.h" + +uchar *zmachine_paged_memory; /* Where we shall store the story file + constructed (contains all of paged + memory, i.e. all but code and the + static strings: allocated only when + we know how large it needs to be, + at the end of the compilation pass */ + +/* In Glulx, zmachine_paged_memory contains all of RAM -- i.e. all but + the header, the code, and the static strings. */ + +/* ------------------------------------------------------------------------- */ +/* Offsets of various areas in the Z-machine: these are set to nominal */ +/* values before the compilation pass, and to their calculated final */ +/* values only when construct_storyfile() happens. These are then used to */ +/* backpatch the incorrect values now existing in the Z-machine which */ +/* used these nominal values. */ +/* Most of the nominal values are 0x800 because this is guaranteed to */ +/* be assembled as a long constant if it's needed in code, since the */ +/* largest possible value of scale_factor is 8 and 0x800/8 = 256. */ +/* */ +/* In Glulx, I use 0x12345 instead of 0x800. This will always be a long */ +/* (32-bit) constant, since there's no scale_factor. */ +/* ------------------------------------------------------------------------- */ + +int32 code_offset, + actions_offset, + preactions_offset, + dictionary_offset, + adjectives_offset, + variables_offset, + strings_offset, + class_numbers_offset, + individuals_offset, + identifier_names_offset, + array_names_offset, + prop_defaults_offset, + prop_values_offset, + static_memory_offset, + attribute_names_offset, + action_names_offset, + fake_action_names_offset, + routine_names_offset, + constant_names_offset, + routines_array_offset, + constants_array_offset, + routine_flags_array_offset, + global_names_offset, + global_flags_array_offset, + array_flags_array_offset; +int32 arrays_offset, + object_tree_offset, + grammar_table_offset, + abbreviations_offset; /* Glulx */ + +int32 Out_Size, Write_Code_At, Write_Strings_At; +int32 RAM_Size, Write_RAM_At; /* Glulx */ + +/* ------------------------------------------------------------------------- */ +/* Story file header settings. (Written to in "directs.c" and "asm.c".) */ +/* ------------------------------------------------------------------------- */ + +int release_number, /* Release number game is to have */ + statusline_flag; /* Either TIME_STYLE or SCORE_STYLE */ + +int serial_code_given_in_program /* If TRUE, a Serial directive has */ + = FALSE; /* specified this 6-digit serial code */ +char serial_code_buffer[7]; /* (overriding the usual date-stamp) */ +int flags2_requirements[16]; /* An array of which bits in Flags 2 of + the header will need to be set: + e.g. if the save_undo / restore_undo + opcodes are ever assembled, we have + to set the "games want UNDO" bit. + Values are 0 or 1. */ + +/* ------------------------------------------------------------------------- */ +/* Construct story/module file (up to code area start). */ +/* */ +/* (To understand what follows, you really need to look at the run-time */ +/* system's specification, the Z-Machine Standards document.) */ +/* ------------------------------------------------------------------------- */ + +extern void write_serial_number(char *buffer) +{ + /* Note that this function may require modification for "ANSI" compilers + which do not provide the standard time functions: what is needed is + the ability to work out today's date */ + + time_t tt; tt=time(0); + if (serial_code_given_in_program) + strcpy(buffer, serial_code_buffer); + else +#ifdef TIME_UNAVAILABLE + sprintf(buffer,"970000"); +#else + strftime(buffer,10,"%y%m%d",localtime(&tt)); +#endif +} + +static void percentage(char *name, int32 x, int32 total) +{ printf(" %-20s %2d.%d%%\n",name,x*100/total,(x*1000/total)%10); +} + +static char *version_name(int v) +{ + if (!glulx_mode) { + switch(v) + { case 3: return "Standard"; + case 4: return "Plus"; + case 5: return "Advanced"; + case 6: return "Graphical"; + case 8: return "Extended"; + } + return "experimental format"; + } + else { + return "Glulx"; + } +} + +static int32 rough_size_of_paged_memory_z(void) +{ + /* This function calculates a modest over-estimate of the amount of + memory required to store the Z-machine's paged memory area + (that is, everything up to the start of the code area). */ + + int32 total, i; + + ASSERT_ZCODE(); + + total = 64 /* header */ + + 2 + subtract_pointers(low_strings_top, low_strings) + /* low strings pool */ + + 6*32; /* abbreviations table */ + + total += 8; /* header extension table */ + if (ZCODE_HEADER_EXT_WORDS>3) total += (ZCODE_HEADER_EXT_WORDS-3)*2; + + if (alphabet_modified) total += 78; /* character set table */ + + if (zscii_defn_modified) /* Unicode translation table */ + total += 2 + 2*zscii_high_water_mark; + + total += 2*((version_number==3)?31:63) /* property default values */ + + no_objects*((version_number==3)?9:14) /* object tree table */ + + properties_table_size /* property values of objects */ + + (no_classes+1)*(module_switch?4:2) + /* class object numbers table */ + + no_symbols*2 /* names of numerous things */ + + individuals_length /* tables of prop variables */ + + dynamic_array_area_size; /* variables and arrays */ + + for (i=0; i 0xFFFF) { + error("Z-machine Unicode translation table cannot contain characters beyond $FFFF."); + } + p[mark++] = j/256; p[mark++] = j%256; + } + } + + /* -------------------- Objects and Properties ------------------------ */ + + /* The object table must be word-aligned. The Z-machine spec does not + require this, but the RA__Pr() veneer routine does. See + http://inform7.com/mantis/view.php?id=1712. + */ + while ((mark%2) != 0) p[mark++]=0; + + prop_defaults_at = mark; + + p[mark++]=0; p[mark++]=0; + + for (i=2; i< ((version_number==3)?32:64); i++) + { p[mark++]=prop_default_value[i]/256; + p[mark++]=prop_default_value[i]%256; + } + + object_tree_at = mark; + + mark += ((version_number==3)?9:14)*no_objects; + + object_props_at = mark; + + for (i=0; i= 5) + { terminating_chars_at = mark; + for (i=0; i 2) + { warning("This version of Inform is unable to produce the grammar \ +table format requested (producing number 2 format instead)"); + grammar_version_number = 2; + } + + grammar_table_at = mark; + + mark = mark + no_Inform_verbs*2; + + for (i=0; i= 256, hence long constants) */ + /* -------------------------------------------------------------------- */ + + while ((mark%length_scale_factor) != 0) p[mark++]=0; + while (mark < (scale_factor*0x100)) p[mark++]=0; + if (oddeven_packing_switch) + while ((mark%(scale_factor*2)) != 0) p[mark++]=0; + + if (mark > 0x0FFFE) + { error("This program has overflowed the maximum readable-memory \ +size of the Z-machine format. See the memory map below: the start \ +of the area marked \"above readable memory\" must be brought down to $FFFE \ +or less."); + memory_map_switch = TRUE; + /* Backpatching the grammar tables requires us to trust some of the */ + /* addresses we've written into Z-machine memory, but they may have */ + /* been truncated to 16 bits, so we can't do it. */ + skip_backpatching = TRUE; + } + + /* -------------------------- Code Area ------------------------------- */ + /* (From this point on we don't write any more into the "p" buffer.) */ + /* -------------------------------------------------------------------- */ + + Write_Code_At = mark; + if (!OMIT_UNUSED_ROUTINES) { + code_length = zmachine_pc; + } + else { + if (zmachine_pc != df_total_size_before_stripping) + compiler_error("Code size does not match (zmachine_pc and df_total_size)."); + code_length = df_total_size_after_stripping; + } + mark += code_length; + + /* ------------------ Another synchronising gap ----------------------- */ + + if (oddeven_packing_switch) + { if (module_switch) + while ((mark%(scale_factor*2)) != 0) mark++; + else + while ((mark%(scale_factor*2)) != scale_factor) mark++; + } + else + while ((mark%scale_factor) != 0) mark++; + + /* ------------------------- Strings Area ----------------------------- */ + + Write_Strings_At = mark; + strings_length = static_strings_extent; + mark += strings_length; + + /* --------------------- Module Linking Data -------------------------- */ + + if (module_switch) + { link_table_at = mark; mark += link_data_size; + mark += zcode_backpatch_size; + mark += zmachine_backpatch_size; + } + + /* --------------------- Is the file too big? ------------------------- */ + + Out_Size = mark; + + switch(version_number) + { case 3: excess = Out_Size-((int32) 0x20000L); limit = 128; break; + case 4: + case 5: excess = Out_Size-((int32) 0x40000L); limit = 256; break; + case 6: + case 7: + case 8: excess = Out_Size-((int32) 0x80000L); limit = 512; break; + } + + if (module_switch) + { excess = Out_Size-((int32) 0x10000L); limit=64; + } + + if (excess > 0) + { char memory_full_error[80]; + sprintf(memory_full_error, + "The %s exceeds version-%d limit (%dK) by %d bytes", + output_called, version_number, limit, excess); + fatalerror(memory_full_error); + } + + /* --------------------------- Offsets -------------------------------- */ + + dictionary_offset = dictionary_at; + variables_offset = globals_at; + actions_offset = actions_at; + preactions_offset = preactions_at; + prop_defaults_offset = prop_defaults_at; + prop_values_offset = object_props_at; + static_memory_offset = grammar_table_at; + grammar_table_offset = grammar_table_at; + + if (extend_memory_map) + { extend_offset=256; + if (no_objects+9 > extend_offset) extend_offset=no_objects+9; + while ((extend_offset%length_scale_factor) != 0) extend_offset++; + /* Not sure why above line is necessary, but oddeven_packing + * will need extend_offset to be even */ + code_offset = extend_offset*scale_factor; + if (oddeven_packing_switch) + strings_offset = code_offset + scale_factor; + else + strings_offset = code_offset + (Write_Strings_At-Write_Code_At); + + /* With the extended memory model, need to specifically check that we + * haven't overflowed the packed address range for routines or strings. + * With the standard memory model, we only need the earlier total size + * check. + */ + excess = code_length + code_offset - (scale_factor*((int32) 0x10000L)); + if (excess > 0) + { char code_full_error[80]; + sprintf(code_full_error, + "The code area limit has been exceeded by %d bytes", + excess); + fatalerror(code_full_error); + } + + excess = strings_length + strings_offset - (scale_factor*((int32) 0x10000L)); + if (excess > 0) + { char strings_full_error[140]; + if (oddeven_packing_switch) + sprintf(strings_full_error, + "The strings area limit has been exceeded by %d bytes", + excess); + else + sprintf(strings_full_error, + "The code+strings area limit has been exceeded by %d bytes. \ + Try running Inform again with -B on the command line.", + excess); + fatalerror(strings_full_error); + } + } + else + { code_offset = Write_Code_At; + strings_offset = Write_Strings_At; + } + + /* --------------------------- The Header ----------------------------- */ + + for (i=0; i<=0x3f; i++) p[i]=0; /* Begin with 64 blank bytes */ + + p[0] = version_number; /* Version number */ + p[1] = statusline_flag*2; /* Bit 1 of Flags 1: statusline style */ + p[2] = (release_number/256); + p[3] = (release_number%256); /* Release */ + p[4] = (Write_Code_At/256); + p[5] = (Write_Code_At%256); /* End of paged memory */ + if (version_number==6) + { j=code_offset/scale_factor; /* Packed address of "Main__" */ + p[6]=(j/256); p[7]=(j%256); + } + else + { j=Write_Code_At+1; /* Initial PC value (bytes) */ + p[6]=(j/256); p[7]=(j%256); /* (first opcode in "Main__") */ + } + p[8] = (dictionary_at/256); p[9]=(dictionary_at%256); /* Dictionary */ + p[10]=prop_defaults_at/256; p[11]=prop_defaults_at%256; /* Objects */ + p[12]=(globals_at/256); p[13]=(globals_at%256); /* Dynamic area */ + p[14]=(grammar_table_at/256); + p[15]=(grammar_table_at%256); /* Grammar */ + for (i=0, j=0, k=1;i<16;i++, k=k*2) /* Flags 2 as needed for any */ + j+=k*flags2_requirements[i]; /* unusual opcodes assembled */ + p[16]=j/256; p[17]=j%256; + write_serial_number((char *) (p+18)); /* Serial number: 6 chars of ASCII */ + p[24]=abbrevs_at/256; + p[25]=abbrevs_at%256; /* Abbreviations table */ + p[26]=0; p[27]=0; /* Length of file to be filled in "files.c" */ + p[28]=0; p[29]=0; /* Checksum to be filled in "files.c" */ + + if (extend_memory_map) + { j=(Write_Code_At - extend_offset*scale_factor)/length_scale_factor; + p[40]=j/256; p[41]=j%256; /* Routines offset */ + if (oddeven_packing_switch) + j=(Write_Strings_At - extend_offset*scale_factor)/length_scale_factor; + p[42]=j/256; p[43]=j%256; /* = Strings offset */ + } + + if (version_number >= 5) + { p[46] = terminating_chars_at/256; /* Terminating characters table */ + p[47] = terminating_chars_at%256; + } + + if (alphabet_modified) + { j = charset_at; + p[52]=j/256; p[53]=j%256; } /* Character set table address */ + + j = headerext_at; + p[54] = j/256; p[55] = j%256; /* Header extension table address */ + + p[60] = '0' + ((RELEASE_NUMBER/100)%10); + p[61] = '.'; + p[62] = '0' + ((RELEASE_NUMBER/10)%10); + p[63] = '0' + RELEASE_NUMBER%10; + + /* ------------------------ Header Extension -------------------------- */ + + /* The numbering in the spec is a little weird -- it's headerext_length + words *after* the initial length word. We follow the spec numbering + in this switch statement, so the count is 1-based. */ + for (i=1; i<=headerext_length; i++) { + switch (i) { + case 3: + j = unicode_at; /* Unicode translation table address */ + break; + case 4: + j = ZCODE_HEADER_FLAGS_3; /* Flags 3 word */ + break; + default: + j = 0; + break; + } + p[headerext_at+2*i+0] = j / 256; + p[headerext_at+2*i+1] = j % 256; + } + + /* ----------------- The Header: Extras for modules ------------------- */ + + if (module_switch) + { p[0]=p[0]+64; + p[1]=MODULE_VERSION_NUMBER; + p[6]=map_of_module/256; + p[7]=map_of_module%256; + + mark = map_of_module; /* Module map format: */ + + p[mark++]=object_tree_at/256; /* 0: Object tree addr */ + p[mark++]=object_tree_at%256; + p[mark++]=object_props_at/256; /* 2: Prop values addr */ + p[mark++]=object_props_at%256; + p[mark++]=(Write_Strings_At/scale_factor)/256; /* 4: Static strs */ + p[mark++]=(Write_Strings_At/scale_factor)%256; + p[mark++]=class_numbers_offset/256; /* 6: Class nos addr */ + p[mark++]=class_numbers_offset%256; + p[mark++]=individuals_offset/256; /* 8: Indiv prop values */ + p[mark++]=individuals_offset%256; + p[mark++]=individuals_length/256; /* 10: Length of table */ + p[mark++]=individuals_length%256; + p[mark++]=no_symbols/256; /* 12: No of symbols */ + p[mark++]=no_symbols%256; + p[mark++]=no_individual_properties/256; /* 14: Max property no */ + p[mark++]=no_individual_properties%256; + p[mark++]=no_objects/256; /* 16: No of objects */ + p[mark++]=no_objects%256; + i = link_table_at; + p[mark++]=i/256; /* 18: Import/exports */ + p[mark++]=i%256; + p[mark++]=link_data_size/256; /* 20: Size of */ + p[mark++]=link_data_size%256; + i += link_data_size; + p[mark++]=i/256; /* 22: Code backpatch */ + p[mark++]=i%256; + p[mark++]=zcode_backpatch_size/256; /* 24: Size of */ + p[mark++]=zcode_backpatch_size%256; + i += zcode_backpatch_size; + p[mark++]=i/256; /* 26: Image backpatch */ + p[mark++]=i%256; + p[mark++]=zmachine_backpatch_size/256; /* 28: Size of */ + p[mark++]=zmachine_backpatch_size%256; + + /* Further space in this table is reserved for future use */ + } + + /* ---- Backpatch the Z-machine, now that all information is in ------- */ + + if (!module_switch && !skip_backpatching) + { backpatch_zmachine_image_z(); + for (i=1; i0; j--) + { int topbits; int32 value; + i = i + 2; + while (p[i] != 15) + { topbits = (p[i]/0x40) & 3; + value = p[i+1]*256 + p[i+2]; + switch(topbits) + { case 1: + value = final_dict_order[value] + *((version_number==3)?7:9) + + dictionary_offset + 7; + break; + case 2: + if (OMIT_UNUSED_ROUTINES) + value = df_stripped_address_for_address(value); + value += code_offset/scale_factor; + break; + } + p[i+1] = value/256; p[i+2] = value%256; + i = i + 3; + } + i++; + } + } + } + } + + /* ---- From here on, it's all reportage: construction is finished ---- */ + + if (statistics_switch) + { int32 k_long, rate; char *k_str=""; + k_long=(Out_Size/1024); + if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; } + else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; } + if (total_bytes_trans == 0) rate = 0; + else rate=total_bytes_trans*1000/total_chars_trans; + + { printf("In:\ +%3d source code files %6d syntactic lines\n\ +%6d textual lines %8ld characters ", + total_input_files, no_syntax_lines, + total_source_line_count, (long int) total_chars_read); + if (character_set_unicode) printf("(UTF-8)\n"); + else if (character_set_setting == 0) printf("(plain ASCII)\n"); + else + { printf("(ISO 8859-%d %s)\n", character_set_setting, + name_of_iso_set(character_set_setting)); + } + + printf("Allocated:\n\ +%6d symbols (maximum %4d) %8ld bytes of memory\n\ +Out: Version %d \"%s\" %s %d.%c%c%c%c%c%c (%ld%sK long):\n", + no_symbols, MAX_SYMBOLS, + (long int) malloced_bytes, + version_number, + version_name(version_number), + output_called, + release_number, p[18], p[19], p[20], p[21], p[22], p[23], + (long int) k_long, k_str); + + printf("\ +%6d classes (maximum %3d) %6d objects (maximum %3d)\n\ +%6d global vars (maximum 233) %6d variable/array space (maximum %d)\n", + no_classes, MAX_CLASSES, + no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)), + no_globals, + dynamic_array_area_size, MAX_STATIC_DATA); + + printf( +"%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\ +%6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\ +%6d actions (maximum %3d) %6d attributes (maximum %2d)\n\ +%6d common props (maximum %2d) %6d individual props (unlimited)\n", + no_Inform_verbs, MAX_VERBS, + dict_entries, MAX_DICT_ENTRIES, + no_grammar_lines, grammar_version_number, + no_grammar_tokens, + no_actions, MAX_ACTIONS, + no_attributes, ((version_number==3)?32:48), + no_properties-2, ((version_number==3)?30:62), + no_individual_properties - 64); + + if (track_unused_routines) + { + uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping; + printf( +"%6ld bytes of Z-code %6ld unused bytes %s (%.1f%%)\n", + (long int) df_total_size_before_stripping, (long int) diff, + (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"), + 100 * (float)diff / (float)df_total_size_before_stripping); + } + + printf( +"%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\ +%6d abbreviations (maximum %d) %6d routines (unlimited)\n\ +%6ld instructions of Z-code %6d sequence points\n\ +%6ld bytes readable memory used (maximum 65536)\n\ +%6ld bytes used in Z-machine %6ld bytes free in Z-machine\n", + (long int) total_chars_trans, + (long int) total_bytes_trans, + (total_chars_trans>total_bytes_trans)?0:1, + (long int) rate, + no_abbreviations, MAX_ABBREVS, + no_routines, + (long int) no_instructions, no_sequence_points, + (long int) Write_Code_At, + (long int) Out_Size, + (long int) + (((long int) (limit*1024L)) - ((long int) Out_Size))); + + } + } + + if (offsets_switch) + { + { printf( +"\nOffsets in %s:\n\ +%05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\ +%05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\ +%05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n", + output_called, + (long int) abbrevs_at, + (long int) prop_defaults_at, + (long int) object_tree_at, + (long int) object_props_at, + (long int) globals_at, + (long int) grammar_table_at, + (long int) actions_at, + (long int) preactions_at, + (long int) adjectives_offset, + (long int) dictionary_at, + (long int) Write_Code_At, + (long int) Write_Strings_At); + if (module_switch) + printf("%05lx Linking data\n",(long int) link_table_at); + } + } + + if (debugfile_switch) + { begin_writing_debug_sections(); + write_debug_section("abbreviations", 64); + write_debug_section("abbreviations table", abbrevs_at); + write_debug_section("header extension", headerext_at); + if (alphabet_modified) + { write_debug_section("alphabets table", charset_at); + } + if (zscii_defn_modified) + { write_debug_section("Unicode table", unicode_at); + } + write_debug_section("property defaults", prop_defaults_at); + write_debug_section("object tree", object_tree_at); + write_debug_section("common properties", object_props_at); + write_debug_section("class numbers", class_numbers_offset); + write_debug_section("identifier names", identifier_names_offset); + write_debug_section("individual properties", individuals_offset); + write_debug_section("global variables", globals_at); + write_debug_section("array space", globals_at+480); + write_debug_section("grammar table", grammar_table_at); + write_debug_section("actions table", actions_at); + write_debug_section("parsing routines", preactions_at); + write_debug_section("adjectives table", adjectives_offset); + write_debug_section("dictionary", dictionary_at); + write_debug_section("code area", Write_Code_At); + write_debug_section("strings area", Write_Strings_At); + end_writing_debug_sections(Out_Size); + } + + if (memory_map_switch) + { + { +printf("Dynamic +---------------------+ 00000\n"); +printf("memory | header |\n"); +printf(" +---------------------+ 00040\n"); +printf(" | abbreviations |\n"); +printf(" + - - - - - - - - - - + %05lx\n", (long int) abbrevs_at); +printf(" | abbreviations table |\n"); +printf(" +---------------------+ %05lx\n", (long int) headerext_at); +printf(" | header extension |\n"); + if (alphabet_modified) + { +printf(" + - - - - - - - - - - + %05lx\n", (long int) charset_at); +printf(" | alphabets table |\n"); + } + if (zscii_defn_modified) + { +printf(" + - - - - - - - - - - + %05lx\n", (long int) unicode_at); +printf(" | Unicode table |\n"); + } +printf(" +---------------------+ %05lx\n", + (long int) prop_defaults_at); +printf(" | property defaults |\n"); +printf(" + - - - - - - - - - - + %05lx\n", (long int) object_tree_at); +printf(" | objects |\n"); +printf(" + - - - - - - - - - - + %05lx\n", + (long int) object_props_at); +printf(" | object short names, |\n"); +printf(" | common prop values |\n"); +printf(" + - - - - - - - - - - + %05lx\n", + (long int) class_numbers_offset); +printf(" | class numbers table |\n"); +printf(" + - - - - - - - - - - + %05lx\n", + (long int) identifier_names_offset); +printf(" | symbol names table |\n"); +printf(" + - - - - - - - - - - + %05lx\n", + (long int) individuals_offset); +printf(" | indiv prop values |\n"); +printf(" +---------------------+ %05lx\n", (long int) globals_at); +printf(" | global variables |\n"); +printf(" + - - - - - - - - - - + %05lx\n", + ((long int) globals_at)+480L); +printf(" | arrays |\n"); +printf(" +=====================+ %05lx\n", + (long int) grammar_table_at); +printf("Readable| grammar table |\n"); +printf("memory + - - - - - - - - - - + %05lx\n", (long int) actions_at); +printf(" | actions |\n"); +printf(" + - - - - - - - - - - + %05lx\n", (long int) preactions_at); +printf(" | parsing routines |\n"); +printf(" + - - - - - - - - - - + %05lx\n", + (long int) adjectives_offset); +printf(" | adjectives |\n"); +printf(" +---------------------+ %05lx\n", (long int) dictionary_at); +printf(" | dictionary |\n"); +if (module_switch) +{ +printf(" + - - - - - - - - - - + %05lx\n", + (long int) map_of_module); +printf(" | map of module addrs |\n"); +} +printf(" +=====================+ %05lx\n", (long int) Write_Code_At); +printf("Above | Z-code |\n"); +printf("readable+---------------------+ %05lx\n", + (long int) Write_Strings_At); +printf("memory | strings |\n"); +if (module_switch) +{ +printf(" +=====================+ %05lx\n", (long int) link_table_at); +printf(" | module linking data |\n"); +} +printf(" +---------------------+ %05lx\n", (long int) Out_Size); + } + } + if (percentages_switch) + { printf("Approximate percentage breakdown of %s:\n", + output_called); + percentage("Z-code", code_length,Out_Size); + if (module_switch) + percentage("Linking data", link_data_size,Out_Size); + percentage("Static strings", strings_length,Out_Size); + percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size); + percentage("Objects", globals_at-prop_defaults_at,Out_Size); + percentage("Globals", grammar_table_at-globals_at,Out_Size); + percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size); + percentage("Header and synonyms", prop_defaults_at,Out_Size); + percentage("Total of save area", grammar_table_at,Out_Size); + percentage("Total of text", total_bytes_trans,Out_Size); + } + if (frequencies_switch) + { + { printf("How frequently abbreviations were used, and roughly\n"); + printf("how many bytes they saved: ('_' denotes spaces)\n"); + for (i=0; i> 24) & 0xFF; + p[mark++] = (val >> 16) & 0xFF; + p[mark++] = (val >> 8) & 0xFF; + p[mark++] = (val) & 0xFF; + } + + for (j=0; j0; j--) { + int topbits; + int32 value; + i = i + 3; + while (p[i] != 15) { + topbits = (p[i]/0x40) & 3; + value = ((p[i+1] << 24) | (p[i+2] << 16) + | (p[i+3] << 8) | (p[i+4])); + switch(topbits) { + case 1: + value = dictionary_offset + 4 + + final_dict_order[value]*DICT_ENTRY_BYTE_LENGTH; + break; + case 2: + if (OMIT_UNUSED_ROUTINES) + value = df_stripped_address_for_address(value); + value += code_offset; + break; + } + WriteInt32(p+(i+1), value); + i = i + 5; + } + i++; + } + } + + } + + /* ---- From here on, it's all reportage: construction is finished ---- */ + + if (statistics_switch) + { int32 k_long, rate; char *k_str=""; + k_long=(Out_Size/1024); + if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; } + else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; } + if (strings_length == 0) rate = 0; + else rate=strings_length*1000/total_chars_trans; + + { printf("In:\ +%3d source code files %6d syntactic lines\n\ +%6d textual lines %8ld characters ", + total_input_files, no_syntax_lines, + total_source_line_count, (long int) total_chars_read); + if (character_set_unicode) printf("(UTF-8)\n"); + else if (character_set_setting == 0) printf("(plain ASCII)\n"); + else + { printf("(ISO 8859-%d %s)\n", character_set_setting, + name_of_iso_set(character_set_setting)); + } + + {char serialnum[8]; + write_serial_number(serialnum); + printf("Allocated:\n\ +%6d symbols (maximum %4d) %8ld bytes of memory\n\ +Out: %s %s %d.%c%c%c%c%c%c (%ld%sK long):\n", + no_symbols, MAX_SYMBOLS, + (long int) malloced_bytes, + version_name(version_number), + output_called, + release_number, + serialnum[0], serialnum[1], serialnum[2], + serialnum[3], serialnum[4], serialnum[5], + (long int) k_long, k_str); + } + + printf("\ +%6d classes (maximum %3d) %6d objects (maximum %3d)\n\ +%6d global vars (maximum %3d) %6d variable/array space (maximum %d)\n", + no_classes, MAX_CLASSES, + no_objects, MAX_OBJECTS, + no_globals, MAX_GLOBAL_VARIABLES, + dynamic_array_area_size, MAX_STATIC_DATA); + + printf( +"%6d verbs (maximum %3d) %6d dictionary entries (maximum %d)\n\ +%6d grammar lines (version %d) %6d grammar tokens (unlimited)\n\ +%6d actions (maximum %3d) %6d attributes (maximum %2d)\n\ +%6d common props (maximum %3d) %6d individual props (unlimited)\n", + no_Inform_verbs, MAX_VERBS, + dict_entries, MAX_DICT_ENTRIES, + no_grammar_lines, grammar_version_number, + no_grammar_tokens, + no_actions, MAX_ACTIONS, + no_attributes, NUM_ATTR_BYTES*8, + no_properties, INDIV_PROP_START, + no_individual_properties - INDIV_PROP_START); + + if (track_unused_routines) + { + uint32 diff = df_total_size_before_stripping - df_total_size_after_stripping; + printf( +"%6ld bytes of code %6ld unused bytes %s (%.1f%%)\n", + (long int) df_total_size_before_stripping, (long int) diff, + (OMIT_UNUSED_ROUTINES ? "stripped out" : "detected"), + 100 * (float)diff / (float)df_total_size_before_stripping); + } + + printf( +"%6ld characters used in text %6ld bytes compressed (rate %d.%3ld)\n\ +%6d abbreviations (maximum %d) %6d routines (unlimited)\n\ +%6ld instructions of code %6d sequence points\n\ +%6ld bytes writable memory used %6ld bytes read-only memory used\n\ +%6ld bytes used in machine %10ld bytes free in machine\n", + (long int) total_chars_trans, + (long int) strings_length, + (total_chars_trans>strings_length)?0:1, + (long int) rate, + no_abbreviations, MAX_ABBREVS, + no_routines, + (long int) no_instructions, no_sequence_points, + (long int) (Out_Size - Write_RAM_At), + (long int) Write_RAM_At, + (long int) Out_Size, + (long int) + (((long int) (limit*1024L)) - ((long int) Out_Size))); + + } + } + + if (offsets_switch) + { + { printf( +"\nOffsets in %s:\n\ +%05lx Synonyms %05lx Defaults %05lx Objects %05lx Properties\n\ +%05lx Variables %05lx Parse table %05lx Actions %05lx Preactions\n\ +%05lx Adjectives %05lx Dictionary %05lx Code %05lx Strings\n", + output_called, + (long int) abbrevs_at, + (long int) prop_defaults_at, + (long int) object_tree_at, + (long int) object_props_at, + (long int) globals_at, + (long int) grammar_table_at, + (long int) actions_at, + (long int) preactions_at, + (long int) adjectives_offset, + (long int) dictionary_at, + (long int) Write_Code_At, + (long int) Write_Strings_At); + } + } + + if (debugfile_switch) + { begin_writing_debug_sections(); + write_debug_section("memory layout id", GLULX_HEADER_SIZE); + write_debug_section("code area", Write_Code_At); + write_debug_section("string decoding table", Write_Strings_At); + write_debug_section("strings area", + Write_Strings_At + compression_table_size); + if (Write_Strings_At + strings_length < Write_RAM_At) + { write_debug_section + ("zero padding", Write_Strings_At + strings_length); + } + if (globals_at) + { compiler_error("Failed assumption that globals are at start of " + "Glulx RAM"); + } + write_debug_section("global variables", Write_RAM_At + globals_at); + write_debug_section("array space", Write_RAM_At + arrays_at); + write_debug_section("abbreviations table", Write_RAM_At + abbrevs_at); + write_debug_section("object tree", Write_RAM_At + object_tree_at); + write_debug_section("common properties", + Write_RAM_At + object_props_at); + write_debug_section("property defaults", + Write_RAM_At + prop_defaults_at); + write_debug_section("class numbers", + Write_RAM_At + class_numbers_offset); + write_debug_section("identifier names", + Write_RAM_At + identifier_names_offset); + write_debug_section("grammar table", Write_RAM_At + grammar_table_at); + write_debug_section("actions table", Write_RAM_At + actions_at); + write_debug_section("dictionary", Write_RAM_At + dictionary_at); + if (MEMORY_MAP_EXTENSION) + { write_debug_section("zero padding", Out_Size); + } + end_writing_debug_sections(Out_Size + MEMORY_MAP_EXTENSION); + } + + if (memory_map_switch) + { + + { +printf(" +---------------------+ 000000\n"); +printf("Read- | header |\n"); +printf(" only +=====================+ %06lx\n", (long int) GLULX_HEADER_SIZE); +printf("memory | memory layout id |\n"); +printf(" +---------------------+ %06lx\n", (long int) Write_Code_At); +printf(" | code |\n"); +printf(" +---------------------+ %06lx\n", + (long int) Write_Strings_At); +printf(" | string decode table |\n"); +printf(" + - - - - - - - - - - + %06lx\n", + (long int) Write_Strings_At + compression_table_size); +printf(" | strings |\n"); +printf(" +=====================+ %06lx\n", + (long int) (Write_RAM_At+globals_at)); +printf("Dynamic | global variables |\n"); +printf("memory + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+arrays_at)); +printf(" | arrays |\n"); +printf(" +---------------------+ %06lx\n", + (long int) (Write_RAM_At+abbrevs_at)); +printf(" | printing variables |\n"); + if (alphabet_modified) + { +printf(" + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+charset_at)); +printf(" | alphabets table |\n"); + } + if (zscii_defn_modified) + { +printf(" + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+unicode_at)); +printf(" | Unicode table |\n"); + } +printf(" +---------------------+ %06lx\n", + (long int) (Write_RAM_At+object_tree_at)); +printf(" | objects |\n"); +printf(" + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+object_props_at)); +printf(" | property values |\n"); +printf(" + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+prop_defaults_at)); +printf(" | property defaults |\n"); +printf(" + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+class_numbers_offset)); +printf(" | class numbers table |\n"); +printf(" + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+identifier_names_offset)); +printf(" | id names table |\n"); +printf(" +---------------------+ %06lx\n", + (long int) (Write_RAM_At+grammar_table_at)); +printf(" | grammar table |\n"); +printf(" + - - - - - - - - - - + %06lx\n", + (long int) (Write_RAM_At+actions_at)); +printf(" | actions |\n"); +printf(" +---------------------+ %06lx\n", + (long int) dictionary_offset); +printf(" | dictionary |\n"); + if (MEMORY_MAP_EXTENSION == 0) + { +printf(" +---------------------+ %06lx\n", (long int) Out_Size); + } + else + { +printf(" +=====================+ %06lx\n", (long int) Out_Size); +printf("Runtime | (empty) |\n"); +printf(" extn +---------------------+ %06lx\n", (long int) Out_Size+MEMORY_MAP_EXTENSION); + } + + } + + } + + + if (percentages_switch) + { printf("Approximate percentage breakdown of %s:\n", + output_called); + percentage("Code", code_length,Out_Size); + if (module_switch) + percentage("Linking data", link_data_size,Out_Size); + percentage("Static strings", strings_length,Out_Size); + percentage("Dictionary", Write_Code_At-dictionary_at,Out_Size); + percentage("Objects", globals_at-prop_defaults_at,Out_Size); + percentage("Globals", grammar_table_at-globals_at,Out_Size); + percentage("Parsing tables", dictionary_at-grammar_table_at,Out_Size); + percentage("Header and synonyms", prop_defaults_at,Out_Size); + percentage("Total of save area", grammar_table_at,Out_Size); + percentage("Total of text", strings_length,Out_Size); + } + if (frequencies_switch) + { + { printf("How frequently abbreviations were used, and roughly\n"); + printf("how many bytes they saved: ('_' denotes spaces)\n"); + for (i=0; i