home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-10-07 | 34.0 KB | 1,109 lines |
- /* ------------------------------------------------------------------------- */
- /* "asm" : The Inform assembler */
- /* */
- /* Part of Inform release 5 */
- /* ------------------------------------------------------------------------- */
-
- #include "header.h"
-
- int in_routine_flag, no_stubbed;
-
- int ignoring_routine;
-
- static int return_flag;
- static int stub_flags[32];
-
- static int lower_strings_flag=0;
-
- static int ifdef_stack[MAX_IFDEF_DEPTH];
- static int ifdef_sp=0;
- static int started_ignoring=0;
-
- #ifndef ALLOCATE_BIG_ARRAYS
- static long int pa_forwards[MAX_FORWARD_REFS];
- #else
- static long int *pa_forwards;
- #endif
-
- extern void asm_allocate_arrays(void)
- {
- #ifdef ALLOCATE_BIG_ARRAYS
- pa_forwards = (long int *) my_calloc(sizeof(long int), MAX_FORWARD_REFS,
- "forward references");
- #endif
- }
-
- extern void asm_free_arrays(void)
- {
- #ifdef ALLOCATE_BIG_ARRAYS
- my_free(pa_forwards, "forward references");
- #endif
- }
-
- /* ------------------------------------------------------------------------- */
- /* Decode arguments as constants and variables */
- /* (Gratuitous Space:1999 reference by Mr Dilip Sequeira of Edinburgh */
- /* University) */
- /* ------------------------------------------------------------------------- */
-
- static int cvflag;
- static char scratch_b[64];
- extern int32 constant_value(char *b)
- { int32 i, j, k, base=10, f, rv, moon, alpha, victor=0, eagle;
-
- if (b[0]=='\'')
- { if ((b[2]=='\'') && (b[3]==0))
- return(translate_to_ascii(b[1]));
- i=strlen(b);
- if ((i>=4)&&(b[i-1]=='\''))
- { b[i-1]=0; for (;i>0;i--) b[i]=b[i-1];
- b[0]='n'; b[1]='$';
- }
- }
- cvflag=0;
- if (b[0]=='#') b++;
- if (b[0]=='#')
- { i=find_symbol(b+1);
- if ((i>=0)&&(stypes[i]==18)) return(svals[i]);
- if (strlen(b)>60)
- { error_named("Action name over 60 characters long:",b);
- return(0);
- }
- sprintf(scratch_b,"a$%sSub",b+1);
- b=scratch_b;
- }
- if (b[0]=='\"')
- { dequote_text(b);
-
- if (lower_strings_flag==1)
- {
- j=subtract_pointers(low_strings_p,low_strings);
- low_strings_p=translate_text(low_strings_p,b);
- i= subtract_pointers(low_strings_p,low_strings);
- if (i>MAX_LOW_STRINGS)
- memoryerror("MAX_LOW_STRINGS", MAX_LOW_STRINGS);
- cvflag=1;
- return(0x21+(j/2));
- }
-
- j= subtract_pointers(strings_p,strings);
-
- #ifdef USE_TEMPORARY_FILES
- {
- zip *c;
- c=translate_text(strings,b);
- i= subtract_pointers(c,strings);
- strings_p+=i;
- if (pass_number==2)
- { for (c=strings; c<strings+i; c++)
- { fputc(*c,Temp1_fp);
- add_to_checksum((void *) c);
- }
- }
- }
- #else
- strings_p=translate_text(strings_p,b);
- i= subtract_pointers(strings_p,strings);
- if (i>MAX_STATIC_STRINGS)
- memoryerror("MAX_STATIC_STRINGS",MAX_STATIC_STRINGS);
- #endif
-
- while ((i%scale_factor)!=0)
- { i+=2;
- #ifdef USE_TEMPORARY_FILES
- strings_p+=2;
- if (pass_number==2)
- { fputc(0,Temp1_fp);
- fputc(0,Temp1_fp);
- }
- #else
- *(strings_p++)=0;
- *(strings_p++)=0;
- #endif
- }
-
- cvflag=1;
- return((strings_offset+j)/scale_factor);
- }
- if(*b=='$')
- { if(*++b=='$') {b++;base=2;}
- else base=16;
- }
- else if(*b=='-') {b++;victor=1;}
- else for (i=0; b[i]; i++) if (!isdigit(b[i])) goto nonumber;
-
- for(moon=0;*b;b++)
- { alpha=isalpha(*b)?(tolower(*b)-'a'+10):*b-'0';
- if(alpha>=base || alpha<0) break; else moon=moon*base+alpha;
- }
- if (victor==0) return(moon);
- eagle=((int32) 0x10000L)-moon;
- return(eagle);
- nonumber:
-
- f=0;
- if (strcmp(b,"adjectives_table")==0) return(adjectives_offset);
- if (strcmp(b,"preactions_table")==0) return(preactions_offset);
- if (strcmp(b,"actions_table")==0) return(actions_offset);
- if (strcmp(b,"version_number")==0) return(version_number);
- if (strcmp(b,"largest_object")==0) return(256+max_no_objects-1);
- if (strcmp(b,"strings_offset")==0)
- { InV3 return(strings_offset/2);
- InV5 return(strings_offset/4);
- }
- if (strcmp(b,"code_offset")==0)
- { InV3 return(code_offset/2);
- InV5 return(code_offset/4);
- }
- if (strcmp(b,"dict_par1")==0) return((version_number==3)?4:6);
- if (strcmp(b,"dict_par2")==0) return((version_number==3)?5:7);
- if (strcmp(b,"dict_par3")==0) return((version_number==3)?6:8);
- if ((b[0]=='a')&&(b[1]=='$')) { b+=2; f=1; }
- if ((b[0]=='w')&&(b[1]=='$'))
- { k=dictionary_find(b+2,2);
- rv=dictionary_offset+7+((version_number==3)?7:9)*(k-1);
- if ((k==0)&&(pass_number==2))
- error_named("Dictionary word not found for constant",b);
- }
- else
- { if ((b[0]=='n')&&(b[1]=='$'))
- { rv=dictionary_add(b+2,0x80,0,0);
- }
- else
- { if ((b[0]=='r')&&(b[1]=='$'))
- { i=find_symbol(b+2);
- if (i<0)
- { if (pass_number==2)
- error_named("No such routine as",b);
- return(256);
- }
- rv=svals[i]; if (rv<256) rv=256;
- }
- else
- { i=find_symbol(b);
- if (i<0)
- { if (pass_number==2)
- error_named("No such constant as",b);
- return(0);
- }
- rv=svals[i];
- }
- }
- }
- switch(stypes[i])
- { case 1: rv=(rv+code_offset)/scale_factor;
- break;
- case 2:
- case 3: error_named("Not a constant:",b); return(0);
- case 4:
- case 10: error_named("Reserved word as constant:",b); return(0);
- }
- if (f==0) return(rv);
- j=find_action(svals[i]);
- return(j);
- }
-
- /* ------------------------------------------------------------------------- */
- /* parse_argument returns: 1000+n Constant value n */
- /* long_form_flag set if long form vital */
- /* n Variable n */
- /* ------------------------------------------------------------------------- */
-
- static char known_unknowns[MAX_IDENTIFIER_LENGTH*16];
- static int no_knowns;
-
- static long int pa_id;
- static int pa_ref;
- static int max_pa_ref;
- static int long_form_flag;
-
- extern void args_begin_pass(void)
- { if (pass_number==2) max_pa_ref=pa_ref;
- pa_ref=0; pa_id=0;
- }
-
- static int32 parse_argument(char *b)
- { int i, flag=0;
- long_form_flag=0;
- if (b[0]=='#') return(1000+constant_value(b));
- if ((b[0]=='-')||(b[0]=='$')||(b[0]=='\"')||(b[0]=='\''))
- return(1000+constant_value(b));
- for (i=0; b[i]!=0; i++) if (isdigit(b[i])==0) flag=1;
- if (flag==0) return(1000+constant_value(b));
- if (in_routine_flag==1)
- { i=local_find_symbol(b);
- if (i>=0) return(1+svals[i]);
- }
- pa_id++;
-
- i=find_symbol(b);
- if (i>=0)
- { switch(stypes[i])
- { case 1: return(1000+svals[i]);
- case 2: return(16+svals[i]);
- case 4: if (svals[i]==0) return(0);
- case 7:
- case 12:
- case 13:
- case 18:
- case 8:
- case 9: if (pass_number==2)
- { while ((pa_ref<max_pa_ref)
- &&(pa_id>pa_forwards[pa_ref])) pa_ref++;
- if ((pa_ref<max_pa_ref)
- &&(pa_id==pa_forwards[pa_ref]))
- { long_form_flag=1;
- /* printf("'%s' ref %d id %d seems forward\n",b,pa_ref, pa_id); */
- }
- }
- return(1000+constant_value(b));
- default: error_named("Type mismatch in argument",b);
- return(0);
- }
- }
-
- if (pass_number==1)
- { if (pa_ref==MAX_FORWARD_REFS)
- memoryerror("MAX_FORWARD_REFS", MAX_FORWARD_REFS);
- pa_forwards[pa_ref++]=pa_id;
- /* printf("'%s' ref %d id %d is forward\n",b,pa_ref, pa_id); */
- return(1256);
- }
-
- for (i=0; i<no_knowns; i++)
- if (strcmp(known_unknowns+i*MAX_IDENTIFIER_LENGTH,b)==0)
- return(0);
- if (no_knowns<16)
- strcpy(known_unknowns+(no_knowns++)*MAX_IDENTIFIER_LENGTH,b);
- error_named("No such variable as",b); return(0);
- }
-
- /* ------------------------------------------------------------------------- */
- /* Assembler of individual lines */
- /* ------------------------------------------------------------------------- */
-
- static void byteout(int32 i)
- { *zcode_p=(unsigned char) i; zcode_p++;
- #ifdef USE_TEMPORARY_FILES
- utf_zcode_p++;
- #endif
- if (subtract_pointers(zcode_p,zcode) >= MAX_ZCODE_SIZE)
- { memoryerror("MAX_ZCODE_SIZE",MAX_ZCODE_SIZE);
- }
- }
-
- static void write_operand(operand_t op)
- { int32 j;
- j=op.value;
- if (op.type!=0) byteout(j);
- else { byteout(j/256); byteout(j%256); }
- }
-
- static operand_t parse_operand(int32 number, opcode opco, char *b)
- { int32 j; int opt, type=opco.type1; operand_t oper;
-
- word(b,number+2);
-
- if (((type==CALL)||(type==NCALL))&&(number==0))
- { if (pass_number==2)
- {
- j=find_symbol(b);
- if (j==-1) { no_such_label(b); }
- if (stypes[j]!=1) { error_named("Not a label:",b); }
- oper.value=(code_offset+svals[j])/scale_factor;
- oper.type=0;
- }
- else
- { oper.value=0x1000; oper.type=0;
- }
- return(oper);
- }
-
- j=parse_argument(b);
-
- if (j>=1256) { opt=0; j=j-1000; }
- else if (j>=1000) { opt=1; j=j-1000; }
- else opt=2;
-
- if ((opt==1) && (long_form_flag==1)) opt=0;
-
- if ((opco.type2==VAR)&&(opt==2)&&(number==0)) opt=1;
-
- oper.value=j; oper.type=opt;
- return(oper);
- }
-
- int a_from_one=0;
- int line_done_flag = 0;
-
- extern int assemble_opcode(char *b, int32 offset, opcode opco)
- {
- zip *opc, *opcname, *ac;
- int32 j, topbits, addr, cargs, ccode, oldccode,
- multi, mask, flag, longf, branchword, offset_here;
- operand_t oper1, oper2;
-
- if (opco.type1==INVALID)
- { if (version_number==3)
- { warning_named("Ignoring Advanced-game opcode",b); }
- else
- { warning_named("Ignoring Standard-game opcode",b); }
- return(1);
- }
- return_flag=0;
- if (opco.type1==RETURN) return_flag=1;
- if (opco.type1==INDIR)
- { byteout(0xE0); byteout(0xBF); byteout(0); byteout(0);
- goto Line_Done;
- }
- opcname=opco.name;
- switch(opco.no)
- { case VARI: topbits=0xc0; break;
- case ZERO: topbits=0xb0; break;
- case ONE: topbits=0x80; break;
- case TWO: topbits=0x00; break;
- }
-
- opc=zcode_p;
-
- if (opco.no!=EXTD)
- { byteout(topbits+opco.code);
- }
- else
- { byteout(0xbe); byteout(opco.code); opco.no=VARI;
- }
-
- if (opco.type1==JUMP)
- { word(b,2);
- if (pass_number==1) addr=0;
- else
- { j=find_symbol(b);
- if (j<0) { no_such_label(b); return(1); }
- if (stypes[j]!=6) { error_named("Not a label:",b); return(1); }
- addr=svals[j]-offset-1;
- if (addr<0) addr+=(int32) 0x10000L;
- }
- byteout(addr/256); byteout(addr%256);
- goto Line_Done;
- }
-
- if (opco.type2==TEXT)
- { char *tmp;
- if (a_from_one==1) textword(b,1); else textword(b,2);
- tmp=zcode_p; zcode_p=translate_text(zcode_p,b);
- j=subtract_pointers(zcode_p,tmp);
- #ifdef USE_TEMPORARY_FILES
- utf_zcode_p+=j;
- #endif
- }
-
- switch(opco.no)
- { case VARI:
- ac=zcode_p; byteout(0);
- cargs= -1; ccode=0xff;
- while (word(b,(++cargs)+2),(b[0]!=0))
- { if (b[0]=='?') { branchword=cargs+2; break; }
- switch(cargs)
- { case 0: multi=0x40; mask=0xc0; break;
- case 1: multi=0x10; mask=0x30; break;
- case 2: multi=0x04; mask=0x0c; break;
- case 3: multi=0x01; mask=0x03; break;
- case 4: multi=0;
- if ((opco.type1!=CALL)&&(opco.type1!=STORE))
- error("Too many arguments");
- break;
- default: error("Too many arguments"); break;
- }
-
- oper1=parse_operand(cargs, opco, b);
-
- write_operand(oper1);
- oldccode=ccode; ccode = (ccode & (~mask)) + oper1.type*multi;
- }
- if ((opco.type1==CALL)||(opco.type1==STORE))
- { if (oper1.type!=2)
- { error("Can't store to that (no such variable)"); }
- *ac=oldccode;
- }
- else *ac=ccode;
- break;
- case ONE:
- oper1=parse_operand(0,opco,b);
- *opc=(*opc) + oper1.type*0x10;
- write_operand(oper1);
- break;
- case TWO:
- oper1=parse_operand(0,opco,b);
- oper2=parse_operand(1,opco,b);
-
- if ((oper1.type==0)||(oper2.type==0))
- { *opc=(*opc) + 0xc0;
- byteout(oper1.type*0x40 + oper2.type*0x10 + 0x0f);
- }
- else
- { if (oper1.type==2) *opc=(*opc) + 0x40;
- if (oper2.type==2) *opc=(*opc) + 0x20;
- }
- write_operand(oper1);
- write_operand(oper2);
- break;
- case ZERO:
- break;
- }
-
- if ((opco.no==ONE) || (opco.no==TWO))
- { if ((opco.type1==STORE)||(opco.type1==CALL))
- { if (opco.no==ONE) oper1=parse_operand(1,opco,b);
- if (opco.no==TWO) oper1=parse_operand(2,opco,b);
- if (oper1.type!=2)
- { error("Can't store to that (no such variable)"); }
- byteout(oper1.value);
- }
- }
-
- if ((opco.type1==BRANCH)||(opco.type2==OBJECT))
- { int o=0; int32 pca;
- pca= subtract_pointers(zcode_p,opc) -1;
- switch(opco.no)
- { case ZERO: word(b,2); break;
- case ONE: if (opco.type2!=OBJECT) { word(b,3); break; }
- case TWO: word(b,4); break;
- case VARI: word(b,branchword); break;
- }
- if (b[0]=='?') { longf=1; o++; }
- else
- { int o2=0;
- if (b[0]=='~') o2=1;
- if (pass_number==1)
- { j=find_symbol(b+o2);
- if (j<0) longf=0;
- else longf=1;
- }
- else
- { j=find_symbol(b+o2);
- if (j<0) longf=0;
- else
- { if (offset-svals[j]>0) longf=1;
- else longf=0;
- if ((svals[j]-offset-pca)>30)
- { error("Branch too far forward: use '?'"); return(1); }
- }
- }
- }
- /* printf("Branch at %04x has longf=%d\n",offset,longf); */
- if (pass_number==1) { byteout(0); if (longf==1) byteout(0); }
- else
- { if (b[o]=='~') { flag=0; o++; } else flag=1;
- j=find_symbol(b+o);
- if (j<0) { no_such_label(b+o); return(1); }
- switch(stypes[j])
- { case 4:
- switch(svals[j])
- { case 1: addr=1; longf=0; break;
- case 2: addr=0x20; longf=0; break;
- default: error("No such return condition for branch");
- return(1);
- }
- break;
- case 1: error("Can't branch to a routine, only to a label");
- return(1);
- case 6:
- if (longf==1) pca++;
- addr=svals[j]-offset-pca;
- if (addr<0) addr+=(int32) 0x10000L; break;
- default: error_named("Not a label:",b+o); return(1);
- }
- addr=addr&0x3fff;
- if (longf==1)
- { byteout(flag*0x80 + addr/256); byteout(addr%256); }
- else
- byteout(flag*0x80+ 0x40 + (addr&0x3f));
- }
- }
-
- Line_Done:
-
- if (trace_mode==1)
- { printf("%04d %04x %-14s ", current_source_line(),
- offset+code_offset,opcname);
- for (j=0;opc<zcode_p; j++, opc++)
- { printf("%02x ", *opc);
- if (j%16==15) printf("\n ");
- }
- printf("\n");
- }
-
- if ((debugging_file==1)&&(pass_number==2)
- &&(line_done_flag==0))
- { debug_pass=2; line_done_flag=1;
- write_debug_byte(10); write_debug_linenum();
- offset_here = offset+code_offset;
- write_debug_byte((offset_here/256)/256);
- write_debug_byte((offset_here/256)%256);
- write_debug_byte(offset_here%256);
- debug_pass=1;
- }
-
- #ifdef USE_TEMPORARY_FILES
- {
- zip *c;
- int32 i;
- i= subtract_pointers(zcode_p,zcode);
- if (pass_number==2)
- { for (c=zcode; c<zcode+i; c++)
- { fputc(*c,Temp2_fp);
- add_to_checksum((void *) c);
- }
- }
- zcode_p=zcode;
- }
- #endif
-
- return(1);
- }
-
- /* ------------------------------------------------------------------------- */
- /* Making attributes and properties (incorporating "alias" code suggested */
- /* by Art Dyer) */
- /* ------------------------------------------------------------------------- */
-
- static void trace_s(char *name, int32 code, int f)
- { if (debugging_file==1)
- { write_debug_byte(5+f); write_debug_byte(code);
- write_debug_string(name);
- }
- if ((printprops_mode==0)||(pass_number==2)) return;
- printf("%s %02d ",(f==0)?"Attr":"Prop",code);
- if (f==0) printf(" ");
- else printf("%s%s",(prop_longflag[code]==1)?"L":" ",
- (prop_additive[code]==1)?"A":" ");
- printf(" %s\n",name);
- }
-
- static void make_attribute(char *b)
- { int i;
-
- word(b,3);
- if (strcmp(b,"alias")==0)
- {
- word(b,4);
- if (b[0]==0)
- { error("Expected an attribute name after 'alias'");
- return;
- }
- if (((i=find_symbol(b))==-1)||(stypes[i]!=7))
- { error_named("'alias' refers to undefined attribute",b);
- return;
- }
- word(b,2);
- trace_s(b,svals[i],0);
- new_symbol(b,svals[i],7);
- return;
- }
- InV3
- { if (no_attributes==32)
- { error("All 32 attributes already declared (compile as Advanced \
- game to get an extra 16)"); return; }
- }
- InV5
- { if (no_attributes==48)
- { error("All 48 attributes already declared"); return; }
- }
- word(b,2);
- trace_s(b,no_attributes,0);
- new_symbol(b,no_attributes++,7);
- return;
- }
-
- static void make_property(char *b)
- { int32 def=0;
- int i, fl, longflag=0, addflag=0;
-
- fl=2;
- do
- { word(b,fl++);
- if (strcmp(b,"long")==0) longflag=1;
- else if (strcmp(b,"additive")==0) addflag=1;
- else break;
- } while (1==1);
-
- word(b,fl);
- if (strcmp(b,"alias")==0)
- { if (longflag)
- { error("'alias' incompatible with 'long'"); return; }
- if (addflag)
- { error("'alias' incompatible with 'additive'"); return; }
- word(b,4);
- if (b[0]==0)
- { error("Expected a property name after 'alias'"); return; }
- i=find_symbol(b);
- if (((i=find_symbol(b))==-1)||(stypes[i]!=12))
- { error_named("'alias' refers to undefined property",b);
- return;
- }
- word(b,2);
- trace_s(b,svals[i],1);
- new_symbol(b,svals[i],12);
- return;
- }
- InV3
- { if (no_properties==32)
- { error("All 30 properties already declared (compile as Advanced \
- game to get an extra 32)"); return; }
- }
- InV5
- { if (no_properties==64)
- { error("All 62 properties already declared"); return; }
- }
- if (b[0]!=0) def=constant_value(b);
- word(b,fl-1);
- prop_defaults[no_properties]=def;
- InV3 { prop_longflag[no_properties]=longflag; }
- InV5 { prop_longflag[no_properties]=1; }
- prop_additive[no_properties]=addflag;
- trace_s(b,no_properties,1);
- new_symbol(b,no_properties++,12);
- return;
- }
-
- static void make_fake_action(char *b)
- { word(b,2);
- new_symbol(b,255-no_fake_actions++,18);
-
- if (debugging_file==1)
- { write_debug_byte(7); write_debug_byte(256-no_fake_actions);
- write_debug_string(b);
- }
- return;
- }
-
- /* ------------------------------------------------------------------------- */
- /* Assembler directives: for diagnosis, and making the non-code part of */
- /* the file */
- /* ------------------------------------------------------------------------- */
-
- static int lmoved_flag=0;
-
- extern void assemble_label(int32 offset, char *b)
- { int i;
- if (pass_number==1) new_symbol(b,offset,6);
- else
- { i=find_symbol(b);
- if (svals[i]!=offset)
- if (lmoved_flag==0)
- { lmoved_flag=1;
- if (no_errors==0)
- error("A label has moved between passes because of a low-level error \
- just before (perhaps an improper use of a routine address as a constant)");
- }
- }
- if (trace_mode==1) printf(".%s\n",b);
- return_flag=0;
- }
-
- static void stack_sline(char *s1, char *b)
- { char rw[100];
- sprintf(rw,s1,b); stack_line(rw);
- }
-
- static int constant_made_flag = 0;
-
- extern void assemble_directive(char *b, int32 offset, int32 code)
- { int i, j, condition=0, debugged_routine;
-
- switch(code)
- {
- case IFDEF_CODE:
- word(b,2); i=find_symbol(b);
- if (i>=0) condition=1;
- goto generic_if;
- case IFNDEF_CODE:
- word(b,2); i=find_symbol(b);
- if (i==-1) condition=1;
- goto generic_if;
- case IFV3_CODE:
- if (version_number==3) condition=1; goto generic_if;
- case IFV5_CODE:
- if (version_number==5) condition=1; goto generic_if;
-
- generic_if:
-
- if (ifdef_sp==MAX_IFDEF_DEPTH)
- { error("'#IF' nested too deeply: increase #define MAX_IFDEF_DEPTH");
- return;
- }
- ifdef_stack[ifdef_sp++]=ignoring_mode;
- if (ignoring_mode==0)
- { ignoring_mode=1-condition;
- started_ignoring=ifdef_sp;
- }
- return;
-
- case ENDIF_CODE:
- if (ifdef_sp==0)
- { error("'#ENDIF' without matching '#IF'"); return; }
- ignoring_mode=(ifdef_stack[--ifdef_sp])%2;
- return;
-
- case IFNOT_CODE:
- if (ifdef_sp==0)
- { error("'#IFNOT' without matching '#IF'"); return; }
- if (ifdef_stack[ifdef_sp-1]>=2)
- { error("Two '#IFNOT's in the same '#IF'"); return; }
- ifdef_stack[ifdef_sp-1]+=2;
- if (ignoring_mode==1)
- { if (ifdef_sp==started_ignoring)
- ignoring_mode=0;
- }
- else
- { ignoring_mode=1;
- }
- return;
-
- case END_CODE:
- endofpass_flag=1;
- if (trace_mode==1) printf("<end>\n");
-
- if (ifdef_sp>0)
- { error("End of file reached inside '#IF...'"); }
- break;
-
- case OPENBLOCK_CODE:
- if (is_systemfile()==1)
- { strcpy(b,"Rep__");
- word(b+5,2);
- i=find_symbol(b);
- if (i!=-1)
- { ignoring_routine=1; /* printf("Ignoring %s\n",b+5); */ break; }
- }
- word(b,2);
- ignoring_routine=0; debugged_routine=0;
- while ((offset%scale_factor)!=0) { byteout(0); offset++; }
- new_symbol(b,offset,1);
- if (trace_mode==1) printf("<Routine %d, '%s' begins at %04x; ",
- no_routines,b,offset);
-
- if (debugging_file==1)
- { debug_pass=2;
- write_debug_byte(11);
- write_debug_byte(no_routines/256);
- write_debug_byte(no_routines%256);
- write_routine_linenum(); write_debug_string(b);
- }
-
- no_locals= -1; no_knowns=0;
- routine_starts_line=current_source_line();
- no_routines++;
- if (no_routines>=MAX_ROUTINES)
- memoryerror("MAX_ROUTINES", MAX_ROUTINES);
- in_routine_flag=1; return_flag=0;
- word(b,3); if (strcmp(b,"*")==0) debugged_routine=1;
- while (word(b,(++no_locals)+3+debugged_routine),(b[0]!=0))
- { if ( ((b[0]==',')&&(b[1]==0)) || ((b[0]==':')&&(b[1]==0)))
- { error("Expected local variable but found ',' or ':' \
- (probably the ';' after the '[ ...' line was forgotten)");
- break;
- }
- new_symbol(b,no_locals,3);
- if (debugging_file==1) write_debug_string(b);
- }
-
- if (debugging_file==1) { write_debug_byte(0); debug_pass=1; }
- byteout(no_locals);
-
- if (actual_version<5)
- { for (i=0; i<no_locals; i++) { byteout(0); byteout(0); }
- }
- if (trace_mode==1) printf("%d locals>\n",no_locals);
- if (no_locals>15) error("Routine has more than 15 local variables");
- if ((no_routines==1)&&(pass_number==1))
- { word(b,2); make_lower_case(b);
- if (strcmp(b,"main")!=0)
- {
- warning_named("Since it is defined before inclusion of the library, game-play \
- will begin not at 'Main' but at the routine",b);
- }
- if (no_locals!=0)
- error("The earliest-defined routine is not allowed to have local variables");
- }
- if (nowarnings_mode==0)
- for (i=0; i<16; i++) used_local_variable[i]=0;
-
- if ((withdebug_mode==1) || (debugged_routine==1))
- { word(b,2); sprintf(sub_buffer,"print \"[%s\"",b);
- for (i=0; (i<no_locals)&&(i<3); i++)
- { word(b, 3+i+debugged_routine);
- sprintf(sub_buffer+strlen(sub_buffer), ", \", %s=\", %s", b, b);
- }
- sprintf(sub_buffer+strlen(sub_buffer), ", \"]^\"");
- stack_line(sub_buffer);
- }
- break;
-
- case CLOSEBLOCK_CODE:
-
- word(b,2);
- if (b[0]!=0)
- { if ((resobj_flag==0) || (strcmp(b,",")!=0))
- {
- if (resobj_flag>0)
- error_named(
- "Expected ',' or ';' after ']' but found",
- parse_buffer);
- else
- error_named(
- "Expected ';' after ']' but found",
- parse_buffer);
- }
- }
-
- if (trace_mode==1) printf("<Routine ends>\n");
- if (debugging_file==1)
- { debug_pass=2;
- write_debug_byte(14);
- write_debug_byte((no_routines-1)/256);
- write_debug_byte((no_routines-1)%256);
- write_re_linenum(); debug_pass=1;
- }
-
- if (return_flag==0)
- { if (resobj_flag==0) stack_line("@rtrue");
- else stack_line("@rfalse");
- }
- if (resobj_flag==1) resobj_flag=3;
-
- if (brace_sp>0)
- { error("Brace mismatch in previous routine");
- brace_sp=0;
- }
- in_routine_flag=0;
- if ((nowarnings_mode==0)&&(pass_number==1))
- { for (i=0; i<no_locals; i++)
- { if (used_local_variable[i]==0)
- { override_error_line = routine_starts_line;
- warning_named("Local variable unused:",
- local_varname[i]);
- }
- }
- }
-
- if (call_for_br_flag==1)
- { compile_box_routine();
- call_for_br_flag=0;
- }
- break;
-
- case ABBREVIATE_CODE:
- textword(b,2);
- if (pass_number==1)
- { if (no_abbrevs==MAX_ABBREVS)
- { error("Too many abbreviations declared"); break; }
- if (almade_flag==1)
- { error("All abbreviations must be declared together"); break; }
- if (strlen(b)<2)
- { error_named("It's not worth abbreviating",b); break; }
- }
- strcpy(abbreviations_at+no_abbrevs*MAX_ABBREV_LENGTH, b);
- word(b,2);
- abbrev_mode=0; lower_strings_flag=1;
- abbrev_values[no_abbrevs]=constant_value(b);
- abbrev_quality[no_abbrevs++]=trans_length-2;
- abbrev_mode=1; lower_strings_flag=0;
- break;
-
- case ATTRIBUTE_CODE:
- make_attribute(b); break;
-
- case CONSTANT_CODE:
- constant_made_flag=1;
- word(b,3);
- IfPass2
- {
- constant_value(b);
- word(b,2);
- i=find_symbol(b);
- if (stypes[i]==11)
- svals[i]=svals[i]-(0x800/scale_factor)
- +strings_offset/scale_factor;
- }
- else
- {
- i=constant_value(b);
- word(b,2);
- if (cvflag==1) new_symbol(b,i,11);
- else new_symbol(b,i,8);
- }
- break;
-
- case LOWSTRING_CODE:
- word(b,3);
- IfPass2
- { lower_strings_flag=1;
- constant_value(b);
- lower_strings_flag=0;
- word(b,2);
- i=find_symbol(b);
- }
- else
- { lower_strings_flag=1;
- i=constant_value(b);
- lower_strings_flag=0;
- word(b,2);
- if (cvflag==1) new_symbol(b,i,11);
- else new_symbol(b,i,8);
- }
- break;
-
- case DEFAULT_CODE:
- word(b,3);
- IfPass2
- {
- }
- else
- { i=constant_value(b);
- word(b,2);
- if (find_symbol(b)==-1)
- { if (cvflag==1)
- { error("Defaulted constants can't be strings"); return; }
- new_symbol(b,i,8);
- }
- }
- break;
-
- case STUB_CODE:
- i=0;
- IfPass2 { if (stub_flags[no_stubbed++]==1) i=1; }
- else
- { word(b,2); if (find_symbol(b)==-1) i=1;
- stub_flags[no_stubbed++]=i;
- }
- if (i==1)
- {
- word(b,3); i=constant_value(b); word(b,2);
- switch(i)
- { case 0: stack_sline("[ %s",b); stack_line("rfalse");
- stack_line("]"); break;
- case 1: stack_sline("[ %s x1",b); stack_line("@store x1 0");
- stack_line("rfalse"); stack_line("]"); break;
- case 2: stack_sline("[ %s x1 x2",b); stack_line("@store x1 0");
- stack_line("@store x2 0");
- stack_line("rfalse"); stack_line("]"); break;
- case 3: stack_sline("[ %s x1 x2 x3",b);
- stack_line("@store x1 0"); stack_line("@store x2 0");
- stack_line("@store x3 0");
- stack_line("rfalse"); stack_line("]"); break;
- default:
- error("Must specify 0 to 3 variables in 'stub' routine");
- return;
- }
- }
- break;
-
- case DICTIONARY_CODE:
- textword(b,3); i=dictionary_add(b,4,0,0);
- word(b,2);
- IfPass2
- { j=find_symbol(b); svals[j]=i; } else new_symbol(b,i,8);
- break;
-
- case FAKE_ACTION_CODE:
- make_fake_action(b); break;
-
- case GLOBAL_CODE: make_global(b); break;
-
- case INCLUDE_CODE:
- textword(b,2); load_sourcefile(b);
- word(b,3);
- if (b[0]!=0)
- error_named("Expected ';' after 'include <file>' but found",b);
- break;
-
- case NEARBY_CODE: make_object(b,1); break;
-
- case OBJECT_CODE: make_object(b,0); break;
-
- case CLASS_CODE: make_class(b); break;
-
- case PROPERTY_CODE: make_property(b); break;
-
- case RELEASE_CODE:
- word(b,2); release_number=constant_value(b); break;
-
- case SWITCHES_CODE:
- if (ignoreswitches_mode==0)
- { if ((pass_number==1)&&(constant_made_flag==1))
- error("A 'switches' directive must \
- must come before constant definitions");
- word(b,2); switches(b,0);
- }
- break;
-
- case STATUSLINE_CODE:
- word(b,2);
- On_("score") { statusline_flag=0; break; }
- On_("time") { statusline_flag=1; break; }
- error_named("Expected 'score' or 'time' after 'statusline' but found",
- b); break;
-
- case SERIAL_CODE:
- textword(b,2);
- if (strlen(b)!=6)
- { error("The serial number must be a 6-digit date in double-quotes");
- break; }
- for (i=0; i<6; i++)
- if (isdigit(b[i])==0)
- { error("The serial number must be a 6-digit date in double-quotes");
- break; }
- strcpy(time_given,b); time_set=1; break;
-
- case SYSTEM_CODE:
- declare_systemfile(); break;
-
- case REPLACE_CODE:
- sprintf(b, "Rep__");
- word(b+5, 2);
- new_symbol(b, 0, 19);
- break;
-
- case VERB_CODE: make_verb(b); break;
-
- case EXTEND_CODE: extend_verb(b); break;
-
- case VERSION_CODE:
- if (override_version) break;
- word(b,2); actual_version=constant_value(b);
- if (actual_version==3) version_number=3; else version_number=5;
- if (version_number==3) scale_factor=2;
- scale_factor=4; if (actual_version==6) scale_factor=8;
- if ((version_number>=3)&&(version_number<=6)) break;
- error("The version number must be 3 to 6: 3 for Standard games and \
- 5 for Advanced"); break;
-
- case TRACE_CODE: IfPass2 trace_mode=1; break;
- case NOTRACE_CODE: IfPass2 trace_mode=tracing_mode; break;
- case ETRACE_CODE:
- IfPass2
- { word(b,2); if (b[0]==0) { etrace_mode=2; break; }
- if (strcmp(b,"full")==0) { etrace_mode=1; break; }
- error_named("Expected 'full' or nothing after 'etrace' but found", b);
- break;
- }
- case NOETRACE_CODE: IfPass2 etrace_mode=0; break;
- case BTRACE_CODE: trace_mode=1; break;
- case NOBTRACE_CODE: trace_mode=0; break;
- case LTRACE_CODE: IfPass2 ltrace_mode=1; break;
- case NOLTRACE_CODE: IfPass2 ltrace_mode=listing_mode; break;
- case ATRACE_CODE: IfPass2 ltrace_mode=2; break;
- case NOATRACE_CODE: IfPass2 ltrace_mode=listing_mode; break;
-
- case LISTSYMBOLS_CODE: IfPass2 list_symbols(); break;
- case LISTOBJECTS_CODE: IfPass2 list_object_tree(); break;
- case LISTVERBS_CODE: IfPass2 list_verb_table(); break;
- case LISTDICT_CODE: IfPass2 show_dictionary(); break;
-
- default: error("Internal error - unknown directive code");
- }
- return;
- }
-
-