/* ------------------------------------------------------------------------- */ /* "tables" : Maintains tables of dictionary, objects, actions, */ /* grammar and global variables; */ /* and constructs the tables part of the story file */ /* */ /* Part of Inform release 5 */ /* */ /* ------------------------------------------------------------------------- */ #include "header.h" int no_attributes, no_properties, no_globals, no_fake_actions=0; int dict_entries; int release_number=1, statusline_flag=0; int time_set=0; char time_given[7]; int globals_size, properties_size; int32 prop_defaults[64]; int prop_longflag[64]; int prop_additive[64]; char *properties_table; int max_no_objects=0; int resobj_flag = 0; static int no_verbs=0, no_actions=0, no_adjectives=0, no_objects=0, no_classes=0, classes_size=0; static int fp_no_actions=0; static int embedded_routine = 0; static fpropt full_object; /* ------------------------------------------------------------------------- */ /* Arrays used by this file */ /* ------------------------------------------------------------------------- */ #ifndef ALLOCATE_BIG_ARRAYS static verbt vs[MAX_VERBS]; static objectt objects[MAX_OBJECTS]; static int table_init[MAX_STATIC_DATA]; static int32 actions[MAX_ACTIONS], preactions[MAX_ACTIONS], adjectives[MAX_ADJECTIVES]; static dict_word adjcomps[MAX_ADJECTIVES]; static int32 gvalues[240]; static int dict_places_list[MAX_DICT_ENTRIES], dict_places_back[MAX_DICT_ENTRIES], dict_places_inverse[MAX_DICT_ENTRIES]; static dict_word dict_sorts[MAX_DICT_ENTRIES]; static zip class_pointer[MAX_CLASS_TABLE_SIZE]; static int classes_here[MAX_CLASSES]; static int32 *classes_at[MAX_CLASSES]; #else static verbt *vs; static objectt *objects; static int *table_init; static int32 *actions, *preactions, *adjectives; static dict_word *adjcomps; static int32 *gvalues; static int *dict_places_list, *dict_places_back, *dict_places_inverse; static dict_word *dict_sorts; static int *classes_here; static int32 **classes_at; static zip *class_pointer; #endif static char *verblist; static char *verblist_p; extern void tables_allocate_arrays(void) { #ifdef ALLOCATE_BIG_ARRAYS vs = my_calloc(sizeof(verbt), MAX_VERBS, "verbs"); objects = my_calloc(sizeof(objectt), MAX_OBJECTS, "objects"); table_init = my_calloc(sizeof(int), MAX_STATIC_DATA, "static data"); actions = my_calloc(sizeof(int32), MAX_ACTIONS, "actions"); preactions = my_calloc(sizeof(int32), MAX_ACTIONS, "preactions"); adjectives = my_calloc(sizeof(int32), MAX_ADJECTIVES, "adjectives"); adjcomps = my_calloc(sizeof(dict_word), MAX_ADJECTIVES, "adj comps"); gvalues = my_calloc(sizeof(int32), 240, "global values"); dict_places_list = my_calloc(sizeof(int), MAX_DICT_ENTRIES, "dictionary places list"); dict_places_back = my_calloc(sizeof(int), MAX_DICT_ENTRIES, "dictionary places back"); dict_places_inverse = my_calloc(sizeof(int), MAX_DICT_ENTRIES, "inverse of dictionary places"); dict_sorts = my_calloc(sizeof(dict_word), MAX_DICT_ENTRIES, "dictionary sort codes"); class_pointer = my_malloc(MAX_CLASS_TABLE_SIZE, "class table"); classes_here = my_calloc(sizeof(int), MAX_CLASSES, "inherited classes list"); classes_at = my_calloc(sizeof(int32), MAX_CLASSES, "pointers to classes"); #endif verblist = my_malloc(MAX_VERBSPACE, "register of verbs"); verblist_p = verblist; } extern void tables_free_arrays(void) { #ifdef ALLOCATE_BIG_ARRAYS my_free(&vs, "verbs"); my_free(&objects, "objects"); my_free(&table_init, "static data"); my_free(&actions, "actions"); my_free(&preactions, "preactions"); my_free(&adjectives, "adjectives"); my_free(&adjcomps, "adj comps"); my_free(&gvalues, "global values"); my_free(&dict_places_list, "dictionary places list"); my_free(&dict_places_back, "dictionary places back"); my_free(&dict_places_inverse, "inverse of dictionary places"); my_free(&dict_sorts, "dictionary sort codes"); my_free(&class_pointer,"class table"); my_free(&classes_here, "inherited classes list"); my_free(&classes_at, "pointers to classes"); #endif my_free(&verblist,"register of verbs"); } /* ------------------------------------------------------------------------- */ /* A routine using an unusual ANSI library function: */ /* */ /* write_serialnumber writes today's date in the form YYMMDD as a string */ /* (as can be seen, the VAX doesn't know it) */ /* ------------------------------------------------------------------------- */ static void write_serialnumber(char *buffer) { time_t tt; tt=time(0); if (time_set==0) #ifdef TIME_UNAVAILABLE sprintf(buffer,"940000"); #else strftime(buffer,10,"%y%m%d",localtime(&tt)); #endif else sprintf(buffer,"%06s",time_given); } /* ------------------------------------------------------------------------- */ /* Dictionary table builder */ /* The dictionary is, so to speak, thumb-indexed: the beginning of each */ /* letter in the double-linked-list is marked. Experiments with */ /* increasing the number of markers (to the first two letters, say) result */ /* in extra bureaucracy which cancels out any speed gain. */ /* ------------------------------------------------------------------------- */ #define NUMBER_DICT_MARKERS 26 static int total_dict_entries; static dict_word letter_keys[NUMBER_DICT_MARKERS]; static int letter_starts[NUMBER_DICT_MARKERS]; static int start_list; static dict_word prepared_sort; static int initial_letter; static void dictionary_begin_pass(void) { int i, j; dict_p=dictionary+7; total_dict_entries=dict_entries; dict_entries=0; if (pass_number==1) { start_list=0; dict_places_list[0]= -2; dict_places_back[0]= -1; for (i=0; i=26)&&(k<2*26)) k=k-26; if ((k/26)!=0) wd[i++]=3+(k/26); wd[i]=6+(k%26); } for (; i<9; i++) wd[i]=5; InV3 { wd[6]=5; wd[7]=5; wd[8]=5; if ((wd[5]==3)||(wd[5]==4)) wd[5]=5; } InV5 { if ((wd[8]==3)||(wd[8]==4)) wd[8]=5; } initial_letter = wd[0]-6; if (initial_letter<0) { error("Dictionary words must begin with a letter of the alphabet"); initial_letter=0; } /* Note... this doesn't depend on A to Z being contiguous in the machine's character set */ tot = wd[2] + wd[1]*(1<<5) + wd[0]*(1<<10); prepared_sort.b[1]=tot%0x100; prepared_sort.b[0]=(tot/0x100)%0x100; tot = wd[5] + wd[4]*(1<<5) + wd[3]*(1<<10); prepared_sort.b[3]=tot%0x100; prepared_sort.b[2]=(tot/0x100)%0x100; tot = wd[8] + wd[7]*(1<<5) + wd[6]*(1<<10); prepared_sort.b[5]=tot%0x100; prepared_sort.b[4]=(tot/0x100)%0x100; InV3 { prepared_sort.b[2]+=0x80; } InV5 { prepared_sort.b[4]+=0x80; } return(prepared_sort); } extern int dictionary_find(char *dword, int scope) { int32 j, j2, k, jlim; dict_word i; i=dictionary_prepare(dword); if (scope==1) jlim=dict_entries; else jlim=total_dict_entries; if (pass_number==1) { for (j=0; j %03d) at %04x: ", i,dict_places_back[i],dict_places_list[i], dictionary_offset+7+(3+res)*i); else printf("Entry %03d at %04x: ",i,dictionary_offset+7+(3+res)*i); show_letter( (((int) p[0])&0x7c)/4 ); show_letter( 8*(((int) p[0])&0x3) + (((int) p[1])&0xe0)/32 ); show_letter( ((int) p[1])&0x1f ); show_letter( (((int) p[2])&0x7c)/4 ); show_letter( 8*(((int) p[2])&0x3) + (((int) p[3])&0xe0)/32 ); show_letter( ((int) p[3])&0x1f ); printf(" "); for (j=0; j<3+res; j++) printf("%02x ",p[j]); printf("\n"); } } static void dictionary_set_verb_number(char *dword, int to) { int i; zip *p; int res=((version_number==3)?4:6); i=dictionary_find(dword,1); if (i!=0) { p=dictionary+7+(i-1)*(3+res)+res; p[1]=to; } } extern int dictionary_add(char *dword, int x, int y, int z) { int off, i, k, l; zip *p; dict_word pcomp, qcomp; int res=((version_number==3)?4:6); if (dict_entries==MAX_DICT_ENTRIES) { memoryerror("MAX_DICT_ENTRIES",MAX_DICT_ENTRIES); } i=dictionary_find(dword,1); if (i!=0) { p=dictionary+7+(i-1)*(3+res)+res; p[0]=(p[0])|x; p[1]=(p[1])|y; p[2]=(p[2])|z; return(dictionary_offset+7+(3+res)*(i-1)); } if (pass_number==1) i=dict_entries; else { i=dict_places_inverse[dict_entries]; } off=(3+res)*i+7; p=dictionary+off; p[0]=prepared_sort.b[0]; p[1]=prepared_sort.b[1]; p[2]=prepared_sort.b[2]; p[3]=prepared_sort.b[3]; InV5 { p[4]=prepared_sort.b[4]; p[5]=prepared_sort.b[5]; } p[res]=x; p[res+1]=y; p[res+2]=z; if (pass_number==1) { pcomp=prepared_sort; if (dict_entries==0) { dict_places_list[0]= -2; dict_places_list[1]= -1; goto PlaceFound; } l=initial_letter; do { k=letter_starts[l--]; } while ((l>=0)&&(k==-1)); if (k==-1) k=start_list; for (; k!=-2; k=dict_places_list[k]) { qcomp=dict_sorts[k]; if (compare_sorts(pcomp,qcomp)<0) { l=dict_places_back[k]; if (l==-1) { dict_places_list[dict_entries]=start_list; dict_places_back[dict_entries]= -1; dict_places_back[k]=dict_entries; start_list=dict_entries; goto PlaceFound; } dict_places_list[l]=dict_entries; dict_places_back[k]=dict_entries; dict_places_list[dict_entries]=k; dict_places_back[dict_entries]=l; goto PlaceFound; } l=k; } dict_places_list[l]=dict_entries; dict_places_back[dict_entries]=l; dict_places_list[dict_entries]= -2; PlaceFound: dict_sorts[dict_entries]=pcomp; if (compare_sorts(pcomp,letter_keys[initial_letter])<0) { letter_keys[initial_letter]=pcomp; letter_starts[initial_letter]=dict_entries; } } dict_entries++; dict_p+=res+3; /* show_dictionary(); */ return(dictionary_offset+off); } extern void list_object_tree(void) { int i; printf("obj par nxt chl Object tree:\n"); for (i=0; i=MAX_ACTIONS) memoryerror("MAX_ACTIONS",MAX_ACTIONS); for (i=0; i=0) { error_named("Two different verb definitions refer to", verb); return; } verbspace_consumed += strlen(verb)+3; if (verbspace_consumed >= MAX_VERBSPACE) memoryerror("MAX_VERBSPACE",MAX_VERBSPACE); strcpy(verblist_p+2,verb); verblist_p[1]=number; verblist_p[0]=3+strlen(verb); verblist_p += verblist_p[0]; } static int32 parsing_routines[64]; static int no_prs; static int debug_acts_writ[256]; static int action_exists[256]; static int grammar_line(int verbnum, int line, int i, char *b) { int j, l, flag=0; int32 k; int vargs, vtokens, vinsert; if (line>=MAX_LINES_PER_VERB) { error("Too many lines of grammar for verb: increase \ #define MAX_LINES_PER_VERB"); return(0); } word(b,i++); flag=2; if (b[0]==0) return(0); if (strcmp(b,"*")!=0) { error_named("'*' divider expected, but found",b); return(0); } vtokens=1; vargs=0; for (j=0; j<8; j++) vs[verbnum].l[line].e[j]=0; do { word(b,i++); if (b[0]==0) { error("'->' clause missing"); return(0); } if (strcmp(b,"->")==0) break; if (b[0]=='\"') { textword(b,i-1); vinsert=make_adjective(b); } else On_("noun") { vargs++; vinsert=0; } else On_("held") { vargs++; vinsert=1; } else On_("multi") { vargs++; vinsert=2; } else On_("multiheld") { vargs++; vinsert=3; } else On_("multiexcept") { vargs++; vinsert=4; } else On_("multiinside") { vargs++; vinsert=5; } else On_("creature") { vargs++; vinsert=6; } else On_("special") { vargs++; vinsert=7; } else On_("number") { vargs++; vinsert=8; } else On_("scope") { word(b,i++); if (strcmp(b,"=")!=0) { error_named("Expected '=' after 'scope' but found",b); return(0); } word(b,i++); j=find_symbol(b); if ((j<0) || (stypes[j]!=1)) { error_named( "Expected routine after 'scope=' but found",b); return(0); } for (l=0; (l0; k--) vs[j].l[k+lines]=vs[j].l[k-1+lines]; i=grammar_line(j, lines++,i,b); } while (i!=0); if (mode==2) { vs[j].lines = l+lines-1; for (k=0; k=256) j=0x1000; } } if ((j>=256)||(prop_longflag[i]==1)) full_object.pp[x].p[y++]=j/256; full_object.pp[x].p[y++]=j%256; } while (flag==0); if (y==0) { full_object.pp[x].p[y++]=0; full_object.pp[x].p[y++]=0; } full_object.pp[x].l=y; InV3 { if (y>8) { word(sub_buffer, pnw); if (pass_number==2) warning_named("Standard-game limit of 8 bytes per property exceeded \ (use Advanced to get 64), so truncating property", sub_buffer); full_object.pp[x].l=8; } } } while (flag==0); sprintf(buffer,"[ Mb__%d",embedded_routine++); do { word(sub_buffer,w++); sprintf(buffer+strlen(buffer)," %s",sub_buffer); } while (sub_buffer[0]!=0); stack_line(buffer); return(-1); } static int attributes(int w) { int i, negate_flag; do { word(sub_buffer,w++); if (sub_buffer[0]==0) return(w-1); if ((strcmp(sub_buffer,"with")==0) || (strcmp(sub_buffer,",")==0) || (strcmp(sub_buffer,"class")==0)) return(w-1); if (sub_buffer[0]=='~') { negate_flag=1; i=find_symbol(sub_buffer+1); } else { negate_flag=0; i=find_symbol(sub_buffer); } if ((i==-1)||(stypes[i]!=7)) { error_named("No such attribute as",sub_buffer); return(w); } i=svals[i]; if (negate_flag==0) full_object.atts[i/8] = full_object.atts[i/8] | (1 << (7-i%8)); else full_object.atts[i/8] = full_object.atts[i/8] & ~(1 << (7-i%8)); } while (1==1); return(0); } static int classes(int w) { int i; zip *p; do { word(sub_buffer,w++); if (sub_buffer[0]==0) return(w-1); if ((strcmp(sub_buffer,",")==0) || (strcmp(sub_buffer,"with")==0) || (strcmp(sub_buffer,"has")==0)) return(w-1); i=find_symbol(sub_buffer); if ((i==-1)||(stypes[i]!=13)) { error_named("No such class as",sub_buffer); return(w); } classes_here[no_c_here++]=svals[i]; /* printf("Inheriting attrs from %d\n",svals[i]); */ p=(zip *)classes_at[svals[i]-1]; for (i=0; i<6; i++) full_object.atts[i] |= p[i]; /* for (i=0; i<6; i++) printf("Data %d %x\n",i,p[i]); */ } while (1==1); return(0); } static int write_properties(zip *p, char *shortname) { int i, l, j, k, count, number; zip *tmp; zip *from; int32 props=0; if (class_flag==0) { for (i=0;i<6;i++) objects[no_objects].atts[i]=full_object.atts[i]; tmp=translate_text(p+1,shortname); props=subtract_pointers(tmp,p); p[0]=(props-1)/2; } else { p=class_pointer+classes_size; classes_at[no_classes]=(int32 *) p; /* printf("Class data at %08x\n",p); */ for (i=0;i<6;i++) p[i]=full_object.atts[i]; p+=6; } for (l=0; l2) count=from[j++]%64; } /* printf("Inheriting no %d count %d\n",number,count); */ for (k=0; k0; l--) { for (j=0; j= MAX_CLASS_TABLE_SIZE) memoryerror("MAX_CLASS_TABLE_SIZE",MAX_CLASS_TABLE_SIZE); } else { properties_size+=props; if (properties_size >= MAX_PROP_TABLE_SIZE) memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE); } return(props); } static char shortname_buffer[256]; extern void finish_object(void) { int j; if (class_flag == 0) { j=objects[no_objects].propsize; objects[no_objects].propsize= write_properties((zip *) (properties_table+properties_size), shortname_buffer); if (pass_number==2) { if (j != objects[no_objects].propsize) { error("Object has altered in memory usage between passes: \ perhaps an attempt to use a routine name as value of a small property"); } } no_objects++; if (pass_number==1) max_no_objects++; } else { write_properties(NULL,NULL); no_classes++; } if (debugging_file==1) { write_present_linenum(); } } extern void resume_object(char *b, int j) { int flag=0, commas=0; if (j==1) { word(b,1); flag=1; if ((strcmp(b,"has")==0) || (strcmp(b,",")==0) || (strcmp(b,"class")==0) || (strcmp(b,"with")==0)) flag=0; } do { RO_Comma: if (flag==0) { word(b,j++); if (b[0]==0) { if (commas>0) error("Object/class definition finishes with ','"); break; } } if (strcmp(b,",")==0) { commas++; goto RO_Comma; } if (commas>1) error("Two commas ',' in a row in object/class definition"); commas=0; if ((flag==1)||(strcmp(b,"with")==0)) { j=properties(j); if (j==-1) { resobj_flag=1; return; } } else if (strcmp(b,"has")==0) j=attributes(j); else if (strcmp(b,"class")==0) j=classes(j); else error_named("Expected 'with', 'has' or \ 'class' in object/class definition but found",b); flag=0; } while (1==1); finish_object(); } extern void make_class(char *b) { class_flag = 1; no_c_here=0; if (no_classes==MAX_CLASSES) memoryerror("MAX_CLASSES", MAX_CLASSES); word(b,2); new_symbol(b,no_classes+1,13); if (debugging_file==1) { write_debug_byte(2); write_debug_linenum(); write_debug_string(b); } full_object.l=0; full_object.atts[0]=0; full_object.atts[1]=0; full_object.atts[2]=0; full_object.atts[3]=0; full_object.atts[4]=0; full_object.atts[5]=0; resume_object(b,3); } static int near_obj; extern void make_object(char *b, int nearby_flag) { int i, j, k, non=0, later, subof; if (no_objects==MAX_OBJECTS) memoryerror("MAX_OBJECTS", MAX_OBJECTS); class_flag = 0; no_c_here=0; word(b,2); if (b[0]=='\"') { textword(b,2); error_named( "Expected an (internal) name for object, but found the string", b); sprintf(b,"failedobj"); } new_symbol(b,no_objects+1,9); if (debugging_file==1) { write_debug_byte(3); write_debug_byte((no_objects+1)/256); write_debug_byte((no_objects+1)%256); write_debug_linenum(); write_debug_string(b); } do { word(b,3+non); if (b[0]!='\"') { new_symbol(b,no_objects+1,9); non++; obsolete_warning("an object should only have one internal name"); } } while (b[0]!='\"'); later=non+5; if (nearby_flag==0) { word(b,4+non); subof=0; if ((b[0]==0) || (strcmp(b,",")==0) || (strcmp(b,"with")==0) || (strcmp(b,"has")==0) || (strcmp(b,"class")==0)) later--; else { i=find_symbol(b); if (i<0) { error_named("An object must be defined \ after the one which contains it: (so far) there is no such object as",b); return; } if (stypes[i]!=9) { error_named("Not an object:",b); return; } subof=svals[i]; } near_obj=no_objects+1; } else { subof=near_obj; later--; } full_object.atts[0]=0; full_object.atts[1]=0; full_object.atts[2]=0; full_object.atts[3]=0; full_object.atts[4]=0; full_object.atts[5]=0; objects[no_objects].parent=subof; objects[no_objects].next=0; objects[no_objects].child=0; full_object.l=0; if (subof>0) { j=subof-1; k=objects[j].child; if (k==0) { objects[j].child=no_objects+1; } else { while(objects[k-1].next!=0) { k=objects[k-1].next; } objects[k-1].next=no_objects+1; } } textword(b,3+non); if ((listobjects_mode==1) && ((pass_number==2)||(bothpasses_mode==1))) printf("%3d \"%s\"\n",no_objects+1,b); strcpy(shortname_buffer,b); resume_object(b, later); } /* ------------------------------------------------------------------------- */ /* Making and initialising variables and arrays */ /* ------------------------------------------------------------------------- */ #define NON_VALUE (int32)0x100000L extern void check_globals(void) { int i; for (i=0;i=256) error("A 'string' array can have at most 256 entries"); table_init[array_base] = i; } } globals_size+=i*multiplier; } static void array_entry(int32 i, int32 j, char *b) { if (globals_size+i*multiplier >= MAX_STATIC_DATA) memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA); if (multiplier==1) { table_init[globals_size+i]=j; if ((pass_number==2)&&(j>=256)) warning_named("Array entry too large for a byte:",b); } else { table_init[globals_size+2*i]=j/256; table_init[globals_size+2*i+1]=j%256; } } extern void assemble_table(char *b, int from) { int32 j; int i; for (i=from;1==1;i++) { word(b,i); if (b[0]==0) return; if (strcmp(b,"]")==0) { finish_array(table_posn); return; } if (strcmp(b,"[")==0) { stack_line("]"); error("Expected ']' but found '['"); return; } j=constant_value(b); array_entry(table_posn++, j, b); } return; } extern void make_global(char *b, int array_flag) { int32 i, j; int array_type, data_type, one_word; word(b,2); if (array_flag==0) { if (no_globals==235) { error("All 235 global variables already declared"); return; } if (pass_number==1) { new_symbol(b,no_globals,2); if (debugging_file==1) { write_debug_byte(4); write_debug_byte(no_globals); write_debug_string(b); } } else { i=find_symbol(b); no_globals=svals[i]; } gvalues[no_globals]=0; no_globals++; } else { IfPass2 { j=find_symbol(b); svals[j]=variables_offset+globals_size; } else new_symbol(b,0x800+globals_size,8); } word(b,3); if (b[0]==0) { if (array_flag==1) error("Missing array definition"); return; } if ((pass_number==1) && (array_flag==0)) gvalues[no_globals-1]=NON_VALUE; if ((strcmp(b,"=")==0) && (array_flag==0)) { word(b,4); i=constant_value(b); if (pass_number==2) gvalues[no_globals-1]=i; return; } if ((pass_number==2) && (array_flag==0)) gvalues[no_globals-1]=globals_size+variables_offset; array_type=0; data_type=-1; if ((array_flag==0)&&(strcmp(b,"data")==0)) { data_type=0; } else if ((array_flag==0)&&(strcmp(b,"initial")==0)) { data_type=1; } else if ((array_flag==0)&&(strcmp(b,"initstr")==0)) { data_type=2; } else if (strcmp(b,"->")==0) array_type=0; else if (strcmp(b,"-->")==0) array_type=1; else if (strcmp(b,"string")==0) array_type=2; else if (strcmp(b,"table")==0) array_type=3; else { if (array_flag==0) error_named("Expected '=', '->', '-->', 'string' or 'table' but found",b); else error_named("Expected '->', '-->', 'string' or 'table' but found",b); return; } multiplier=1; if ((array_type==1) || (array_type==3)) multiplier=2; word(b,5); one_word=0; if (b[0]==0) one_word=1; word(b,4); if (b[0]==0) { error("Missing array definition"); return; } switch(data_type) { case -1: if (b[0]=='[') data_type=3; else { if (one_word==1) { if (b[0]=='\"') data_type=2; else data_type=0; } else data_type=1; } break; case 0: obsolete_warning("use '->' instead of 'data'"); break; case 1: obsolete_warning("use '->' instead of 'initial'"); break; case 2: obsolete_warning("use '->' instead of 'initstr'"); break; } array_base=globals_size; if ((array_type==2) || (array_type==3)) globals_size+=multiplier; switch(data_type) { case 0: word(b,4); j=constant_value(b); for (i=0; i0) { sprintf(buffer, "Story file exceeds version-%d limit (%dK) by %d bytes", version_number, limit, excess); fatalerror(buffer); } extend_offset=256; if (no_objects+5 > extend_offset) extend_offset=no_objects+5; if (extend_memory_map==1) code_offset = extend_offset*scale_factor; else code_offset = code; if (extend_memory_map==1) strings_offset = code_offset + (strs-code); else strings_offset = strs; dictionary_offset = dict; variables_offset = vars; actions_offset = actshere; preactions_offset = preactshere; j=Out_Size/scale_factor; p[26]=j/256; p[27]=j%256; p[28]=0; p[29]=0; for (i=0; i= 512) { k_long++; k_str=""; } else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; } rate=total_bytes_trans*1000/total_chars_trans; if ((pass_number==2)||(bothpasses_mode==1)) { printf("Input %d lines (%d statements, %d chars)", total_source_line,internal_line,marker_in_file); if (total_files_read > 1) { printf(" from %d files", total_files_read); } printf( "\nVersion %d (%s) story file\n\ %4d objects (maximum %3d) %4d dictionary entries (maximum %d)\n\ %4d attributes (maximum %2d) %4d properties (maximum %2d)\n\ %4d adjectives (maximum 240) %4d verbs (maximum %d)\n\ %4d actions (maximum %3d) %4d abbreviations (maximum %d)\n", actual_version, version_name(actual_version), no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)), dict_entries, MAX_DICT_ENTRIES, no_attributes, ((version_number==3)?32:48), no_properties-2, ((version_number==3)?30:62), no_adjectives, no_verbs, MAX_VERBS, no_actions, MAX_ACTIONS, no_abbrevs, MAX_ABBREVS); printf( "%4d globals (maximum 240) %4d variable space (maximum %d)\n\ %4d symbols (maximum %4d) %4d routines (maximum %d)\n\ %4d classes (maximum %2d) %4d fake actions (unlimited)\n\ %4ld characters of text (compressed to %ld bytes, rate 0.%3ld)\n\ Output story file is %3ld%sK long (maximum %ldK)\n", no_globals, globals_size, MAX_STATIC_DATA, no_symbols, MAX_SYMBOLS, no_routines, MAX_ROUTINES, no_classes, MAX_CLASSES, no_fake_actions, (long int) total_chars_trans, (long int) total_bytes_trans, (long int) rate, (long int) k_long, k_str, (long int) limit); } } if ((debugging_file==1)&&(pass_number==2)) { debug_pass=2; write_debug_byte(13); write_debug_address(vars+480); write_debug_address(parsat); write_debug_address(dict); write_debug_address(code); write_debug_address(strs); debug_pass=1; } if (offsets_mode==1) { if ((pass_number==2)||(bothpasses_mode==1)) { printf( "\nOffsets in story file:\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\n", (long int) synsat, (long int) glpat, (long int) objat, (long int) propat, (long int) vars, (long int) parsat, (long int) actshere, (long int) preactshere, (long int) adjectives_offset, (long int) dict, (long int) code, (long int) strs); } } if (memory_map_mode==1) { if ((pass_number==2)||(bothpasses_mode==1)) { printf("Dynamic +---------------------+ 00000\n"); printf("memory | header |\n"); printf(" +---------------------+ 00040\n"); printf(" | synonym strings |\n"); printf(" + - - - - - - - - - - + %05lx\n", (long int) synsat); printf(" | synonym table |\n"); printf(" +---------------------+ %05lx\n", (long int) glpat); printf(" | property defaults |\n"); printf(" + - - - - - - - - - - + %05lx\n", (long int) objat); printf(" | objects |\n"); printf(" + - - - - - - - - - - + %05lx\n", (long int) propat); printf(" | object short names |\n"); printf(" | and properties |\n"); printf(" +---------------------+ %05lx\n", (long int) vars); printf(" | global variables |\n"); printf(" + - - - - - - - - - - + %05lx\n", ((long int) vars)+480L); printf(" | arrays |\n"); printf(" +=====================+ %05lx\n", (long int) parsat); printf("Static | grammar table |\n"); printf("cached + - - - - - - - - - - + %05lx\n", (long int) actshere); printf("data | actions |\n"); printf(" + - - - - - - - - - - + %05lx\n", (long int) preactshere); printf(" | preactions |\n"); printf(" + - - - - - - - - - - + %05lx\n", (long int) adjectives_offset); printf(" | adjectives |\n"); printf(" +---------------------+ %05lx\n", (long int) dict); printf(" | dictionary |\n"); printf(" +---------------------+ %05lx\n", (long int) code); printf("Static | Z-code |\n"); printf("paged +---------------------+ %05lx\n", (long int) strs); printf("data | strings |\n"); printf(" +---------------------+ %05lx\n", (long int) Out_Size); } } if (percentages_mode==1) { if ((pass_number==2)||(bothpasses_mode==1)) { printf("Approximate percentage breakdown of story file:\n"); percentage("Z-code",code_length,Out_Size); percentage("Static strings",strings_length,Out_Size); percentage("Dictionary",code-dict,Out_Size); percentage("Objects",vars-glpat,Out_Size); percentage("Globals",parsat-vars,Out_Size); percentage("Parsing tables",dict-parsat,Out_Size); percentage("Header and synonyms",glpat,Out_Size); percentage("Total of save area",parsat,Out_Size); percentage("Total of text",total_bytes_trans,Out_Size); } } if (frequencies_mode==1) { if ((pass_number==2)||(bothpasses_mode==1)) { printf("How frequently abbreviations were used, and roughly\n"); printf("how many bytes they saved: ('_' denotes spaces)\n"); for (i=0; i