Inform - Support - Patches

About Patches  

Compiler  
Library  

DM4 Errata  

Issue C63003     [previous patch]

Erroneous "Branch out of range" message
Submitted by: Graham Nelson     Appeared in: Compiler 6.30     Fixed in: -
Problem

Obscure circumstances cause the erroneous message:

  File "<veneer routine 'RT__ChPrintS'>"; Line 1 # Fatal error:
  Branch out of range: divide the routine up?

This is in response to apparently valid code that compiles correctly under 6.21.

Solution (by Cedric Knight)

The error is not erroneous, but the location given is. If an error occurs when compiling the infix symbol table, the last veneer routine is quoted. This can be fixed like this:

diff -u inform630ref\veneer.c .\veneer.c
--- inform630ref\veneer.c	Fri Feb 27 06:30:00 2004
+++ .\veneer.c	Sat Mar 20 21:38:44 2004
@@ -2163,6 +2163,8 @@
     assign_symbol(j,
         assemble_routine_header(2, FALSE, "Symb__Tab", &null_dbgl, FALSE, j),
         ROUTINE_T);
+    restart_lexer("", "Symb__Tab");
+
     sflags[j] |= SYSTEM_SFLAG + USED_SFLAG;
     if (trace_fns_setting==3) sflags[j] |= STAR_SFLAG;

Inform 6.21 didn't have the 'branch out of range' error, but Infix instructions like '; story' when there were very many arrays or routines could cause illegal opcode or other problems. One possibility is to break Symb__Tab into three separate routines, so that it can't possibly overflow. However, a general solution is to extend the maximum range of branches, and the maximum size of the symbol table, fourfold like this:

diff -u inform630ref\asm.c .\asm.c
--- inform630ref\asm.c	Fri Feb 27 06:30:00 2004
+++ .\asm.c	Sat Mar 20 21:49:12 2004
@@ -1531,13 +1530,18 @@
         {   if (asm_trace_level >= 4)
                 printf("Branch detected at offset %04x\n", pc);
             j = (256*zcode_holding_area[i] + zcode_holding_area[i+1]) & 0x7fff;
+            addr = label_offsets[j]-pc;
             if (asm_trace_level >= 4)
                 printf("To label %d, which is %d from here\n",
-                    j, label_offsets[j]-pc);
-            if ((label_offsets[j] >= pc+2) && (label_offsets[j] < pc+64))
+                    j, addr);
+            if ((addr > 2) && (addr < 64))
             {   if (asm_trace_level >= 4) printf("Short form\n");
                 zcode_markers[i+1] = DELETED_MV;
             }
+            else if (addr<-0x2000 || addr>0x1fff) 
+            {   if (asm_trace_level >= 4) printf("Inverted branch and jump\n");
+                zcode_markers[i+1] = EXPANDED_MV;
+            }
         }
     }

@@ -1567,6 +1571,7 @@
                 label = label_next[label];
             }
            if (zcode_markers[i] != DELETED_MV) new_pc++;
+           if (zcode_markers[i] == EXPANDED_MV) new_pc+=2;
         }
     }

@@ -1578,19 +1583,28 @@
     {   switch(zcode_markers[i])
         { case BRANCH_MV:
             long_form = 1; if (zcode_markers[i+1] == DELETED_MV) long_form = 0;
+            if (zcode_markers[i+1] == EXPANDED_MV) long_form = 3;

             j = (256*zcode_holding_area[i] + zcode_holding_area[i+1]) & 0x7fff;
             branch_on_true = ((zcode_holding_area[i]) & 0x80);
             offset_of_next = new_pc + long_form + 1;

             addr = label_offsets[j] - offset_of_next + 2;
-            if (addr<-0x2000 || addr>0x1fff) 
+            if (addr<-0x8000 || addr>0x7fff) 
                 fatalerror("Branch out of range: divide the routine up?");
             if (addr<0) addr+=(int32) 0x10000L;

-            addr=addr&0x3fff;
-            if (long_form==1)
-            {   zcode_holding_area[i] = branch_on_true + addr/256;
+            if (long_form==3)
+            {   zcode_holding_area[i] = (0x80 ^ branch_on_true) + 0x40 + 5;
+                transfer_byte(zcode_holding_area + i); new_pc++;
+                zcode_holding_area[i] = 0x8c;
+                transfer_byte(zcode_holding_area + i); new_pc++;
+                zcode_holding_area[i] = addr/256;
+                zcode_holding_area[i+1] = addr%256;
+            }
+            else if (long_form==1)
+            {   addr=addr&0x3fff;
+                zcode_holding_area[i] = branch_on_true + addr/256;
                 zcode_holding_area[i+1] = addr%256;
             }
             else
@@ -1619,7 +1633,8 @@

           default:
             switch(zcode_markers[i] & 0x7f)
-            {   case NULL_MV: break;
+            {   case EXPANDED_MV:
+                case NULL_MV: break;
                 case VARIABLE_MV:
                 case OBJECT_MV:
                 case ACTION_MV:
diff -u inform630ref\header.h .\header.h
--- inform630ref\header.h	Fri Feb 27 06:30:00 2004
+++ .\header.h	Sat Mar 20 18:24:28 2004
@@ -1836,8 +1836,9 @@

 #define LABEL_MV              36     /* Ditto: marks "jump" operands */
 #define DELETED_MV            37     /* Ditto: marks bytes deleted from code */
-#define BRANCH_MV             38     /* Used in "asm.c" for routine coding */
-#define BRANCHMAX_MV          58     /* In fact, the range BRANCH_MV to 
+#define EXPANDED_MV           38     /* asm.c again: marks branch to invert */
+#define BRANCH_MV             39     /* Used in "asm.c" for routine coding */
+#define BRANCHMAX_MV          59     /* In fact, the range BRANCH_MV to 
                                         BRANCHMAX_MV all means the same thing.
                                         The position within the range means
                                         how far back from the label to go


Last updated 17 April 2013. This site is no longer supported; information may be out of date.
Maintained as a historical archive by the Interactive Fiction Technology Foundation. Copyright 1993-2018 IFTF, CC-BY-SA unless otherwise noted.
This page was originally managed by Roger Firth.