home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / games / inform / compiler / source / c / asm next >
Encoding:
Text File  |  1994-10-07  |  34.0 KB  |  1,109 lines

  1. /* ------------------------------------------------------------------------- */
  2. /*   "asm" : The Inform assembler                                            */
  3. /*                                                                           */
  4. /*   Part of Inform release 5                                                */
  5. /* ------------------------------------------------------------------------- */
  6.  
  7. #include "header.h"
  8.  
  9. int in_routine_flag, no_stubbed;
  10.  
  11. int ignoring_routine;
  12.  
  13. static int return_flag;
  14. static int stub_flags[32];
  15.  
  16. static int lower_strings_flag=0;
  17.  
  18. static int ifdef_stack[MAX_IFDEF_DEPTH];
  19. static int ifdef_sp=0;
  20. static int started_ignoring=0;
  21.  
  22. #ifndef ALLOCATE_BIG_ARRAYS
  23.   static long int pa_forwards[MAX_FORWARD_REFS];
  24. #else
  25.   static long int *pa_forwards;
  26. #endif
  27.  
  28. extern void asm_allocate_arrays(void)
  29. {
  30. #ifdef ALLOCATE_BIG_ARRAYS
  31.     pa_forwards = (long int *) my_calloc(sizeof(long int),   MAX_FORWARD_REFS,
  32.                   "forward references");
  33. #endif
  34. }
  35.  
  36. extern void asm_free_arrays(void)
  37. {   
  38. #ifdef ALLOCATE_BIG_ARRAYS
  39.     my_free(pa_forwards, "forward references");
  40. #endif
  41. }
  42.  
  43. /* ------------------------------------------------------------------------- */
  44. /*   Decode arguments as constants and variables                             */
  45. /*   (Gratuitous Space:1999 reference by Mr Dilip Sequeira of Edinburgh      */
  46. /*   University)                                                             */
  47. /* ------------------------------------------------------------------------- */
  48.  
  49. static int cvflag;
  50. static char scratch_b[64];
  51. extern int32 constant_value(char *b)
  52. {   int32 i, j, k, base=10, f, rv, moon, alpha, victor=0, eagle;
  53.  
  54.     if (b[0]=='\'')
  55.     {   if ((b[2]=='\'') && (b[3]==0))
  56.             return(translate_to_ascii(b[1]));
  57.         i=strlen(b);
  58.         if ((i>=4)&&(b[i-1]=='\''))
  59.         {   b[i-1]=0; for (;i>0;i--) b[i]=b[i-1];
  60.             b[0]='n'; b[1]='$';
  61.         }
  62.     }
  63.     cvflag=0;
  64.     if (b[0]=='#') b++;
  65.     if (b[0]=='#')
  66.     {   i=find_symbol(b+1);
  67.         if ((i>=0)&&(stypes[i]==18)) return(svals[i]);
  68.         if (strlen(b)>60)
  69.         {   error_named("Action name over 60 characters long:",b);
  70.             return(0);
  71.         }
  72.         sprintf(scratch_b,"a$%sSub",b+1);
  73.         b=scratch_b;
  74.     }
  75.     if (b[0]=='\"')
  76.     {   dequote_text(b);
  77.  
  78.         if (lower_strings_flag==1)
  79.         {
  80.             j=subtract_pointers(low_strings_p,low_strings);
  81.             low_strings_p=translate_text(low_strings_p,b);
  82.             i= subtract_pointers(low_strings_p,low_strings);
  83.             if (i>MAX_LOW_STRINGS)
  84.                 memoryerror("MAX_LOW_STRINGS", MAX_LOW_STRINGS);
  85.             cvflag=1;
  86.             return(0x21+(j/2));
  87.         }
  88.  
  89.         j= subtract_pointers(strings_p,strings);
  90.  
  91. #ifdef USE_TEMPORARY_FILES
  92.       {
  93.         zip *c;
  94.         c=translate_text(strings,b);
  95.         i= subtract_pointers(c,strings);
  96.         strings_p+=i;
  97.         if (pass_number==2)
  98.         {   for (c=strings; c<strings+i; c++)
  99.             {   fputc(*c,Temp1_fp);
  100.                     add_to_checksum((void *) c);
  101.             }
  102.         }
  103.       }
  104. #else
  105.         strings_p=translate_text(strings_p,b);
  106.         i= subtract_pointers(strings_p,strings);
  107.         if (i>MAX_STATIC_STRINGS)
  108.             memoryerror("MAX_STATIC_STRINGS",MAX_STATIC_STRINGS);
  109. #endif
  110.  
  111.         while ((i%scale_factor)!=0)
  112.         {   i+=2;
  113. #ifdef USE_TEMPORARY_FILES
  114.             strings_p+=2;
  115.             if (pass_number==2)
  116.             {   fputc(0,Temp1_fp);
  117.                 fputc(0,Temp1_fp);
  118.             }
  119. #else
  120.             *(strings_p++)=0;
  121.             *(strings_p++)=0;
  122. #endif
  123.         }
  124.  
  125.         cvflag=1;
  126.         return((strings_offset+j)/scale_factor);
  127.     }
  128.     if(*b=='$') 
  129.     {   if(*++b=='$') {b++;base=2;}
  130.         else base=16;
  131.     }
  132.     else if(*b=='-') {b++;victor=1;}
  133.     else for (i=0; b[i]; i++) if (!isdigit(b[i])) goto nonumber;
  134.  
  135.     for(moon=0;*b;b++) 
  136.     {  alpha=isalpha(*b)?(tolower(*b)-'a'+10):*b-'0';
  137.        if(alpha>=base || alpha<0) break; else moon=moon*base+alpha;
  138.     }
  139.     if (victor==0) return(moon);
  140.     eagle=((int32) 0x10000L)-moon;
  141.     return(eagle);  
  142.     nonumber:
  143.  
  144.     f=0;
  145.     if (strcmp(b,"adjectives_table")==0) return(adjectives_offset);
  146.     if (strcmp(b,"preactions_table")==0) return(preactions_offset);
  147.     if (strcmp(b,"actions_table")==0) return(actions_offset);
  148.     if (strcmp(b,"version_number")==0) return(version_number);
  149.     if (strcmp(b,"largest_object")==0) return(256+max_no_objects-1);
  150.     if (strcmp(b,"strings_offset")==0)
  151.     {   InV3 return(strings_offset/2);
  152.         InV5 return(strings_offset/4);
  153.     }
  154.     if (strcmp(b,"code_offset")==0)
  155.     {   InV3 return(code_offset/2);
  156.         InV5 return(code_offset/4);
  157.     }
  158.     if (strcmp(b,"dict_par1")==0) return((version_number==3)?4:6);
  159.     if (strcmp(b,"dict_par2")==0) return((version_number==3)?5:7);
  160.     if (strcmp(b,"dict_par3")==0) return((version_number==3)?6:8);
  161.     if ((b[0]=='a')&&(b[1]=='$')) { b+=2; f=1; }
  162.     if ((b[0]=='w')&&(b[1]=='$'))
  163.     {   k=dictionary_find(b+2,2);
  164.         rv=dictionary_offset+7+((version_number==3)?7:9)*(k-1);
  165.         if ((k==0)&&(pass_number==2))
  166.             error_named("Dictionary word not found for constant",b);
  167.     }
  168.     else
  169.     {   if ((b[0]=='n')&&(b[1]=='$'))
  170.         {   rv=dictionary_add(b+2,0x80,0,0);
  171.         }
  172.         else
  173.         {   if ((b[0]=='r')&&(b[1]=='$'))
  174.             {   i=find_symbol(b+2);
  175.                 if (i<0)
  176.                 {   if (pass_number==2)
  177.                       error_named("No such routine as",b);
  178.                     return(256);
  179.                 }
  180.                 rv=svals[i]; if (rv<256) rv=256;
  181.             }
  182.             else
  183.             {   i=find_symbol(b);
  184.                 if (i<0)
  185.                 {   if (pass_number==2)
  186.                       error_named("No such constant as",b);
  187.                     return(0);
  188.                 }
  189.                 rv=svals[i];
  190.             }
  191.         }
  192.     }
  193.     switch(stypes[i])
  194.     {   case 1: rv=(rv+code_offset)/scale_factor;
  195.                 break;
  196.         case 2:
  197.         case 3: error_named("Not a constant:",b); return(0);
  198.         case 4:
  199.         case 10: error_named("Reserved word as constant:",b); return(0);
  200.     }
  201.     if (f==0) return(rv);
  202.     j=find_action(svals[i]);
  203.     return(j);
  204. }
  205.  
  206. /* ------------------------------------------------------------------------- */
  207. /*   parse_argument returns: 1000+n   Constant value n                       */
  208. /*                                    long_form_flag set if long form vital  */
  209. /*                                n   Variable n                             */
  210. /* ------------------------------------------------------------------------- */
  211.  
  212. static char known_unknowns[MAX_IDENTIFIER_LENGTH*16];
  213. static int  no_knowns;
  214.  
  215. static long int pa_id;
  216. static int pa_ref;
  217. static int max_pa_ref;
  218. static int long_form_flag;
  219.  
  220. extern void args_begin_pass(void)
  221. {   if (pass_number==2) max_pa_ref=pa_ref;
  222.     pa_ref=0; pa_id=0;
  223. }
  224.  
  225. static int32 parse_argument(char *b)
  226. {   int i, flag=0;
  227.     long_form_flag=0;
  228.     if (b[0]=='#') return(1000+constant_value(b));
  229.     if ((b[0]=='-')||(b[0]=='$')||(b[0]=='\"')||(b[0]=='\''))
  230.         return(1000+constant_value(b));
  231.     for (i=0; b[i]!=0; i++) if (isdigit(b[i])==0) flag=1;
  232.     if (flag==0) return(1000+constant_value(b));
  233.     if (in_routine_flag==1)
  234.     {   i=local_find_symbol(b);
  235.         if (i>=0) return(1+svals[i]);
  236.     }
  237.     pa_id++;
  238.  
  239.     i=find_symbol(b);
  240.     if (i>=0)
  241.     {   switch(stypes[i])
  242.         {   case 1: return(1000+svals[i]);
  243.             case 2: return(16+svals[i]);
  244.             case 4: if (svals[i]==0) return(0);
  245.             case 7:
  246.             case 12:
  247.             case 13:
  248.             case 18:
  249.             case 8:
  250.             case 9: if (pass_number==2)
  251.                     {   while ((pa_ref<max_pa_ref)
  252.                            &&(pa_id>pa_forwards[pa_ref])) pa_ref++;
  253.                         if ((pa_ref<max_pa_ref)
  254.                             &&(pa_id==pa_forwards[pa_ref]))
  255.                         {  long_form_flag=1;
  256. /*  printf("'%s' ref %d id %d seems forward\n",b,pa_ref, pa_id); */
  257.                         }
  258.                     }
  259.                     return(1000+constant_value(b));
  260.             default: error_named("Type mismatch in argument",b);
  261.               return(0);
  262.         }
  263.     }
  264.  
  265.     if (pass_number==1)
  266.     {   if (pa_ref==MAX_FORWARD_REFS)
  267.             memoryerror("MAX_FORWARD_REFS", MAX_FORWARD_REFS);
  268.         pa_forwards[pa_ref++]=pa_id;
  269. /*  printf("'%s' ref %d id %d is forward\n",b,pa_ref, pa_id); */
  270.         return(1256);
  271.     }
  272.  
  273.     for (i=0; i<no_knowns; i++)
  274.         if (strcmp(known_unknowns+i*MAX_IDENTIFIER_LENGTH,b)==0)
  275.             return(0);
  276.     if (no_knowns<16)
  277.         strcpy(known_unknowns+(no_knowns++)*MAX_IDENTIFIER_LENGTH,b);
  278.     error_named("No such variable as",b); return(0);
  279. }
  280.  
  281. /* ------------------------------------------------------------------------- */
  282. /*   Assembler of individual lines                                           */
  283. /* ------------------------------------------------------------------------- */
  284.  
  285. static void byteout(int32 i)
  286. {   *zcode_p=(unsigned char) i; zcode_p++;
  287. #ifdef USE_TEMPORARY_FILES
  288.     utf_zcode_p++;
  289. #endif
  290.     if (subtract_pointers(zcode_p,zcode) >= MAX_ZCODE_SIZE)
  291.     {   memoryerror("MAX_ZCODE_SIZE",MAX_ZCODE_SIZE);
  292.     }
  293. }
  294.  
  295. static void write_operand(operand_t op)
  296. {   int32 j;
  297.     j=op.value;
  298.     if (op.type!=0) byteout(j);
  299.     else { byteout(j/256); byteout(j%256); }
  300. }
  301.  
  302. static operand_t parse_operand(int32 number, opcode opco, char *b)
  303. {   int32 j; int opt, type=opco.type1; operand_t oper;
  304.  
  305.     word(b,number+2);
  306.  
  307.     if (((type==CALL)||(type==NCALL))&&(number==0))
  308.     {   if (pass_number==2)
  309.         {   
  310.             j=find_symbol(b);
  311.             if (j==-1) { no_such_label(b); }
  312.             if (stypes[j]!=1) { error_named("Not a label:",b); }
  313.             oper.value=(code_offset+svals[j])/scale_factor;
  314.             oper.type=0;
  315.         }
  316.         else
  317.         {   oper.value=0x1000; oper.type=0;
  318.         }
  319.         return(oper);
  320.     }
  321.  
  322.     j=parse_argument(b);
  323.  
  324.     if (j>=1256) { opt=0; j=j-1000; }
  325.     else if (j>=1000) { opt=1; j=j-1000; }
  326.     else opt=2;
  327.  
  328.     if ((opt==1) && (long_form_flag==1)) opt=0;
  329.  
  330.     if ((opco.type2==VAR)&&(opt==2)&&(number==0)) opt=1;
  331.  
  332.     oper.value=j; oper.type=opt;
  333.     return(oper);
  334. }
  335.  
  336. int a_from_one=0;
  337. int line_done_flag = 0;
  338.  
  339. extern int assemble_opcode(char *b, int32 offset, opcode opco)
  340. {
  341.     zip *opc, *opcname, *ac;
  342.     int32 j, topbits, addr, cargs, ccode, oldccode,
  343.           multi, mask, flag, longf, branchword, offset_here;
  344.     operand_t oper1, oper2;
  345.  
  346.     if (opco.type1==INVALID)
  347.     {   if (version_number==3)
  348.         { warning_named("Ignoring Advanced-game opcode",b); }
  349.         else
  350.         { warning_named("Ignoring Standard-game opcode",b); }
  351.         return(1);
  352.     }
  353.     return_flag=0;
  354.     if (opco.type1==RETURN) return_flag=1;
  355.     if (opco.type1==INDIR)
  356.     {   byteout(0xE0); byteout(0xBF); byteout(0);  byteout(0);
  357.         goto Line_Done;
  358.     }
  359.     opcname=opco.name;
  360.     switch(opco.no)
  361.     {   case VARI: topbits=0xc0; break;
  362.         case ZERO: topbits=0xb0; break;
  363.         case ONE:  topbits=0x80; break;
  364.         case TWO:  topbits=0x00; break;
  365.     }
  366.  
  367.     opc=zcode_p;
  368.  
  369.     if (opco.no!=EXTD)
  370.     {   byteout(topbits+opco.code);
  371.     }
  372.     else
  373.     {   byteout(0xbe); byteout(opco.code); opco.no=VARI;
  374.     }
  375.  
  376.     if (opco.type1==JUMP)
  377.     {   word(b,2);
  378.         if (pass_number==1) addr=0;
  379.         else
  380.         {   j=find_symbol(b);
  381.             if (j<0) { no_such_label(b); return(1); }
  382.             if (stypes[j]!=6) { error_named("Not a label:",b); return(1); }
  383.             addr=svals[j]-offset-1;
  384.             if (addr<0) addr+=(int32) 0x10000L;
  385.         }
  386.         byteout(addr/256); byteout(addr%256);
  387.         goto Line_Done;
  388.     }
  389.  
  390.     if (opco.type2==TEXT)
  391.     {   char *tmp;
  392.         if (a_from_one==1) textword(b,1); else textword(b,2);
  393.         tmp=zcode_p; zcode_p=translate_text(zcode_p,b);
  394.         j=subtract_pointers(zcode_p,tmp);
  395. #ifdef USE_TEMPORARY_FILES
  396.         utf_zcode_p+=j;  
  397. #endif
  398.     }
  399.  
  400.     switch(opco.no)
  401.     {   case VARI:
  402.             ac=zcode_p; byteout(0);
  403.             cargs= -1; ccode=0xff;
  404.             while (word(b,(++cargs)+2),(b[0]!=0))
  405.             {   if (b[0]=='?') { branchword=cargs+2; break; }
  406.                 switch(cargs)
  407.                 {   case 0: multi=0x40; mask=0xc0; break;
  408.                     case 1: multi=0x10; mask=0x30; break;
  409.                     case 2: multi=0x04; mask=0x0c; break;
  410.                     case 3: multi=0x01; mask=0x03; break;
  411.                     case 4: multi=0;
  412.                             if ((opco.type1!=CALL)&&(opco.type1!=STORE))
  413.                                 error("Too many arguments");
  414.                             break;
  415.                     default: error("Too many arguments"); break;
  416.                 }
  417.  
  418.                 oper1=parse_operand(cargs, opco, b);
  419.  
  420.                 write_operand(oper1);
  421.                 oldccode=ccode; ccode = (ccode & (~mask)) + oper1.type*multi;
  422.             }
  423.             if ((opco.type1==CALL)||(opco.type1==STORE))
  424.             {   if (oper1.type!=2)
  425.                 { error("Can't store to that (no such variable)"); }
  426.                 *ac=oldccode;
  427.             }
  428.             else *ac=ccode;
  429.             break;
  430.         case ONE:
  431.             oper1=parse_operand(0,opco,b);
  432.             *opc=(*opc) + oper1.type*0x10;
  433.             write_operand(oper1);
  434.             break;
  435.         case TWO:
  436.             oper1=parse_operand(0,opco,b);
  437.             oper2=parse_operand(1,opco,b);
  438.  
  439.             if ((oper1.type==0)||(oper2.type==0))
  440.             {   *opc=(*opc) + 0xc0;
  441.                 byteout(oper1.type*0x40 + oper2.type*0x10 + 0x0f);
  442.             }
  443.             else
  444.             {   if (oper1.type==2) *opc=(*opc) + 0x40;
  445.                 if (oper2.type==2) *opc=(*opc) + 0x20;
  446.             }
  447.             write_operand(oper1);
  448.             write_operand(oper2);
  449.             break;                    
  450.         case ZERO:
  451.             break;
  452.     }
  453.  
  454.     if ((opco.no==ONE) || (opco.no==TWO))
  455.     {   if ((opco.type1==STORE)||(opco.type1==CALL))
  456.         {   if (opco.no==ONE) oper1=parse_operand(1,opco,b);
  457.             if (opco.no==TWO) oper1=parse_operand(2,opco,b);
  458.             if (oper1.type!=2)
  459.             { error("Can't store to that (no such variable)"); }
  460.             byteout(oper1.value);
  461.         }
  462.     }
  463.  
  464.     if ((opco.type1==BRANCH)||(opco.type2==OBJECT))
  465.     {   int o=0; int32 pca;
  466.         pca= subtract_pointers(zcode_p,opc) -1;
  467.         switch(opco.no)
  468.         {   case ZERO: word(b,2); break;
  469.             case ONE:  if (opco.type2!=OBJECT) { word(b,3); break; }
  470.             case TWO:  word(b,4); break;
  471.             case VARI: word(b,branchword); break;
  472.         }
  473.         if (b[0]=='?') { longf=1; o++; }
  474.         else
  475.         {   int o2=0;
  476.             if (b[0]=='~') o2=1;
  477.             if (pass_number==1)
  478.             {   j=find_symbol(b+o2);
  479.                 if (j<0) longf=0;
  480.                 else longf=1;
  481.             }
  482.             else
  483.             {   j=find_symbol(b+o2);
  484.                 if (j<0) longf=0;
  485.                 else
  486.                 {   if (offset-svals[j]>0) longf=1;
  487.                     else longf=0;
  488.                     if ((svals[j]-offset-pca)>30)
  489.                     { error("Branch too far forward: use '?'"); return(1); }
  490.                 }
  491.             }
  492.         }
  493.         /* printf("Branch at %04x has longf=%d\n",offset,longf);  */
  494.         if (pass_number==1) { byteout(0); if (longf==1) byteout(0); }
  495.         else
  496.         {   if (b[o]=='~') { flag=0; o++; } else flag=1;
  497.             j=find_symbol(b+o);
  498.             if (j<0) { no_such_label(b+o); return(1); }
  499.             switch(stypes[j])
  500.             {   case 4:
  501.                   switch(svals[j])
  502.                   {   case 1: addr=1; longf=0; break;
  503.                       case 2: addr=0x20; longf=0; break;
  504.                       default: error("No such return condition for branch");
  505.                                return(1);
  506.                   }
  507.                   break;
  508.                 case 1: error("Can't branch to a routine, only to a label");
  509.                         return(1);
  510.                 case 6:
  511.                   if (longf==1) pca++;
  512.                   addr=svals[j]-offset-pca;
  513.                   if (addr<0) addr+=(int32) 0x10000L; break;
  514.                 default: error_named("Not a label:",b+o); return(1);
  515.             }
  516.             addr=addr&0x3fff;
  517.             if (longf==1)
  518.             {   byteout(flag*0x80 + addr/256); byteout(addr%256); }
  519.             else
  520.                 byteout(flag*0x80+ 0x40 + (addr&0x3f));
  521.         }
  522.     }
  523.  
  524.     Line_Done:
  525.  
  526.     if (trace_mode==1)
  527.     {   printf("%04d %04x  %-14s  ", current_source_line(),
  528.             offset+code_offset,opcname);
  529.         for (j=0;opc<zcode_p; j++, opc++)
  530.         {   printf("%02x ", *opc);
  531.             if (j%16==15) printf("\n                           ");
  532.         }
  533.         printf("\n");
  534.     }
  535.  
  536.     if ((debugging_file==1)&&(pass_number==2)
  537.         &&(line_done_flag==0))
  538.     {   debug_pass=2; line_done_flag=1;
  539.         write_debug_byte(10); write_debug_linenum();
  540.         offset_here = offset+code_offset;
  541.         write_debug_byte((offset_here/256)/256);
  542.         write_debug_byte((offset_here/256)%256);
  543.         write_debug_byte(offset_here%256);
  544.         debug_pass=1;
  545.     }
  546.  
  547. #ifdef USE_TEMPORARY_FILES
  548.       {
  549.         zip *c;
  550.         int32 i;
  551.         i= subtract_pointers(zcode_p,zcode);
  552.         if (pass_number==2)
  553.         {   for (c=zcode; c<zcode+i; c++)
  554.             {   fputc(*c,Temp2_fp);
  555.                 add_to_checksum((void *) c);
  556.             }
  557.         }
  558.         zcode_p=zcode;
  559.       }
  560. #endif
  561.  
  562.     return(1);
  563. }
  564.  
  565. /* ------------------------------------------------------------------------- */
  566. /*   Making attributes and properties (incorporating "alias" code suggested  */
  567. /*   by Art Dyer)                                                            */
  568. /* ------------------------------------------------------------------------- */
  569.  
  570. static void trace_s(char *name, int32 code, int f)
  571. {   if (debugging_file==1)
  572.     {   write_debug_byte(5+f); write_debug_byte(code);
  573.         write_debug_string(name);
  574.     }
  575.     if ((printprops_mode==0)||(pass_number==2)) return;
  576.     printf("%s  %02d  ",(f==0)?"Attr":"Prop",code);
  577.     if (f==0) printf("  ");
  578.     else      printf("%s%s",(prop_longflag[code]==1)?"L":" ",
  579.                             (prop_additive[code]==1)?"A":" ");
  580.     printf("  %s\n",name);
  581. }
  582.  
  583. static void make_attribute(char *b)
  584. {   int i;
  585.  
  586.     word(b,3);
  587.     if (strcmp(b,"alias")==0)
  588.     {   
  589.         word(b,4);
  590.         if (b[0]==0)
  591.         {   error("Expected an attribute name after 'alias'");
  592.             return;
  593.         }
  594.         if (((i=find_symbol(b))==-1)||(stypes[i]!=7))
  595.         {   error_named("'alias' refers to undefined attribute",b);
  596.             return;
  597.         }
  598.         word(b,2);
  599.         trace_s(b,svals[i],0);
  600.         new_symbol(b,svals[i],7);
  601.         return;
  602.     }
  603.     InV3
  604.     {   if (no_attributes==32)
  605.         {   error("All 32 attributes already declared (compile as Advanced \
  606. game to get an extra 16)"); return; }
  607.     }
  608.     InV5
  609.     {   if (no_attributes==48)
  610.         {   error("All 48 attributes already declared"); return; }
  611.     }
  612.     word(b,2);
  613.     trace_s(b,no_attributes,0);
  614.     new_symbol(b,no_attributes++,7);
  615.     return;
  616. }
  617.  
  618. static void make_property(char *b)
  619. {   int32 def=0;
  620.     int i, fl, longflag=0, addflag=0;
  621.  
  622.     fl=2;
  623.     do
  624.     {   word(b,fl++);
  625.         if (strcmp(b,"long")==0) longflag=1;
  626.         else if (strcmp(b,"additive")==0) addflag=1;
  627.         else break;
  628.     } while (1==1);
  629.  
  630.     word(b,fl);
  631.     if (strcmp(b,"alias")==0)
  632.     {   if (longflag)
  633.         {   error("'alias' incompatible with 'long'"); return; }
  634.         if (addflag)
  635.         {   error("'alias' incompatible with 'additive'"); return; }
  636.         word(b,4);
  637.         if (b[0]==0)
  638.         {   error("Expected a property name after 'alias'"); return; }
  639.         i=find_symbol(b);
  640.         if (((i=find_symbol(b))==-1)||(stypes[i]!=12))
  641.         {   error_named("'alias' refers to undefined property",b);
  642.             return;
  643.         }
  644.         word(b,2);
  645.         trace_s(b,svals[i],1);
  646.         new_symbol(b,svals[i],12);
  647.         return;
  648.     }
  649.     InV3
  650.     {   if (no_properties==32)
  651.         { error("All 30 properties already declared (compile as Advanced \
  652. game to get an extra 32)"); return; }
  653.     }
  654.     InV5
  655.     {   if (no_properties==64)
  656.         { error("All 62 properties already declared"); return; }
  657.     }
  658.     if (b[0]!=0) def=constant_value(b);
  659.     word(b,fl-1);
  660.     prop_defaults[no_properties]=def;
  661.     InV3 { prop_longflag[no_properties]=longflag; }
  662.     InV5 { prop_longflag[no_properties]=1; }
  663.     prop_additive[no_properties]=addflag;
  664.     trace_s(b,no_properties,1);
  665.     new_symbol(b,no_properties++,12);
  666.     return;
  667. }
  668.  
  669. static void make_fake_action(char *b)
  670. {   word(b,2);
  671.     new_symbol(b,255-no_fake_actions++,18);
  672.  
  673.     if (debugging_file==1)
  674.     {   write_debug_byte(7); write_debug_byte(256-no_fake_actions);
  675.         write_debug_string(b);
  676.     }
  677.     return;
  678. }
  679.  
  680. /* ------------------------------------------------------------------------- */
  681. /*   Assembler directives: for diagnosis, and making the non-code part of    */
  682. /*     the file                                                              */
  683. /* ------------------------------------------------------------------------- */
  684.  
  685. static int lmoved_flag=0;
  686.  
  687. extern void assemble_label(int32 offset, char *b)
  688. {   int i;
  689.     if (pass_number==1) new_symbol(b,offset,6);
  690.     else
  691.     {   i=find_symbol(b);
  692.         if (svals[i]!=offset)
  693.             if (lmoved_flag==0)
  694.             {   lmoved_flag=1;
  695.                 if (no_errors==0)
  696.     error("A label has moved between passes because of a low-level error \
  697. just before (perhaps an improper use of a routine address as a constant)");
  698.             }
  699.     }
  700.     if (trace_mode==1) printf(".%s\n",b);
  701.     return_flag=0;
  702. }
  703.  
  704. static void stack_sline(char *s1, char *b)
  705. {   char rw[100];
  706.     sprintf(rw,s1,b); stack_line(rw);
  707. }
  708.  
  709. static int constant_made_flag = 0;
  710.  
  711. extern void assemble_directive(char *b, int32 offset, int32 code)
  712. {   int i, j, condition=0, debugged_routine;
  713.  
  714.   switch(code)
  715.   { 
  716.     case IFDEF_CODE:
  717.         word(b,2); i=find_symbol(b);
  718.         if (i>=0) condition=1;
  719.         goto generic_if;
  720.     case IFNDEF_CODE:
  721.         word(b,2); i=find_symbol(b);
  722.         if (i==-1) condition=1;
  723.         goto generic_if;
  724.     case IFV3_CODE:
  725.         if (version_number==3) condition=1; goto generic_if;
  726.     case IFV5_CODE:
  727.         if (version_number==5) condition=1; goto generic_if;
  728.  
  729.     generic_if:
  730.  
  731.         if (ifdef_sp==MAX_IFDEF_DEPTH)
  732.         { error("'#IF' nested too deeply: increase #define MAX_IFDEF_DEPTH");
  733.           return;
  734.         }
  735.         ifdef_stack[ifdef_sp++]=ignoring_mode;
  736.         if (ignoring_mode==0)
  737.         {   ignoring_mode=1-condition;
  738.             started_ignoring=ifdef_sp;
  739.         }
  740.         return;
  741.  
  742.     case ENDIF_CODE:
  743.         if (ifdef_sp==0)
  744.         { error("'#ENDIF' without matching '#IF'"); return; }
  745.         ignoring_mode=(ifdef_stack[--ifdef_sp])%2;
  746.         return;
  747.  
  748.     case IFNOT_CODE:
  749.         if (ifdef_sp==0)
  750.         { error("'#IFNOT' without matching '#IF'"); return; }
  751.         if (ifdef_stack[ifdef_sp-1]>=2)
  752.         { error("Two '#IFNOT's in the same '#IF'"); return; }
  753.         ifdef_stack[ifdef_sp-1]+=2;
  754.         if (ignoring_mode==1)
  755.         {   if (ifdef_sp==started_ignoring)
  756.                 ignoring_mode=0;
  757.         }
  758.         else
  759.         {   ignoring_mode=1;
  760.         }
  761.         return;
  762.  
  763.     case END_CODE:
  764.         endofpass_flag=1;
  765.         if (trace_mode==1) printf("<end>\n");
  766.  
  767.         if (ifdef_sp>0)
  768.         { error("End of file reached inside '#IF...'"); }
  769.         break;
  770.  
  771.     case OPENBLOCK_CODE:
  772.         if (is_systemfile()==1)
  773.         {   strcpy(b,"Rep__");
  774.             word(b+5,2);
  775.             i=find_symbol(b);
  776.             if (i!=-1)
  777.             {   ignoring_routine=1; /* printf("Ignoring %s\n",b+5); */ break; }
  778.         }
  779.         word(b,2);
  780.         ignoring_routine=0; debugged_routine=0;
  781.         while ((offset%scale_factor)!=0) { byteout(0); offset++; }
  782.         new_symbol(b,offset,1);
  783.         if (trace_mode==1) printf("<Routine %d, '%s' begins at %04x; ",
  784.           no_routines,b,offset);
  785.  
  786.         if (debugging_file==1)
  787.         {   debug_pass=2;
  788.             write_debug_byte(11);
  789.             write_debug_byte(no_routines/256);
  790.             write_debug_byte(no_routines%256);
  791.             write_routine_linenum(); write_debug_string(b);
  792.         }
  793.  
  794.         no_locals= -1; no_knowns=0;
  795.         routine_starts_line=current_source_line();
  796.         no_routines++;
  797.         if (no_routines>=MAX_ROUTINES)
  798.             memoryerror("MAX_ROUTINES", MAX_ROUTINES);
  799.         in_routine_flag=1; return_flag=0;
  800.         word(b,3); if (strcmp(b,"*")==0) debugged_routine=1;
  801.         while (word(b,(++no_locals)+3+debugged_routine),(b[0]!=0))
  802.         {   if ( ((b[0]==',')&&(b[1]==0)) || ((b[0]==':')&&(b[1]==0)))
  803.             {   error("Expected local variable but found ',' or ':' \
  804. (probably the ';' after the '[ ...' line was forgotten)");
  805.                 break;
  806.             }
  807.             new_symbol(b,no_locals,3);
  808.             if (debugging_file==1) write_debug_string(b);
  809.         }
  810.  
  811.         if (debugging_file==1) { write_debug_byte(0); debug_pass=1; }
  812.         byteout(no_locals);
  813.  
  814.         if (actual_version<5)
  815.         {   for (i=0; i<no_locals; i++) { byteout(0); byteout(0); }
  816.         }
  817.         if (trace_mode==1) printf("%d locals>\n",no_locals);
  818.         if (no_locals>15) error("Routine has more than 15 local variables");
  819.         if ((no_routines==1)&&(pass_number==1))
  820.         {   word(b,2); make_lower_case(b);
  821.             if (strcmp(b,"main")!=0)
  822.             {
  823. warning_named("Since it is defined before inclusion of the library, game-play \
  824. will begin not at 'Main' but at the routine",b);
  825.             }
  826.             if (no_locals!=0)
  827.  error("The earliest-defined routine is not allowed to have local variables");
  828.         }
  829.         if (nowarnings_mode==0)
  830.             for (i=0; i<16; i++) used_local_variable[i]=0;
  831.  
  832.         if ((withdebug_mode==1) || (debugged_routine==1))
  833.         {   word(b,2); sprintf(sub_buffer,"print \"[%s\"",b);
  834.             for (i=0; (i<no_locals)&&(i<3); i++)
  835.             {   word(b, 3+i+debugged_routine);
  836.                sprintf(sub_buffer+strlen(sub_buffer), ", \", %s=\", %s", b, b);
  837.             }
  838.             sprintf(sub_buffer+strlen(sub_buffer), ", \"]^\"");
  839.             stack_line(sub_buffer);
  840.         }
  841.         break;
  842.  
  843.     case CLOSEBLOCK_CODE:
  844.  
  845.         word(b,2);
  846.         if (b[0]!=0)
  847.         {   if ((resobj_flag==0) || (strcmp(b,",")!=0))
  848.             {
  849.                 if (resobj_flag>0)
  850.                 error_named(
  851.                     "Expected ',' or ';' after ']' but found",
  852.                     parse_buffer);
  853.                 else
  854.                 error_named(
  855.                     "Expected ';' after ']' but found",
  856.                     parse_buffer);
  857.             }
  858.         }
  859.  
  860.         if (trace_mode==1)  printf("<Routine ends>\n");
  861.         if (debugging_file==1)
  862.         {   debug_pass=2;
  863.             write_debug_byte(14);
  864.             write_debug_byte((no_routines-1)/256);
  865.             write_debug_byte((no_routines-1)%256);
  866.             write_re_linenum(); debug_pass=1;
  867.         }
  868.  
  869.         if (return_flag==0)
  870.         {   if (resobj_flag==0) stack_line("@rtrue");
  871.                            else stack_line("@rfalse");
  872.         }
  873.         if (resobj_flag==1) resobj_flag=3;
  874.  
  875.         if (brace_sp>0)
  876.         {   error("Brace mismatch in previous routine");
  877.             brace_sp=0;
  878.         }
  879.         in_routine_flag=0;
  880.         if ((nowarnings_mode==0)&&(pass_number==1))
  881.         {   for (i=0; i<no_locals; i++)
  882.             {   if (used_local_variable[i]==0)
  883.                 {   override_error_line = routine_starts_line;
  884.                     warning_named("Local variable unused:",
  885.                       local_varname[i]);
  886.                 }
  887.             }
  888.         }
  889.  
  890.         if (call_for_br_flag==1)
  891.         {   compile_box_routine();
  892.             call_for_br_flag=0;
  893.         }
  894.         break;
  895.  
  896.     case ABBREVIATE_CODE:
  897.         textword(b,2);
  898.         if (pass_number==1)
  899.         {   if (no_abbrevs==MAX_ABBREVS)
  900.             {   error("Too many abbreviations declared"); break; }
  901.             if (almade_flag==1) 
  902.             {   error("All abbreviations must be declared together"); break; }
  903.             if (strlen(b)<2)
  904.             {   error_named("It's not worth abbreviating",b); break; }
  905.         }
  906.         strcpy(abbreviations_at+no_abbrevs*MAX_ABBREV_LENGTH, b);
  907.         word(b,2);
  908.         abbrev_mode=0; lower_strings_flag=1;
  909.         abbrev_values[no_abbrevs]=constant_value(b);
  910.         abbrev_quality[no_abbrevs++]=trans_length-2;
  911.         abbrev_mode=1; lower_strings_flag=0;
  912.         break;
  913.  
  914.     case ATTRIBUTE_CODE:
  915.         make_attribute(b); break;
  916.  
  917.     case CONSTANT_CODE:
  918.         constant_made_flag=1;
  919.         word(b,3);
  920.         IfPass2
  921.         {   
  922.             constant_value(b);
  923.             word(b,2);
  924.             i=find_symbol(b);
  925.             if (stypes[i]==11)
  926.               svals[i]=svals[i]-(0x800/scale_factor)
  927.                                +strings_offset/scale_factor;
  928.         }
  929.         else
  930.         {   
  931.             i=constant_value(b);
  932.             word(b,2);
  933.             if (cvflag==1) new_symbol(b,i,11);
  934.             else new_symbol(b,i,8);
  935.         }
  936.         break;
  937.  
  938.     case LOWSTRING_CODE:
  939.         word(b,3);
  940.         IfPass2
  941.         {   lower_strings_flag=1;
  942.             constant_value(b);
  943.             lower_strings_flag=0;
  944.             word(b,2);
  945.             i=find_symbol(b);
  946.         }
  947.         else
  948.         {   lower_strings_flag=1;
  949.             i=constant_value(b);
  950.             lower_strings_flag=0;
  951.             word(b,2);
  952.             if (cvflag==1) new_symbol(b,i,11);
  953.             else new_symbol(b,i,8);
  954.         }
  955.         break;
  956.  
  957.     case DEFAULT_CODE:
  958.         word(b,3);
  959.         IfPass2
  960.         {
  961.         }
  962.         else
  963.         {   i=constant_value(b);
  964.             word(b,2);
  965.             if (find_symbol(b)==-1)
  966.             {   if (cvflag==1)
  967.                 { error("Defaulted constants can't be strings"); return; }
  968.                 new_symbol(b,i,8);
  969.             }
  970.         }
  971.         break;
  972.  
  973.     case STUB_CODE:
  974.         i=0;
  975.         IfPass2 { if (stub_flags[no_stubbed++]==1) i=1; }
  976.         else
  977.         {   word(b,2); if (find_symbol(b)==-1) i=1;
  978.             stub_flags[no_stubbed++]=i;
  979.         }
  980.         if (i==1)
  981.         {
  982.             word(b,3); i=constant_value(b); word(b,2);
  983.             switch(i)
  984.             {   case 0: stack_sline("[ %s",b); stack_line("rfalse");
  985.                         stack_line("]"); break;
  986.                 case 1: stack_sline("[ %s x1",b); stack_line("@store x1 0");
  987.                         stack_line("rfalse"); stack_line("]"); break;
  988.                 case 2: stack_sline("[ %s x1 x2",b); stack_line("@store x1 0");
  989.                         stack_line("@store x2 0");
  990.                         stack_line("rfalse"); stack_line("]"); break;
  991.                 case 3: stack_sline("[ %s x1 x2 x3",b);
  992.                         stack_line("@store x1 0"); stack_line("@store x2 0");
  993.                         stack_line("@store x3 0");
  994.                         stack_line("rfalse"); stack_line("]"); break;
  995.                 default:
  996.                     error("Must specify 0 to 3 variables in 'stub' routine");
  997.                         return;
  998.             }
  999.         }
  1000.         break;
  1001.  
  1002.     case DICTIONARY_CODE:
  1003.         textword(b,3); i=dictionary_add(b,4,0,0);
  1004.         word(b,2);
  1005.         IfPass2
  1006.         { j=find_symbol(b); svals[j]=i; } else new_symbol(b,i,8);
  1007.         break;
  1008.  
  1009.     case FAKE_ACTION_CODE:
  1010.         make_fake_action(b); break;
  1011.  
  1012.     case GLOBAL_CODE: make_global(b); break;
  1013.  
  1014.     case INCLUDE_CODE:
  1015.         textword(b,2); load_sourcefile(b);
  1016.         word(b,3);
  1017.         if (b[0]!=0)
  1018.             error_named("Expected ';' after 'include <file>' but found",b);
  1019.         break;
  1020.  
  1021.     case NEARBY_CODE: make_object(b,1); break;
  1022.  
  1023.     case OBJECT_CODE: make_object(b,0); break;
  1024.  
  1025.     case CLASS_CODE: make_class(b); break;
  1026.  
  1027.     case PROPERTY_CODE: make_property(b); break;
  1028.  
  1029.     case RELEASE_CODE:
  1030.         word(b,2); release_number=constant_value(b); break;
  1031.         
  1032.     case SWITCHES_CODE:
  1033.         if (ignoreswitches_mode==0)
  1034.         {   if ((pass_number==1)&&(constant_made_flag==1))
  1035.                 error("A 'switches' directive must \
  1036. must come before constant definitions");
  1037.             word(b,2); switches(b,0);
  1038.         }
  1039.         break;
  1040.  
  1041.     case STATUSLINE_CODE:
  1042.         word(b,2);
  1043.         On_("score") { statusline_flag=0; break; }
  1044.         On_("time")  { statusline_flag=1; break; }
  1045.         error_named("Expected 'score' or 'time' after 'statusline' but found",
  1046.             b); break;
  1047.  
  1048.     case SERIAL_CODE:
  1049.         textword(b,2);
  1050.         if (strlen(b)!=6)
  1051.         {   error("The serial number must be a 6-digit date in double-quotes");
  1052.             break; }
  1053.         for (i=0; i<6; i++)
  1054.           if (isdigit(b[i])==0)
  1055.           { error("The serial number must be a 6-digit date in double-quotes");
  1056.             break; }
  1057.         strcpy(time_given,b); time_set=1; break;
  1058.  
  1059.     case SYSTEM_CODE: 
  1060.         declare_systemfile(); break;
  1061.  
  1062.     case REPLACE_CODE:
  1063.         sprintf(b, "Rep__");
  1064.         word(b+5, 2);
  1065.         new_symbol(b, 0, 19);
  1066.         break;
  1067.  
  1068.     case VERB_CODE: make_verb(b); break;
  1069.  
  1070.     case EXTEND_CODE: extend_verb(b); break;
  1071.  
  1072.     case VERSION_CODE:
  1073.         if (override_version) break;
  1074.         word(b,2); actual_version=constant_value(b);
  1075.         if (actual_version==3) version_number=3; else version_number=5;
  1076.         if (version_number==3) scale_factor=2;
  1077.         scale_factor=4; if (actual_version==6) scale_factor=8;
  1078.         if ((version_number>=3)&&(version_number<=6)) break;
  1079.         error("The version number must be 3 to 6: 3 for Standard games and \
  1080. 5 for Advanced"); break;
  1081.  
  1082.     case TRACE_CODE:     IfPass2 trace_mode=1;  break;
  1083.     case NOTRACE_CODE:   IfPass2 trace_mode=tracing_mode;  break;
  1084.     case ETRACE_CODE:
  1085.         IfPass2
  1086.         {   word(b,2); if (b[0]==0) { etrace_mode=2; break; }
  1087.             if (strcmp(b,"full")==0) { etrace_mode=1; break; }
  1088.         error_named("Expected 'full' or nothing after 'etrace' but found", b);
  1089.             break;
  1090.         }
  1091.     case NOETRACE_CODE:  IfPass2 etrace_mode=0; break; 
  1092.     case BTRACE_CODE:            trace_mode=1;  break; 
  1093.     case NOBTRACE_CODE:          trace_mode=0;  break; 
  1094.     case LTRACE_CODE:    IfPass2 ltrace_mode=1; break; 
  1095.     case NOLTRACE_CODE:  IfPass2 ltrace_mode=listing_mode; break; 
  1096.     case ATRACE_CODE:    IfPass2 ltrace_mode=2; break; 
  1097.     case NOATRACE_CODE:  IfPass2 ltrace_mode=listing_mode; break; 
  1098.  
  1099.     case LISTSYMBOLS_CODE:  IfPass2 list_symbols();     break;
  1100.     case LISTOBJECTS_CODE:  IfPass2 list_object_tree(); break;
  1101.     case LISTVERBS_CODE:    IfPass2 list_verb_table();  break;
  1102.     case LISTDICT_CODE:     IfPass2 show_dictionary();  break;
  1103.  
  1104.     default: error("Internal error - unknown directive code");
  1105.   }
  1106.     return;
  1107. }
  1108.  
  1109.