home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / games / inform / compiler / source / c / tables < prev    next >
Encoding:
Text File  |  1994-10-10  |  48.6 KB  |  1,466 lines

  1. /* ------------------------------------------------------------------------- */
  2. /*   "tables" :  Maintains tables of dictionary, objects, actions,           */
  3. /*               grammar and global variables;                               */
  4. /*               and constructs the tables part of the story file            */
  5. /*                                                                           */
  6. /*   Part of Inform release 5                                                */
  7. /*                                                                           */
  8. /* ------------------------------------------------------------------------- */
  9.  
  10. #include "header.h"
  11.  
  12. int no_attributes, no_properties, no_globals=0, no_fake_actions=0;
  13. int dict_entries;
  14. int release_number=1, statusline_flag=0;
  15.  
  16. int time_set=0;
  17. char time_given[7];
  18.  
  19. int globals_size, properties_size;
  20.  
  21. int32 prop_defaults[64];
  22. int prop_longflag[64];
  23. int prop_additive[64];
  24. char *properties_table;
  25.  
  26. int max_no_objects=0;
  27.  
  28. int resobj_flag = 0;
  29.  
  30. static int no_verbs=0, no_actions=0, no_adjectives=0,
  31.            no_objects=0, no_classes=0, classes_size=0;
  32. static int no_gconstants=0, fp_no_actions=0;
  33. static int embedded_routine = 0;
  34.  
  35. static fpropt full_object;
  36.  
  37. /* ------------------------------------------------------------------------- */
  38. /*   Arrays used by this file                                                */
  39. /* ------------------------------------------------------------------------- */
  40.  
  41. #ifndef ALLOCATE_BIG_ARRAYS
  42.   static verbt   vs[MAX_VERBS];
  43.   static objectt objects[MAX_OBJECTS];
  44.   static int     table_init[MAX_STATIC_DATA];
  45.   static int32   actions[MAX_ACTIONS],
  46.                  preactions[MAX_ACTIONS],
  47.                  adjectives[MAX_ADJECTIVES];
  48.   static dict_word adjcomps[MAX_ADJECTIVES];
  49.   static int32   gvalues[240];
  50.   static int     gflags[240];
  51.   static int     dict_places_list[MAX_DICT_ENTRIES],
  52.                  dict_places_back[MAX_DICT_ENTRIES],
  53.                  dict_places_inverse[MAX_DICT_ENTRIES];
  54.   static dict_word dict_sorts[MAX_DICT_ENTRIES];
  55.   static zip     class_pointer[MAX_CLASS_TABLE_SIZE];
  56.   static int     classes_here[MAX_CLASSES];
  57.   static int32  *classes_at[MAX_CLASSES];
  58.   static int32   gcs[MAX_GCONSTANTS],
  59.                  gcvals[MAX_GCONSTANTS];
  60. #else
  61.   static verbt   *vs;
  62.   static objectt *objects;
  63.   static int     *table_init;
  64.   static int32   *actions,
  65.                  *preactions,
  66.                  *adjectives;
  67.   static dict_word *adjcomps;
  68.   static int32   *gvalues;
  69.   static int     *gflags;
  70.   static int     *dict_places_list,
  71.                  *dict_places_back,
  72.                  *dict_places_inverse;
  73.   static dict_word *dict_sorts;
  74.   static int     *classes_here;
  75.   static int32   **classes_at;
  76.   static zip     *class_pointer;
  77.   static int32   *gcs,
  78.                  *gcvals;
  79. #endif
  80.  
  81. static char *verblist;
  82. static char *verblist_p;
  83.  
  84. extern void tables_allocate_arrays(void)
  85. {   
  86. #ifdef ALLOCATE_BIG_ARRAYS
  87.     vs         = my_calloc(sizeof(verbt),   MAX_VERBS, "verbs");
  88.     objects    = my_calloc(sizeof(objectt), MAX_OBJECTS, "objects");
  89.     table_init = my_calloc(sizeof(int),     MAX_STATIC_DATA, "static data");
  90.     actions    = my_calloc(sizeof(int32),   MAX_ACTIONS, "actions");
  91.     preactions = my_calloc(sizeof(int32),   MAX_ACTIONS, "preactions");
  92.     adjectives = my_calloc(sizeof(int32),   MAX_ADJECTIVES, "adjectives");
  93.     adjcomps   = my_calloc(sizeof(dict_word), MAX_ADJECTIVES, "adj comps");
  94.     gvalues    = my_calloc(sizeof(int32),   240, "global values");
  95.     gflags     = my_calloc(sizeof(int),     240, "global flags");
  96.     dict_places_list = my_calloc(sizeof(int),  MAX_DICT_ENTRIES,
  97.                                                "dictionary places list");
  98.     dict_places_back = my_calloc(sizeof(int),  MAX_DICT_ENTRIES,
  99.                                                "dictionary places back");
  100.     dict_places_inverse = my_calloc(sizeof(int),  MAX_DICT_ENTRIES,
  101.                                                "inverse of dictionary places");
  102.     dict_sorts = my_calloc(sizeof(dict_word),   MAX_DICT_ENTRIES,
  103.                                                "dictionary sort codes");
  104.     class_pointer = my_malloc(MAX_CLASS_TABLE_SIZE, "class table");
  105.     classes_here = my_calloc(sizeof(int), MAX_CLASSES,
  106.                                                "inherited classes list");
  107.     classes_at = my_calloc(sizeof(int32), MAX_CLASSES,
  108.                                                "pointers to classes");
  109.     gcs = my_calloc(sizeof(int32), MAX_GCONSTANTS, "global constants");
  110.     gcvals = my_calloc(sizeof(int32), MAX_GCONSTANTS,
  111.                                                "global constant values");
  112. #endif
  113.     verblist = my_malloc(2000, "register of verbs");
  114.     verblist_p = verblist;
  115. }
  116.  
  117. extern void tables_free_arrays(void)
  118. {   
  119. #ifdef ALLOCATE_BIG_ARRAYS
  120.     my_free(vs, "verbs");
  121.     my_free(objects, "objects");
  122.     my_free(table_init, "static data");
  123.     my_free(actions, "actions");
  124.     my_free(preactions, "preactions");
  125.     my_free(adjectives, "adjectives");
  126.     my_free(adjcomps, "adj comps");
  127.     my_free(gvalues, "global values");
  128.     my_free(gflags, "global flags");
  129.     my_free(dict_places_list, "dictionary places list");
  130.     my_free(dict_places_back, "dictionary places back");
  131.     my_free(dict_places_inverse, "inverse of dictionary places");
  132.     my_free(dict_sorts, "dictionary sort codes");
  133.     my_free(classes_here, "inherited classes list");
  134.     my_free(classes_at, "pointers to classes");
  135.     my_free(gcs, "global constants");
  136.     my_free(gcvals, "global constant values");
  137. #endif
  138. }
  139.  
  140. /* ------------------------------------------------------------------------- */
  141. /*  A routine using an unusual ANSI library function:                        */
  142. /*                                                                           */
  143. /*  write_serialnumber writes today's date in the form YYMMDD as a string    */
  144. /*    (as can be seen, the VAX doesn't know it)                              */
  145. /* ------------------------------------------------------------------------- */
  146.  
  147. static void write_serialnumber(char *buffer)
  148. {   time_t tt;  tt=time(0);
  149.     if (time_set==0)
  150. #ifdef TIME_UNAVAILABLE
  151.       sprintf(buffer,"940000");
  152. #else
  153.       strftime(buffer,10,"%y%m%d",localtime(&tt));
  154. #endif
  155.     else
  156.       sprintf(buffer,"%06s",time_given);
  157. }
  158.  
  159. /* ------------------------------------------------------------------------- */
  160. /*   Dictionary table builder                                                */
  161. /*   The dictionary is, so to speak, thumb-indexed: the beginning of each    */
  162. /*   letter in the double-linked-list is marked.  Experiments with           */
  163. /*   increasing the number of markers (to the first two letters, say) result */
  164. /*   in extra bureaucracy which cancels out any speed gain.                  */
  165. /* ------------------------------------------------------------------------- */
  166.  
  167. #define NUMBER_DICT_MARKERS 26
  168.  
  169. static int total_dict_entries;
  170. static dict_word letter_keys[NUMBER_DICT_MARKERS];
  171. static int letter_starts[NUMBER_DICT_MARKERS];
  172. static int start_list;
  173. static dict_word prepared_sort;
  174. static int initial_letter;
  175.  
  176. static void dictionary_begin_pass(void)
  177. {   int i, j;
  178.     dict_p=dictionary+7;
  179.     total_dict_entries=dict_entries; dict_entries=0;
  180.     if (pass_number==1)
  181.     {   start_list=0; dict_places_list[0]= -2; dict_places_back[0]= -1;
  182.         for (i=0; i<NUMBER_DICT_MARKERS; i++)
  183.         {   letter_keys[i].b[0]=0xff;
  184.             letter_starts[i]= -1;
  185.         }
  186.     }
  187.     else
  188.     {   for (j=start_list, i=0; i<total_dict_entries; i++)
  189.         {   dict_places_inverse[j]=i; j=dict_places_list[j]; }
  190.     }
  191. }
  192.  
  193. static int compare_sorts(dict_word d1, dict_word d2)
  194. {   int i;
  195.     for (i=0; i<6; i++) if (d1.b[i]!=d2.b[i]) return(d1.b[i]-d2.b[i]);
  196. /*  since memcmp(d1.b, d2.b, 6); doesn't work in the Unix port - ? */
  197.     return(0);
  198. }
  199.  
  200. static dict_word dictionary_prepare(char *dword)
  201. {   int i, j, k, wd[10]; int32 tot;
  202.     for (i=0, j=0; (i<9)&&(dword[j]!=0); i++, j++)
  203.     {   k=chars_lookup[(int) (dword[j])];
  204.         if ((k>=26)&&(k<2*26)) k=k-26;
  205.         if ((k/26)!=0) wd[i++]=3+(k/26);
  206.         wd[i]=6+(k%26);
  207.     }
  208.     for (; i<9; i++) wd[i]=5;
  209.     InV3 { wd[6]=5; wd[7]=5; wd[8]=5;
  210.            if ((wd[5]==3)||(wd[5]==4)) wd[5]=5;
  211.          }
  212.     InV5 { if ((wd[8]==3)||(wd[8]==4)) wd[8]=5; }
  213.  
  214.     initial_letter = wd[0]-6;
  215.     if (initial_letter<0)
  216.     {   error("Dictionary words must begin with a letter of the alphabet");
  217.         initial_letter=0;
  218.     }
  219.     /* Note... this doesn't depend on A to Z being contiguous in the
  220.        machine's character set  */
  221.  
  222.     tot = wd[2] + wd[1]*(1<<5) + wd[0]*(1<<10);
  223.     prepared_sort.b[1]=tot%0x100;
  224.     prepared_sort.b[0]=(tot/0x100)%0x100;
  225.     tot = wd[5] + wd[4]*(1<<5) + wd[3]*(1<<10);
  226.     prepared_sort.b[3]=tot%0x100;
  227.     prepared_sort.b[2]=(tot/0x100)%0x100;
  228.     tot = wd[8] + wd[7]*(1<<5) + wd[6]*(1<<10);
  229.     prepared_sort.b[5]=tot%0x100;
  230.     prepared_sort.b[4]=(tot/0x100)%0x100;
  231.     InV3 { prepared_sort.b[2]+=0x80; }
  232.     InV5 { prepared_sort.b[4]+=0x80; }
  233.  
  234.     return(prepared_sort);
  235. }
  236.  
  237. extern int dictionary_find(char *dword, int scope)
  238. {   int32 j, j2, k, jlim;
  239.     dict_word i;
  240.     i=dictionary_prepare(dword);
  241.     if (scope==1) jlim=dict_entries; else jlim=total_dict_entries;
  242.  
  243.     if (pass_number==1)
  244.     {   for (j=0; j<jlim; j++)
  245.             if (compare_sorts(i,dict_sorts[j])==0) return((int) j+1);
  246.         return(0);
  247.     }
  248.     if ((k=letter_starts[initial_letter])==-1) return(0);
  249.     j=initial_letter+1;
  250.     while ((j<NUMBER_DICT_MARKERS)&&((j2=letter_starts[j])==-1)) j++;
  251.     if (j==NUMBER_DICT_MARKERS) { j2= -2; }
  252.     while (k!=j2)
  253.     {
  254.         if ((compare_sorts(i,dict_sorts[k])==0)&&(k<jlim))
  255.             return(dict_places_inverse[k]+1);
  256.         k=dict_places_list[k];
  257.     }
  258.     return(0);
  259. }        
  260.  
  261. static void show_letter(int code)
  262. {
  263.     if (code<6) { printf("."); return; }
  264.     printf("%c",(alphabet[0])[code-6]);
  265. }
  266.  
  267. extern void show_dictionary(void)
  268. {   int i, j; char *p;
  269.     int res=((version_number==3)?4:6);
  270.     printf("Dictionary contains %d entries:\n",dict_entries);
  271.     for (i=0; i<dict_entries; i++)
  272.     {   p=dictionary+7+(3+res)*i;
  273.         if (dict_entries==0)
  274.           printf("Entry %03d (%03d > %03d) at %04x: ",
  275.             i,dict_places_back[i],dict_places_list[i],
  276.             dictionary_offset+7+(3+res)*i);
  277.         else
  278.           printf("Entry %03d at %04x: ",i,dictionary_offset+7+(3+res)*i);
  279.         show_letter( (((int) p[0])&0x7c)/4 );
  280.         show_letter( 8*(((int) p[0])&0x3) + (((int) p[1])&0xe0)/32 );
  281.         show_letter( ((int) p[1])&0x1f );
  282.         show_letter( (((int) p[2])&0x7c)/4 );
  283.         show_letter( 8*(((int) p[2])&0x3) + (((int) p[3])&0xe0)/32 );
  284.         show_letter( ((int) p[3])&0x1f );
  285.         printf("  ");
  286.         for (j=0; j<3+res; j++) printf("%02x ",p[j]);
  287.         printf("\n");
  288.     }
  289. }
  290.  
  291. extern int dictionary_add(char *dword, int x, int y, int z)
  292. {   int off, i, k, l; zip *p; dict_word pcomp, qcomp;
  293.     int res=((version_number==3)?4:6);
  294.  
  295.     if (dict_entries==MAX_DICT_ENTRIES)
  296.     {   memoryerror("MAX_DICT_ENTRIES",MAX_DICT_ENTRIES); }
  297.  
  298.     i=dictionary_find(dword,1);
  299.     if (i!=0)
  300.     {   p=dictionary+7+(i-1)*(3+res)+res;
  301.         p[0]=(p[0])|x; p[1]=(p[1])|y; p[2]=(p[2])|z;
  302.         return(dictionary_offset+7+(3+res)*(i-1));
  303.     }
  304.  
  305.     if (pass_number==1) i=dict_entries;
  306.     else { i=dict_places_inverse[dict_entries]; }
  307.  
  308.     off=(3+res)*i+7;
  309.     p=dictionary+off;
  310.  
  311.     p[0]=prepared_sort.b[0]; p[1]=prepared_sort.b[1];
  312.     p[2]=prepared_sort.b[2]; p[3]=prepared_sort.b[3];
  313.     InV5 { p[4]=prepared_sort.b[4]; p[5]=prepared_sort.b[5]; }
  314.  
  315.     p[res]=x; p[res+1]=y; p[res+2]=z;
  316.  
  317.     if (pass_number==1)
  318.     {   pcomp=prepared_sort;
  319.         if (dict_entries==0)
  320.         {   dict_places_list[0]= -2; dict_places_list[1]= -1;
  321.             goto PlaceFound;
  322.         }
  323.         l=initial_letter; do { k=letter_starts[l--]; } while ((l>=0)&&(k==-1));
  324.         if (k==-1) k=start_list;
  325.         for (; k!=-2; k=dict_places_list[k])
  326.         {   qcomp=dict_sorts[k];
  327.             if (compare_sorts(pcomp,qcomp)<0)
  328.             {   l=dict_places_back[k];
  329.                 if (l==-1)
  330.                 {   dict_places_list[dict_entries]=start_list;
  331.                     dict_places_back[dict_entries]= -1;
  332.                     dict_places_back[k]=dict_entries;
  333.                     start_list=dict_entries; goto PlaceFound;
  334.                 }
  335.                 dict_places_list[l]=dict_entries;
  336.                 dict_places_back[k]=dict_entries;
  337.                 dict_places_list[dict_entries]=k;
  338.                 dict_places_back[dict_entries]=l;
  339.                 goto PlaceFound;
  340.             }
  341.             l=k;
  342.         }
  343.         dict_places_list[l]=dict_entries;
  344.         dict_places_back[dict_entries]=l;
  345.         dict_places_list[dict_entries]= -2;
  346.         PlaceFound: dict_sorts[dict_entries]=pcomp;
  347.         if (compare_sorts(pcomp,letter_keys[initial_letter])<0)
  348.         {   letter_keys[initial_letter]=pcomp;
  349.             letter_starts[initial_letter]=dict_entries;
  350.         }        
  351.     }
  352.  
  353.     dict_entries++; dict_p+=res+3;
  354.     /* show_dictionary();  */
  355.     return(dictionary_offset+off);
  356. }
  357.  
  358. extern void list_object_tree(void)
  359. {   int i;
  360.     printf("obj   par nxt chl   Object tree:\n");
  361.     for (i=0; i<no_objects; i++)
  362.         printf("%3d   %3d %3d %3d\n",
  363.             i+1,objects[i].parent,objects[i].next, objects[i].child);
  364. }
  365.  
  366. extern void list_verb_table(void)
  367. {   int i, j, k;
  368.     for (i=0; i<no_verbs; i++)
  369.     {   printf("Verb entry %2d  [%d]\n",i,vs[i].lines);
  370.         for (j=0; j<vs[i].lines; j++)
  371.         {   for (k=0; k<8; k++) printf("%03d ",vs[i].l[j].e[k]);
  372.             printf("\n");
  373.         }
  374.     }
  375. }
  376.  
  377. /* ------------------------------------------------------------------------- */
  378. /*   Keep track of actions                                                   */
  379. /* ------------------------------------------------------------------------- */
  380.  
  381. static int make_action(int32 addr)
  382. {   int i;
  383.     if (no_actions>=MAX_ACTIONS)
  384.       memoryerror("MAX_ACTIONS",MAX_ACTIONS);
  385.     for (i=0; i<no_actions; i++) if (actions[i]==addr) return(i);
  386.     actions[no_actions]=addr; preactions[no_actions]= -1;
  387.     return(no_actions++);
  388. }
  389.  
  390. extern int find_action(int32 addr)
  391. {   int i;
  392.     for (i=0; i<fp_no_actions; i++) if (actions[i]==addr) return(i);
  393.     if (pass_number==2)
  394.         error("Action given in constant does not exist");
  395.     return(0);
  396. }
  397.  
  398. /* ------------------------------------------------------------------------- */
  399. /*   Parsing the grammar table, and making new adjectives and verbs          */
  400. /*   (see the documentation for what the verb table it makes looks like)     */
  401. /* ------------------------------------------------------------------------- */
  402.  
  403. static int make_adjective(char *c)
  404. {   int i; dict_word acomp;
  405.  
  406.     acomp=dictionary_prepare(c);
  407.     for (i=0; i<no_adjectives; i++)
  408.     {   if (compare_sorts(acomp,adjcomps[i])==0) return(0xff-i);
  409.     }
  410.     adjectives[no_adjectives]=dictionary_add(c,8,0,0xff-no_adjectives);
  411.     adjcomps[no_adjectives]=acomp;
  412.     return(0xff-no_adjectives++);
  413. }
  414.  
  415. static int find_verb(char *verb)
  416. {   char *p;
  417.     p=verblist;
  418.     while (p<verblist_p)
  419.     {   if (strcmp(verb, p+2)==0) return(p[1]);
  420.         p=p+p[0];
  421.     }
  422.     return(-1);
  423. }
  424.  
  425. static void register_verb(char *verb, int number)
  426. {   if (find_verb(verb)>=0)
  427.     {   error_named("Two different verb definitions refer to", verb);
  428.         return;
  429.     }
  430.     strcpy(verblist_p+2,verb);
  431.     verblist_p[1]=number;
  432.     verblist_p[0]=3+strlen(verb);
  433.     verblist_p += verblist_p[0];
  434. }
  435.  
  436. static int32 parsing_routines[64];
  437. static int no_prs;
  438. static int debug_acts_writ[256];
  439.  
  440. static int grammar_line(int verbnum, int line, int i, char *b)
  441. {   int j, l, flag=0; int32 k;
  442.     int vargs, vtokens, vinsert;
  443.  
  444.     if (line==MAX_LINES_PER_VERB)
  445.     {   error("Too many lines of grammar for verb: increase \
  446. #define MAX_LINES_PER_VERB"); return(0); }
  447.  
  448.         word(b,i++); flag=2;
  449.         if (b[0]==0) return(0);
  450.         if (strcmp(b,"*")!=0)
  451.         {   error_named("'*' divider expected, but found",b); return(0); }
  452.         vtokens=1; vargs=0; for (j=0; j<8; j++) vs[verbnum].l[line].e[j]=0;
  453.         do
  454.         {   word(b,i++);
  455.             if (b[0]==0) { error("'->' clause missing"); return(0); }
  456.             if (strcmp(b,"->")==0) break;
  457.             if (b[0]=='\"')
  458.             {   textword(b,i-1); vinsert=make_adjective(b);
  459.             }
  460.             else On_("noun")        { vargs++; vinsert=0; }
  461.             else On_("held")        { vargs++; vinsert=1; }
  462.             else On_("multi")       { vargs++; vinsert=2; }
  463.             else On_("multiheld")   { vargs++; vinsert=3; }
  464.             else On_("multiexcept") { vargs++; vinsert=4; }
  465.             else On_("multiinside") { vargs++; vinsert=5; }
  466.             else On_("creature")    { vargs++; vinsert=6; }
  467.             else On_("special")     { vargs++; vinsert=7; }
  468.             else On_("number")      { vargs++; vinsert=8; }
  469.             else On_("scope")
  470.                  {   word(b,i++);
  471.                      if (strcmp(b,"=")!=0)
  472.                      {   error_named("Expected '=' after 'scope' but found",b);
  473.                          return(0);
  474.                      }
  475.                      word(b,i++);
  476.                      j=find_symbol(b);
  477.                      if ((j<0) || (stypes[j]!=1))
  478.                      {   error_named("Expected routine after 'scope=' but found",b);
  479.                          return(0);
  480.                      }
  481.  
  482.                      for (l=0; (l<no_prs)
  483.                               && parsing_routines[l]!=svals[j]; l++) ;
  484.                      parsing_routines[l]=svals[j]; if (l==no_prs) no_prs++;
  485.                      vargs++; vinsert=l+80;
  486.                  }
  487.             else On_("=")
  488.                  {   if ((vtokens==0)||(vs[verbnum].l[line].e[vtokens-1]!=0))
  489.                      {   error("'=' is only legal here as 'noun=Routine'");
  490.                          return(0);
  491.                      }
  492.                      word(b,i++);
  493.                      j=find_symbol(b);
  494.                      if ((j<0) || (stypes[j]!=1))
  495.                      {   error_named("Expected routine after 'noun=' but found", b);
  496.                          return(0);
  497.                      }
  498.                      vtokens--;
  499.  
  500.                      for (l=0; (l<no_prs)
  501.                               && parsing_routines[l]!=svals[j]; l++) ;
  502.                      parsing_routines[l]=svals[j]; if (l==no_prs) no_prs++;
  503.                      vinsert=l+16;
  504.                  }
  505.             else
  506.             {   j=find_symbol(b);
  507.                 if ((j<0) || ((stypes[j]!=7)&&(stypes[j]!=1)))
  508.                 {   error_named("No such token as",b); return(0); }
  509.                 if (stypes[j]==7)
  510.                 {   vargs++; vinsert=svals[j]+128;
  511.                 }
  512.                 else
  513.                 {   vargs++;
  514.                     for (l=0; (l<no_prs)
  515.                               && parsing_routines[l]!=svals[j]; l++) ;
  516.                     parsing_routines[l]=svals[j]; if (l==no_prs) no_prs++;
  517.                     vinsert=l+48;
  518.                 }
  519.             }
  520.             vs[verbnum].l[line].e[vtokens]=vinsert;
  521.             vtokens++;
  522.         } while (1==1);
  523.  
  524.         word(b,i++);
  525.         j=strlen(b)-3;
  526.         if ((j<0)||(b[j]!='S')||(b[j+1]!='u')||(b[j+2]!='b'))
  527.             sprintf(b+j+3,"Sub");
  528.         j=find_symbol(b);
  529.         if ((j==-1)&&(pass_number==2))
  530.         {   error_named("No such action routine as",b);
  531.             return(0);
  532.         }
  533.         if (j==-1) k=0;
  534.         else
  535.         {   if (stypes[j]!=1) { error_named("Not an action:",b); return(0); }
  536.             k=svals[j];
  537.         }
  538.         vs[verbnum].l[line].e[0]=vargs;
  539.         vs[verbnum].l[line].e[7]=make_action(k);
  540.  
  541.         if ((debugging_file==1)&&(k!=0)
  542.             &&(debug_acts_writ[find_action(k)]==0))
  543.         {   debug_pass=2;
  544.             b[strlen(b)-3]=0;
  545.             write_debug_byte(8); write_debug_byte(find_action(k));
  546.             write_debug_string(b);
  547.             debug_pass=1;
  548.             if (pass_number==2) debug_acts_writ[find_action(k)]=1;
  549.         }
  550.  
  551.     return(i);
  552. }
  553.  
  554. extern void make_verb(char *b)
  555. {   int i, flag=0;
  556.     int lines=0;
  557.     i=2;
  558.     if (no_verbs==MAX_VERBS)
  559.         memoryerror("MAX_VERBS",MAX_VERBS);
  560.     word(b,i);
  561.     On_("meta") { i++; flag=2; }
  562.     do
  563.     {   word(b,i);
  564.         if (b[0]!='\"') break;
  565.         textword(b,i++);
  566.         dictionary_add(b,0x41+flag,0xff-no_verbs,0);
  567.         if (pass_number==1) register_verb(b,no_verbs);
  568.     } while (1==1);
  569.  
  570.     do
  571.     {   i=grammar_line(no_verbs, lines++,i,b);
  572.     } while (i!=0);
  573.  
  574.     vs[no_verbs].lines=--lines;
  575.     no_verbs++;
  576. }
  577.  
  578. extern void extend_verb(char *b)
  579. {   int i, j, k, lines, mode;
  580.     textword(b,2);
  581.     j=find_verb(b);
  582.     if (j==-1)
  583.     {   error_named("There is no previous grammar for the verb", b);
  584.         return;
  585.     }
  586.     i=3;
  587.     word(b,i); mode=3;
  588.     if (strcmp(b,"*")!=0)
  589.     {   mode=0;
  590.         if (strcmp(b,"replace")==0) mode=1;
  591.         if (strcmp(b,"first")==0) mode=2;
  592.         if (strcmp(b,"last")==0) mode=3;
  593.         if (mode==0)
  594.         {   error_named(
  595.                 "Expected 'replace', 'last' or 'first' but found",b);
  596.             mode=3;
  597.         }
  598.         i++;
  599.     }
  600.     if (mode==1) lines=0;
  601.     else lines=vs[j].lines;
  602.     do
  603.     {   if (mode==2)
  604.         {   lines=0;
  605.             for (k=vs[j].lines; k>0; k--)
  606.                  vs[j].l[k]=vs[j].l[k-1];
  607.             vs[j].lines++;
  608.         }
  609.         i=grammar_line(j, lines++,i,b);
  610.     } while (i!=0);
  611.  
  612.     if (mode!=2) vs[j].lines=--lines;
  613. }
  614.  
  615. /* ------------------------------------------------------------------------- */
  616. /*   Object manufacture.  Note that property lists are not kept for each     */
  617. /*   object, only written in game-file format and then forgotten; but the    */
  618. /*   object tree structure so far, is kept                                   */
  619. /* ------------------------------------------------------------------------- */
  620.  
  621. static int class_flag;
  622. static int no_c_here;
  623.  
  624. static int properties(int w)
  625. {   int i, k, x, y, pnw, flag=0; int32 j;
  626.  
  627.     do
  628.     {   pnw=w;
  629.         word(sub_buffer,w++);
  630.         if (sub_buffer[0]==0) return(w-1);
  631. /*        if (strcmp(sub_buffer,",")==0) return(w-1); */
  632.         if (strcmp(sub_buffer,"has")==0) return(w-1);
  633.         if (strcmp(sub_buffer,"class")==0) return(w-1);
  634.         i=find_symbol(sub_buffer);
  635.         if (i==-1)
  636.         {   error_named("No such property as",sub_buffer);
  637.             return(w);
  638.         }
  639.         if (stypes[i]!=12)
  640.         {   error_named("Not a property:",sub_buffer);
  641.             return(w);
  642.         }
  643.         i=svals[i];
  644.         x=full_object.l++;
  645.         full_object.pp[x].num=i;
  646.         y=0;
  647.         do
  648.         {   word(sub_buffer,w++);
  649.             if (strcmp(sub_buffer,",")==0) break;
  650.             if (strcmp(sub_buffer,"has")==0) { w--; break; }
  651.             if (strcmp(sub_buffer,"class")==0) { w--; break; }
  652.             if (sub_buffer[0]==0) break;
  653.  
  654.             if (strcmp(sub_buffer,"[")==0)
  655.             {   flag=1;
  656.                 sprintf(sub_buffer,"Mb__%d",embedded_routine);
  657.             }
  658.             if (i==1)
  659.             {   textword(sub_buffer,w-1);
  660.                 j=dictionary_add(sub_buffer,0x80,0,0);
  661.             }
  662.             else
  663.             {   if ((pass_number==2)&&(y!=0))
  664.                 {   k=find_symbol(sub_buffer);
  665.                     if ((k!=-1)&&(stypes[k]==12))
  666.                     {   warning_named(
  667.             "Missing ','?  Property data seems to contain the property name",
  668.                             sub_buffer);
  669.                     }
  670.                 }
  671.                 j=constant_value(sub_buffer);
  672.                 if (j==0)
  673.                 {   if (prop_defaults[i]>=256) j=0x1000;
  674.                 }
  675.             }
  676.             if ((j>=256)||(prop_longflag[i]==1))
  677.                 full_object.pp[x].p[y++]=j/256;
  678.             full_object.pp[x].p[y++]=j%256;
  679.         } while (flag==0);
  680.         full_object.pp[x].l=y;
  681.         InV3
  682.         {   if (y>8)
  683.             {   word(sub_buffer, pnw);
  684.                 if (pass_number==2)
  685.        warning_named("Standard-game limit of 8 bytes per property exceeded \
  686. (use Advanced to get 64), so truncating property", sub_buffer);
  687.                 full_object.pp[x].l=8;
  688.             }
  689.         }
  690.     } while (flag==0);
  691.     sprintf(buffer,"[ Mb__%d",embedded_routine++);
  692.     do
  693.     {   word(sub_buffer,w++);
  694.         sprintf(buffer+strlen(buffer)," %s",sub_buffer);
  695.     } while (sub_buffer[0]!=0);
  696.     stack_line(buffer);
  697.     return(-1);
  698. }
  699.  
  700. static int attributes(int w)
  701. {   int i, negate_flag;
  702.     do
  703.     {   word(sub_buffer,w++);
  704.         if (sub_buffer[0]==0) return(w-1);
  705.         if ((strcmp(sub_buffer,"with")==0)
  706.             || (strcmp(sub_buffer,",")==0)
  707.             || (strcmp(sub_buffer,"class")==0)) return(w-1);
  708.         if (sub_buffer[0]=='~')
  709.         {   negate_flag=1; i=find_symbol(sub_buffer+1); }
  710.         else
  711.         {   negate_flag=0; i=find_symbol(sub_buffer); }
  712.         if ((i==-1)||(stypes[i]!=7))
  713.         { error_named("No such attribute as",sub_buffer); return(w); }
  714.         i=svals[i];
  715.         if (negate_flag==0)
  716.             full_object.atts[i/8] =
  717.                 full_object.atts[i/8] | (1 << (7-i%8));
  718.         else
  719.             full_object.atts[i/8] =
  720.                 full_object.atts[i/8] & ~(1 << (7-i%8));
  721.     } while (1==1);
  722.     return(0);
  723. }
  724.  
  725. static int classes(int w)
  726. {   int i; zip *p;
  727.     do
  728.     {   word(sub_buffer,w++);
  729.         if (sub_buffer[0]==0) return(w-1);
  730.         if ((strcmp(sub_buffer,",")==0)
  731.             || (strcmp(sub_buffer,"with")==0)
  732.             || (strcmp(sub_buffer,"has")==0)) return(w-1);
  733.         i=find_symbol(sub_buffer);
  734.         if ((i==-1)||(stypes[i]!=13))
  735.         { error_named("No such class as",sub_buffer); return(w); }
  736.         classes_here[no_c_here++]=svals[i];
  737. /*        printf("Inheriting attrs from %d\n",svals[i]); */
  738.         p=(zip *)classes_at[svals[i]-1];
  739.         for (i=0; i<6; i++) full_object.atts[i] |= p[i];
  740. /*        for (i=0; i<6; i++) printf("Data %d  %x\n",i,p[i]); */
  741.     } while (1==1);
  742.     return(0);
  743. }
  744.  
  745. static int write_properties(zip *p, char *shortname)
  746. {   int i, l, j, k, count, number; char *tmp; zip *from;
  747.     int32 props=0;
  748.  
  749.     if (class_flag==0)
  750.     {   for (i=0;i<6;i++)
  751.             objects[no_objects].atts[i]=full_object.atts[i];
  752.  
  753.         tmp=translate_text(p+1,shortname);
  754.         props=subtract_pointers(tmp,p);
  755.         p[0]=(props-1)/2;
  756.     }
  757.     else
  758.     {   p=class_pointer+classes_size;
  759.         classes_at[no_classes]=(int32 *) p;
  760.         /* printf("Class data at %08x\n",p); */
  761.         for (i=0;i<6;i++) p[i]=full_object.atts[i];
  762.         p+=6;
  763.     }
  764.  
  765.     for (l=0; l<no_c_here; l++)
  766.     {   j=0; from=6+(zip *)classes_at[classes_here[l]-1];
  767.         /* printf("Inheriting from %d at %08x\n",classes_here[l],from); */
  768.  
  769.         /* for (j=0; j<32; j++) printf("%02x ",from[j]); printf("\n"); j=0; */
  770.  
  771.         while (from[j]!=0)
  772.         {   InV3
  773.             {   number=from[j]%32; count=1+from[j++]/32;
  774.             }
  775.             InV5
  776.             {   number=from[j]%64; count=1+from[j++]/64;
  777.                 if (count>2) count=from[j++]%64;
  778.             }
  779.             /* printf("Inheriting no %d count %d\n",number,count); */
  780.             for (k=0; k<full_object.l; k++)
  781.             {   if (full_object.pp[k].num == number)
  782.                 {   if ((number==1) || (prop_additive[number]!=0))
  783.                     {   /* printf("Appending %d\n",number); */
  784.                         for (i=full_object.pp[k].l;
  785.                              i<full_object.pp[k].l+count; i++)
  786.                             full_object.pp[k].p[i]=from[j++];
  787.                         full_object.pp[k].l += count;
  788.                     }
  789.                     else
  790.                     {   j+=count;
  791.                         /* printf("Ignoring %d\n",number); */
  792.                     }
  793.                     goto DunInheriting;
  794.                 }
  795.             }
  796.             k=full_object.l++;
  797.             full_object.pp[k].num = number;
  798.             full_object.pp[k].l = count;
  799.             for (i=0; i<count; i++)
  800.                 full_object.pp[k].p[i]=from[j++];
  801.             /* printf("Creating %d\n",number); */
  802.             DunInheriting: ;
  803.         }
  804.     }
  805.  
  806.     for (l=((version_number==3)?31:63); l>0; l--)
  807.     {   for (j=0; j<full_object.l; j++)
  808.         {   if (full_object.pp[j].num == l)
  809.             {   count=full_object.pp[j].l; number=full_object.pp[j].num;
  810.                 InV3
  811.                 {   p[props++] = number + (count - 1)*32;
  812.                 }
  813.                 InV5
  814.                 {   switch(count)
  815.                     {   case 1:
  816.                           p[props++] = number; break;
  817.                         case 2:
  818.                           p[props++] = number + 0x40; break;
  819.                         default:
  820.                           p[props++] = number + 0x80;
  821.                           p[props++] = count + 0x80;
  822.                           break;
  823.                     }
  824.                 }
  825.  
  826.                 for (k=0; k<full_object.pp[j].l; k++)
  827.                 {   p[props++]=full_object.pp[j].p[k];
  828.                 }
  829.             }
  830.         }
  831.     }
  832.  
  833.     p[props]=0; props++;
  834.  
  835.     if (class_flag==1)
  836.     {
  837.         classes_size+=props+6;
  838.         if (classes_size >= MAX_CLASS_TABLE_SIZE)
  839.             memoryerror("MAX_CLASS_TABLE_SIZE",MAX_CLASS_TABLE_SIZE);
  840.     }
  841.     else
  842.     {
  843.         properties_size+=props;
  844.         if (properties_size >= MAX_PROP_TABLE_SIZE)
  845.             memoryerror("MAX_PROP_TABLE_SIZE",MAX_PROP_TABLE_SIZE);
  846.     }
  847.  
  848.     return(props);
  849. }
  850.  
  851. static char shortname_buffer[256];
  852.  
  853. extern void finish_object(void)
  854. {   int j;
  855.     if (class_flag == 0)
  856.     {   j=objects[no_objects].propsize;
  857.         objects[no_objects].propsize=
  858.             write_properties((zip *) (properties_table+properties_size),
  859.             shortname_buffer);
  860.         if (pass_number==2)
  861.         {   if (j != objects[no_objects].propsize)
  862.             {   error("Object has altered in memory usage between passes: \
  863. perhaps an attempt to use a routine name as value of a small property");
  864.             }
  865.         }
  866.         no_objects++;
  867.         if (pass_number==1) max_no_objects++;
  868.     }
  869.     else { write_properties(NULL,NULL); no_classes++; }
  870.  
  871.     if (debugging_file==1)
  872.     {   write_present_linenum();
  873.     }
  874. }
  875.  
  876. extern void resume_object(char *b, int j)
  877. {   int flag=0, commas=0;
  878.     if (j==1)
  879.     {   word(b,1); flag=1;
  880.         if ((strcmp(b,"has")==0)
  881.             || (strcmp(b,",")==0)
  882.             || (strcmp(b,"class")==0)
  883.             || (strcmp(b,"with")==0)) flag=0;
  884.     }
  885.     do
  886.     {   RO_Comma:
  887.         if (flag==0)
  888.         {   word(b,j++);
  889.             if (b[0]==0)
  890.             {   if (commas>0)
  891.                     error("Object/class definition finishes with ','");
  892.                 break;
  893.             }
  894.         }
  895.         if (strcmp(b,",")==0) { commas++; goto RO_Comma; }
  896.         if (commas>1)
  897.             error("Two commas ',' in a row in object/class definition");
  898.         commas=0;
  899.         if ((flag==1)||(strcmp(b,"with")==0))
  900.         {   j=properties(j);
  901.             if (j==-1) { resobj_flag=1; return; }
  902.         }
  903.         else if (strcmp(b,"has")==0) j=attributes(j);
  904.         else if (strcmp(b,"class")==0) j=classes(j);
  905.         else error_named("Expected 'with', 'has' or \
  906. 'class' in object/class definition but found",b);
  907.         flag=0;
  908.     } while (1==1);
  909.     finish_object();
  910. }
  911.  
  912. extern void make_class(char *b)
  913. {   class_flag = 1; no_c_here=0;
  914.  
  915.     if (no_classes==MAX_CLASSES)
  916.         memoryerror("MAX_CLASSES", MAX_CLASSES);
  917.  
  918.     word(b,2); new_symbol(b,no_classes+1,13);
  919.  
  920.     if (debugging_file==1)
  921.     {   write_debug_byte(2); write_debug_linenum();
  922.         write_debug_string(b);
  923.     }
  924.   
  925.     full_object.l=0;
  926.     full_object.atts[0]=0;
  927.     full_object.atts[1]=0;
  928.     full_object.atts[2]=0;
  929.     full_object.atts[3]=0;
  930.     resume_object(b,3);
  931. }
  932.  
  933. static int near_obj;
  934.  
  935. extern void make_object(char *b, int nearby_flag)
  936. {   int i, j, k, non=0, later, subof;
  937.  
  938.     if (no_objects==MAX_OBJECTS)
  939.         memoryerror("MAX_OBJECTS", MAX_OBJECTS);
  940.     
  941.     class_flag = 0; no_c_here=0;
  942.  
  943.     word(b,2);
  944.     if (b[0]=='\"')
  945.     {   textword(b,2);
  946.         error_named(
  947.             "Expected an (internal) name for object, but found the string", b);
  948.         sprintf(b,"failedobj");
  949.     }
  950.     new_symbol(b,no_objects+1,9);
  951.     if (debugging_file==1)
  952.     {   write_debug_byte(3);
  953.         write_debug_byte((no_objects+1)/256);
  954.         write_debug_byte((no_objects+1)%256);
  955.         write_debug_linenum(); write_debug_string(b);
  956.     }
  957.  
  958.     do
  959.     {   word(b,3+non);
  960.         if (b[0]!='\"')
  961.         {   new_symbol(b,no_objects+1,9); non++;
  962.         }
  963.     } while (b[0]!='\"');
  964.     later=non+5;
  965.  
  966.     if (nearby_flag==0)
  967.     {   word(b,4+non);
  968.         subof=0;
  969.         if ((b[0]==0)
  970.             || (strcmp(b,",")==0)
  971.             || (strcmp(b,"with")==0)
  972.             || (strcmp(b,"has")==0)
  973.             || (strcmp(b,"class")==0)) later--;
  974.         else
  975.         {   i=find_symbol(b);
  976.             if (i<0)
  977.             {   error_named("An object must be defined \
  978. after the one which contains it: (so far) there is no such object as",b);
  979.                 return;
  980.             }
  981.             if (stypes[i]!=9)
  982.             {   error_named("Not an object:",b); return; }
  983.             subof=svals[i];
  984.         }
  985.         near_obj=no_objects+1;
  986.     }
  987.     else
  988.     {   subof=near_obj; later--;
  989.     }
  990.     full_object.atts[0]=0;
  991.     full_object.atts[1]=0;
  992.     full_object.atts[2]=0;
  993.     full_object.atts[3]=0;
  994.     full_object.atts[4]=0;
  995.     full_object.atts[5]=0;
  996.     objects[no_objects].parent=subof;
  997.     objects[no_objects].next=0;
  998.     objects[no_objects].child=0;
  999.     full_object.l=0;
  1000.  
  1001.     if (subof>0)
  1002.     {   j=subof-1; k=objects[j].child;
  1003.         if (k==0)
  1004.         {   objects[j].child=no_objects+1; }
  1005.         else
  1006.         {   while(objects[k-1].next!=0) { k=objects[k-1].next; }
  1007.             objects[k-1].next=no_objects+1;
  1008.         }
  1009.     }
  1010.  
  1011.     textword(b,3+non);
  1012.     if ((listobjects_mode==1) && ((pass_number==2)||(bothpasses_mode==1)))
  1013.         printf("%3d \"%s\"\n",no_objects+1,b);
  1014.     strcpy(shortname_buffer,b);
  1015.     resume_object(b, later);
  1016. }
  1017.  
  1018. /* ------------------------------------------------------------------------- */
  1019. /*   Making (and, which is trickier, initialising) globals and global arrays */
  1020. /* ------------------------------------------------------------------------- */
  1021.  
  1022. extern void fix_gconstants(char *globs)
  1023. {   int i;
  1024.     for (i=0; i<no_gconstants; i++)
  1025.         globs[gcs[i]]=gcvals[i];
  1026.  
  1027. extern void make_global(char *b)
  1028. {   int32 i, j; int iflag, sflag;
  1029.  
  1030.     if (pass_number>1) return;
  1031.  
  1032.     if (no_globals==235)
  1033.     {   error("All 235 global variables already declared");
  1034.         return;
  1035.     }
  1036.     word(b,2);
  1037.     new_symbol(b,no_globals,2);
  1038.  
  1039.     if (debugging_file==1)
  1040.     {   write_debug_byte(4); write_debug_byte(no_globals);
  1041.         write_debug_string(b);
  1042.     }
  1043.  
  1044.     no_globals++;
  1045.     word(b,3); iflag=0;
  1046.     if (b[0]==0) return;
  1047.     if (strcmp(b,"string")==0) sflag=1;
  1048.     else if (strcmp(b,"data")==0) sflag=0;
  1049.     else if (strcmp(b,"initial")==0) { sflag=0; iflag=1; }
  1050.     else if (strcmp(b,"initstr")==0) { sflag=0; iflag=2; }
  1051.     else
  1052.     {   if (strcmp(b,"=")!=0)
  1053.         { error_named("Expected 'string', 'data', 'initial', \
  1054. 'initstr' or '=' but found",b); return; }
  1055.         word(b,4); i=constant_value(b);
  1056.         gvalues[no_globals-1]=i; gflags[no_globals-1]=0;
  1057.         return;
  1058.     }
  1059.     if (iflag==0)
  1060.     {   word(b,4);
  1061.         i=constant_value(b);
  1062.     }
  1063.     if (iflag==1)
  1064.     {   i=0;
  1065.         do
  1066.         {   word(b,4+i); if (b[0]==0) break;
  1067.             j=constant_value(b); table_init[globals_size+i]=j; i++;
  1068.         } while (1==1);
  1069.     }
  1070.     if (iflag==2)
  1071.     {   textword(b,4);
  1072.         for (i=0; b[i]!=0; i++)
  1073.         {   j=b[i]; table_init[globals_size+i]=j;
  1074.         }
  1075.     }
  1076.     if (sflag==1)
  1077.     {
  1078.         if (no_gconstants==MAX_GCONSTANTS)
  1079.             memoryerror("MAX_GCONSTANTS", MAX_GCONSTANTS);
  1080.  
  1081.         gcs[no_gconstants]=globals_size; gcvals[no_gconstants++]=i++;
  1082.     }
  1083.     gvalues[no_globals-1]=globals_size;
  1084.     gflags[no_globals-1]=2;
  1085.     globals_size+=i;
  1086.  
  1087.     if (globals_size >= MAX_STATIC_DATA)
  1088.         memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA);
  1089. }
  1090.  
  1091. /* ------------------------------------------------------------------------- */
  1092. /*   Construct story file up as far as code area                             */
  1093. /*   (see documentation for description of what goes on here)                */
  1094. /* ------------------------------------------------------------------------- */
  1095.  
  1096. static void percentage(char *name, int32 x, int32 total)
  1097. {   printf("   %-20s %2d.%d%%\n",name,x*100/total,(x*1000/total)%10);
  1098. }
  1099.  
  1100. static int alloc_done_flag=0;
  1101.  
  1102. extern void construct_storyfile(void)
  1103. {   char *p; unsigned char *u; int32 i, j, k; int32 excess;
  1104.     int32 syns, objs, props, vars, parse, code, strs, dict, nparse,
  1105.         actshere, preactshere;
  1106.     int32 synsat, glpat, objat, propat, parsat;
  1107.     int32 code_length, strings_length, alloc_size;
  1108.     int32 limit;
  1109.  
  1110.     if (alloc_done_flag==0)
  1111.     {   alloc_done_flag=1;
  1112.         alloc_size=0x4000 + subtract_pointers(dict_p,dictionary);
  1113.         for (i=0; i<no_objects; i++) alloc_size+=objects[i].propsize;
  1114.         output_p=my_malloc(alloc_size, "output buffer");
  1115.     }
  1116.  
  1117.     p=output_p; u=(unsigned char *) p;
  1118.  
  1119.     for (i=0; i<=0x3f; i++) p[i]=0;
  1120.  
  1121.     p[0]=actual_version; p[1]=statusline_flag*2;
  1122.     p[2]=(release_number/256); p[3]=(release_number%256);
  1123.     p[16]=0; p[17]=0;
  1124.  
  1125.     write_serialnumber(buffer);
  1126.     for (i=0; i<6; i++) p[18+i]=buffer[i];
  1127.  
  1128.     syns=0x40;
  1129.     u[syns]=0x80; p[syns+1]=0; syns+=2;
  1130.     for (i=0; i+low_strings<low_strings_p; syns++, i++)
  1131.         p[0x42+i]=low_strings[i];
  1132.  
  1133.     p[24]=syns/256; p[25]=syns%256; synsat=syns;
  1134.     for (i=0; i<3*32; i++)
  1135.     {   p[syns++]=0; p[syns++]=0x20;
  1136.     }
  1137.  
  1138.     for (i=0; i<no_abbrevs; i++)
  1139.     {   j=abbrev_values[i];
  1140.         p[synsat+64+2*i]=j/256;
  1141.         p[synsat+65+2*i]=j%256;
  1142.     }
  1143.     objs=syns;
  1144.  
  1145.     p[10]=objs/256; p[11]=objs%256; glpat=objs;
  1146.     p[objs]=0; p[objs+1]=0;
  1147.  
  1148.     for (i=2; i< ((version_number==3)?32:64); i++)
  1149.     {   p[objs+2*i-2]=prop_defaults[i]/256;
  1150.         p[objs+2*i-1]=prop_defaults[i]%256;
  1151.     }
  1152.     objs+=2*i-2;
  1153.     props=objs+((version_number==3)?9:14)*no_objects;
  1154.     objat=objs; propat=props;
  1155.  
  1156.     for (i=0; i<properties_size; i++)
  1157.         p[props+i]=properties_table[i];
  1158.  
  1159.     for (i=0; i<no_objects; i++)
  1160.     {
  1161.         InV3
  1162.         {   p[objs]=objects[i].atts[0];
  1163.             p[objs+1]=objects[i].atts[1];
  1164.             p[objs+2]=objects[i].atts[2];
  1165.             p[objs+3]=objects[i].atts[3];
  1166.             p[objs+4]=objects[i].parent;
  1167.             p[objs+5]=objects[i].next;
  1168.             p[objs+6]=objects[i].child;
  1169.             p[objs+7]=props/256;
  1170.             p[objs+8]=props%256;
  1171.             objs+=9;
  1172.         }
  1173.         InV5
  1174.         {   p[objs]=objects[i].atts[0];
  1175.             p[objs+1]=objects[i].atts[1];
  1176.             p[objs+2]=objects[i].atts[2];
  1177.             p[objs+3]=objects[i].atts[3];
  1178.             p[objs+4]=objects[i].atts[4];
  1179.             p[objs+5]=objects[i].atts[5];
  1180.             p[objs+6]=(objects[i].parent)/256;
  1181.             p[objs+7]=(objects[i].parent)%256;
  1182.             p[objs+8]=(objects[i].next)/256;
  1183.             p[objs+9]=(objects[i].next)%256;
  1184.             p[objs+10]=(objects[i].child)/256;
  1185.             p[objs+11]=(objects[i].child)%256;
  1186.             p[objs+12]=props/256;
  1187.             p[objs+13]=props%256;
  1188.             objs+=14;
  1189.         }
  1190.         props+=objects[i].propsize;
  1191.     }
  1192.  
  1193.     vars=props;
  1194.  
  1195.     p[12]=(vars/256); p[13]=(vars%256);
  1196.  
  1197.     for (i=vars; i<vars+globals_size; i++) p[i]=table_init[i-vars];
  1198.  
  1199.     parse=vars+globals_size;
  1200.  
  1201.     p[14]=(parse/256); p[15]=(parse%256);  parsat=parse;
  1202.     nparse=parse+no_verbs*2;
  1203.     for (i=0; i<no_verbs; i++)
  1204.     {   p[parse]=(nparse/256); p[parse+1]=(nparse%256);
  1205.         parse+=2;
  1206.         p[nparse]=vs[i].lines; nparse++;
  1207.         for (j=0; j<vs[i].lines; j++)
  1208.         {   for (k=0; k<8; k++) p[nparse+k]=vs[i].l[j].e[k];
  1209.             nparse+=8;
  1210.         }
  1211.     }
  1212.  
  1213.     actshere=nparse; nparse+=2*no_actions;
  1214.     preactshere=nparse; nparse+=2*no_actions;
  1215.  
  1216.     p[nparse]=0; p[nparse+1]=no_adjectives; nparse+=2;
  1217.  
  1218.     dict=nparse+4*no_adjectives;
  1219.  
  1220.     adjectives_offset=nparse;
  1221.  
  1222.     for (i=0; i<no_adjectives; i++)
  1223.     {   j=adjectives[no_adjectives-i-1];
  1224.         p[nparse]=j/256; p[nparse+1]=j%256; p[nparse+2]=0;
  1225.         p[nparse+3]=(256-no_adjectives+i); nparse+=4;
  1226.     }
  1227.  
  1228.     dictionary[0]=3; dictionary[1]='.'; dictionary[2]=','; dictionary[3]='"';
  1229.     dictionary[4]=(version_number==3)?7:9;
  1230.     dictionary[5]=(dict_entries/256); dictionary[6]=(dict_entries%256);
  1231.  
  1232.     p[8]=(dict/256);     p[9]=(dict%256);
  1233.     for (i=0; i+dictionary<dict_p; i++) p[dict+i]=dictionary[i];
  1234.     code=dict+i;
  1235.     while ((code%scale_factor) != 0) p[code++]=0;
  1236.  
  1237.     p[4]=(code/256);     p[5]=(code%256);
  1238.     p[6]=((code+1)/256); p[7]=((code+1)%256);
  1239.  
  1240.     Write_Code_At = code;
  1241.     code_length=subtract_pointers(zcode_p,zcode);
  1242.  
  1243.     strs=code+code_length;
  1244.     while ((strs%scale_factor) != 0) strs++;
  1245.  
  1246.     Write_Strings_At = strs;
  1247.     strings_length=subtract_pointers(strings_p,strings);
  1248.  
  1249.     Out_Size=strs+strings_length;
  1250.  
  1251.     InV3 { excess=Out_Size-((int32) 0x20000L); limit=128; }
  1252.     InV5 { excess=Out_Size-((int32) 0x40000L); limit=256; }
  1253.  
  1254.     if (excess>0)
  1255.     {   sprintf(buffer,
  1256.           "Story file exceeds version-%d limit (%dK) by %d bytes",
  1257.           version_number, limit, excess);
  1258.         fatalerror(buffer);
  1259.     }
  1260.  
  1261.     code_offset = code;
  1262.     dictionary_offset = dict;
  1263.     variables_offset = vars;
  1264.     strings_offset = strs;
  1265.     actions_offset = actshere;
  1266.     preactions_offset = preactshere;
  1267.  
  1268.     j=Out_Size/scale_factor;
  1269.  
  1270.     p[26]=j/256; p[27]=j%256; p[28]=0; p[29]=0;
  1271.  
  1272.     for (i=0; i<no_actions; i++)
  1273.     {   j=(actions[i]+code)/scale_factor;
  1274.         p[actshere+i*2]=j/256; p[actshere+i*2+1]=j%256;
  1275.  
  1276.         if (i<no_prs) j=(parsing_routines[i]+code)/scale_factor;
  1277.         else if (preactions[i]==-1) j=0;
  1278.         else j=(preactions[i]+code)/scale_factor;
  1279.         p[preactshere+i*2]=j/256; p[preactshere+i*2+1]=j%256;
  1280.     }
  1281.  
  1282.     for (i=0; i<240; i++)
  1283.     {   j=gvalues[i];
  1284.         switch(gflags[i])
  1285.         {   case 1: j+=(code/scale_factor); break;
  1286.             case 2: j+=vars; break;
  1287.         }
  1288.         p[vars+i*2]   = j/256;
  1289.         p[vars+i*2+1] = j%256;
  1290.     }
  1291.  
  1292.     fix_gconstants(p+vars);
  1293.  
  1294.     /*  From here on, it's all reportage: construction is finished  */
  1295.  
  1296.  
  1297.     if (statistics_mode==1)
  1298.     {   int32 k_long, rate; char *k_str="";
  1299.         k_long=(Out_Size/1024);
  1300.         if ((Out_Size-1024*k_long) >= 512) { k_long++; k_str=""; }
  1301.         else if ((Out_Size-1024*k_long) > 0) { k_str=".5"; }
  1302.         rate=total_bytes_trans*1000/total_chars_trans;
  1303.         if ((pass_number==2)||(bothpasses_mode==1))
  1304.         {   printf("Input %d lines (%d statements, %d chars)",
  1305.                 total_source_line,internal_line,marker_in_file);
  1306.             if (total_files_read > 1) { printf(" from %d files",
  1307.                 total_files_read); }
  1308.             printf(
  1309. "\nVersion %d (%s) story file\n\
  1310. %4d objects (maximum %3d)     %4d dictionary entries (maximum %d)\n\
  1311. %4d attributes (maximum %2d)   %4d properties (maximum %2d)\n\
  1312. %4d adjectives (maximum 240)  %4d verbs (maximum %d)\n\
  1313. %4d actions (maximum %3d)     %4d abbreviations (maximum %d)\n",
  1314.                    version_number, ((version_number==3)?"Standard":"Advanced"),
  1315.                    no_objects, ((version_number==3)?255:(MAX_OBJECTS-1)),
  1316.                    dict_entries, MAX_DICT_ENTRIES,
  1317.                    no_attributes, ((version_number==3)?32:48),
  1318.                    no_properties-2, ((version_number==3)?30:62),
  1319.                    no_adjectives,
  1320.                    no_verbs, MAX_VERBS,
  1321.                    no_actions, MAX_ACTIONS,
  1322.                    no_abbrevs, MAX_ABBREVS);
  1323.  
  1324.             printf(
  1325. "%4d globals (maximum 240)     %4d variable space (maximum %d)\n\
  1326. %4d symbols (maximum %4d)    %4d routines (maximum %d)\n\
  1327. %4d classes (maximum %2d)      %4d fake actions (maximum %3d)\n\
  1328. %4ld characters of text (compressed to %ld bytes, rate 0.%3ld)\n\
  1329. Output story file is %3ld%sK long (maximum %ldK)\n",
  1330.                    no_globals,
  1331.                    globals_size, MAX_STATIC_DATA,
  1332.                    no_symbols, MAX_SYMBOLS,
  1333.                    no_routines, MAX_ROUTINES,
  1334.                    no_classes, MAX_CLASSES,
  1335.                    no_fake_actions, MAX_ACTIONS,
  1336.                    (long int) total_chars_trans,
  1337.                    (long int) total_bytes_trans,
  1338.                    (long int) rate,
  1339.                    (long int) k_long, k_str, (long int) limit);
  1340.         }
  1341.     }
  1342.  
  1343.     if ((debugging_file==1)&&(pass_number==2))
  1344.     {   debug_pass=2;
  1345.         write_debug_byte(13);
  1346.         write_debug_address(vars+480);
  1347.         write_debug_address(parsat);
  1348.         write_debug_address(dict);
  1349.         write_debug_address(code);
  1350.         write_debug_address(strs);
  1351.         debug_pass=1;
  1352.     }
  1353.  
  1354.     if (offsets_mode==1)
  1355.     {   if ((pass_number==2)||(bothpasses_mode==1))
  1356.         {   printf(
  1357. "\nOffsets in story file:\n\
  1358. %05lx Synonyms     %05lx Defaults     %05lx Objects    %05lx Properties\n\
  1359. %05lx Variables    %05lx Parse table  %05lx Actions    %05lx Preactions\n\
  1360. %05lx Adjectives   %05lx Dictionary   %05lx Code       %05lx Strings\n\n",
  1361.    (long int) synsat, (long int) glpat, (long int) objat, (long int) propat,
  1362.    (long int) vars, (long int) parsat, (long int) actshere,
  1363.    (long int) preactshere, (long int) adjectives_offset, (long int) dict,
  1364.    (long int) code, (long int) strs);
  1365.         }
  1366.     }
  1367.     if (memory_map_mode==1)
  1368.     {   if ((pass_number==2)||(bothpasses_mode==1))
  1369.         {
  1370. printf("Dynamic +---------------------+   00000\n");
  1371. printf("memory  |       header        |\n");
  1372. printf("        +---------------------+   00040\n");
  1373. printf("        |   synonym strings   |\n");
  1374. printf("        + - - - - - - - - - - +   %05lx\n", (long int) synsat);
  1375. printf("        |    synonym table    |\n");
  1376. printf("        +---------------------+   %05lx\n", (long int) glpat);
  1377. printf("        |  property defaults  |\n");
  1378. printf("        + - - - - - - - - - - +   %05lx\n", (long int) objat);
  1379. printf("        |      objects        |\n");
  1380. printf("        + - - - - - - - - - - +   %05lx\n", (long int) propat);
  1381. printf("        | object short names  |\n");
  1382. printf("        |   and properties    |\n");
  1383. printf("        +---------------------+   %05lx\n", (long int) vars);
  1384. printf("        |  global variables   |\n");
  1385. printf("        + - - - - - - - - - - +   %05lx\n", ((long int) vars)+480L);
  1386. printf("        |       arrays        |\n");
  1387. printf("        +=====================+   %05lx\n", (long int) parsat);
  1388. printf("Static  |    grammar table    |\n");
  1389. printf("cached  + - - - - - - - - - - +   %05lx\n", (long int) actshere);
  1390. printf("data    |       actions       |\n");
  1391. printf("        + - - - - - - - - - - +   %05lx\n", (long int) preactshere);
  1392. printf("        |     preactions      |\n");
  1393. printf("        + - - - - - - - - - - +   %05lx\n",
  1394.                                               (long int) adjectives_offset);
  1395. printf("        |     adjectives      |\n");
  1396. printf("        +---------------------+   %05lx\n", (long int) dict);
  1397. printf("        |     dictionary      |\n");
  1398. printf("        +---------------------+   %05lx\n", (long int) code);
  1399. printf("Static  |       Z-code        |\n");
  1400. printf("paged   +---------------------+   %05lx\n", (long int) strs);
  1401. printf("data    |       strings       |\n");
  1402. printf("        +---------------------+   %05lx\n", (long int) Out_Size);
  1403.         }
  1404.     }
  1405.     if (percentages_mode==1)
  1406.     {   if ((pass_number==2)||(bothpasses_mode==1))
  1407.         {   printf("Approximate percentage breakdown of story file:\n");
  1408.             percentage("Z-code",code_length,Out_Size);
  1409.             percentage("Static strings",strings_length,Out_Size);
  1410.             percentage("Dictionary",code-dict,Out_Size);
  1411.             percentage("Objects",vars-glpat,Out_Size);
  1412.             percentage("Globals",parsat-vars,Out_Size);
  1413.             percentage("Parsing tables",dict-parsat,Out_Size);
  1414.             percentage("Header and synonyms",glpat,Out_Size);
  1415.             percentage("Total of save area",parsat,Out_Size);
  1416.             percentage("Total of text",total_bytes_trans,Out_Size);
  1417.         }
  1418.     }
  1419.     if (frequencies_mode==1)
  1420.     {   if ((pass_number==2)||(bothpasses_mode==1))
  1421.         {   printf("How frequently abbreviations were used, and roughly\n");
  1422.             printf("how many bytes they saved:  ('_' denotes spaces)\n");
  1423.             for (i=0; i<no_abbrevs; i++)
  1424.             {   sprintf(sub_buffer,abbreviations_at+i*MAX_ABBREV_LENGTH);
  1425.                 for (j=0; sub_buffer[j]!=0; j++)
  1426.                     if (sub_buffer[j]==' ') sub_buffer[j]='_';
  1427.                 printf("%10s %5d/%5d   ",sub_buffer,abbrev_freqs[i],
  1428.                     2*((abbrev_freqs[i]-1)*abbrev_quality[i])/3);
  1429.                 if ((i%3)==2) printf("\n");
  1430.             }
  1431.             if ((i%3)!=0) printf("\n");
  1432.             if (no_abbrevs==0) printf("None were declared.\n");
  1433.         }
  1434.     }
  1435.     if (((statistics_mode==1)||(economy_mode==1))&&(pass_number==2))
  1436.     {   printf("Essential size %ld bytes: %ld remaining\n",
  1437.             (long int) Out_Size,
  1438.             (long int) (((long int) (limit*1024L)) - ((long int) Out_Size)));
  1439.     }
  1440. }
  1441.  
  1442. /* ------------------------------------------------------------------------- */
  1443. /*  Begin pass                                                               */
  1444. /* ------------------------------------------------------------------------- */
  1445.  
  1446. extern void tables_begin_pass(void)
  1447. {   int i;
  1448.  
  1449.     for (i=0; i<256; i++) debug_acts_writ[i]=0;
  1450.  
  1451.     dictionary_begin_pass();
  1452.  
  1453.     properties_size=0; classes_size=0;
  1454.  
  1455.     no_objects=0; no_classes=0; embedded_routine=0;
  1456.  
  1457.     no_verbs=0; fp_no_actions=no_actions; no_actions=0; no_adjectives=0;
  1458.     no_properties=2; no_attributes=0; no_fake_actions=0;
  1459.  
  1460.     no_prs=0;
  1461.  
  1462.     objects[0].parent=0; objects[0].child=0; objects[0].next=0;
  1463. }
  1464.  
  1465.