Inform - Support - Patches

About Patches  

Compiler  
Library  

DM4 Errata  

Issue C63104     [previous patch]

Support @push and @pull macros in Glulx
Submitted by: Jesse McGrew     Appeared in: Compiler 6.31 or before     Fixed in: -
Problem

This patch makes @push x and @pull x work as aliases for @copy x sp and @copy sp x, respectively, when in Glulx mode. Many of the ifdef blocks in the library are there only because Z-code and Glulx currently use different syntax for saving values on the stack.

Solution

Apply the following patch.

diff -c inform631-old/asm.c inform631_source/asm.c
*** inform631-old/asm.c	Sat Jan 28 06:13:46 2006
--- inform631_source/asm.c	Sat Jul 15 05:41:42 2006
***************
*** 554,559 ****
--- 554,566 ----
    { (uchar *) "callfiii",   0x0163, St, 0, 5 },
  };

+ /* The opmacros table is used for fake opcodes. The opcode numbers are
+    ignored; this table is only used for argument parsing. */
+ static opcodeg opmacros_table_g[] = {
+   { (uchar *) "pull", 0, St, 0, 1 },
+   { (uchar *) "push", 0,  0, 0, 1 },
+ };
+
  static opcodeg custom_opcode_g;

  static opcodez internal_number_to_opcode_z(int32 i)
***************
*** 611,616 ****
--- 618,628 ----
      return x;
  }

+ static opcodeg internal_number_to_opmacro_g(int32 i)
+ {
+     return opmacros_table_g[i];
+ }
+
  static void make_opcode_syntax_g(opcodeg opco)
  {
      int ix;
***************
*** 944,949 ****
--- 956,1015 ----
      error_named("Assembly mistake: syntax is", opcode_syntax_string);
  }

+ static void assembleg_macro(assembly_instruction *AI)
+ {
+     /* validate macro syntax first */
+     int ix, no_operands_given;
+     opcodeg opco;
+
+     opco = internal_number_to_opmacro_g(AI->internal_number);
+     no_operands_given = AI->operand_count;
+
+     if (no_operands_given != opco.no)
+         goto OpcodeSyntaxError;
+
+     for (ix = 0; ix < no_operands_given; ix++) {
+         int type = AI->operand[ix].type;
+         if ((opco.flags & St)
+           && ((!(opco.flags & Br) && (ix == no_operands_given-1))
+           || ((opco.flags & Br) && (ix == no_operands_given-2)))) {
+             if (is_constant_ot(type)) {
+                 error("*** assembly macro tried to store to a constant ***");
+                 goto OpcodeSyntaxError;
+             }
+         }
+         if ((opco.flags & St2)
+             && (ix == no_operands_given-2)) {
+             if (is_constant_ot(type)) {
+               error("*** assembly macro tried to store to a constant ***");
+               goto OpcodeSyntaxError;
+             }
+         }
+     }
+
+     /* expand the macro */
+     switch (AI->internal_number) {
+         case pull_gm:
+             assembleg_store(AI->operand[0], stack_pointer);
+             break;
+
+         case push_gm:
+             assembleg_store(stack_pointer, AI->operand[0]);
+             break;
+
+         default:
+             compiler_error("Invalid Glulx assembly macro");
+             break;
+     }
+
+     return;
+
+     OpcodeSyntaxError:
+
+     make_opcode_syntax_g(opco);
+     error_named("Assembly mistake: syntax is", opcode_syntax_string);
+ }
+
  extern void assembleg_instruction(assembly_instruction *AI)
  {
      uchar *start_pc, *opmodes_pc;
***************
*** 2729,2741 ****
  {
    opcodeg O;
    assembly_operand AO;
!   int error_flag = FALSE;

    AI.operand_count = 0;

    opcode_names.enabled = TRUE;
    get_next_token();
    opcode_names.enabled = FALSE;

    if (token_type == DQ_TT) {
      error("Runtime assembly definitions are not yet supported in Glulx.");
--- 2795,2809 ----
  {
    opcodeg O;
    assembly_operand AO;
!   int error_flag = FALSE, is_macro = FALSE;

    AI.operand_count = 0;

    opcode_names.enabled = TRUE;
+   opcode_macros.enabled = TRUE;
    get_next_token();
    opcode_names.enabled = FALSE;
+   opcode_macros.enabled = FALSE;

    if (token_type == DQ_TT) {
      error("Runtime assembly definitions are not yet supported in Glulx.");
***************
*** 2743,2755 ****
      return;
    }
    else {
!     if (token_type != OPCODE_NAME_TT) {
        ebf_error("an opcode name", token_text);
        panic_mode_error_recovery();
        return;
      }
      AI.internal_number = token_value;
!     O = internal_number_to_opcode_g(AI.internal_number);
    }

    return_sp_as_variable = TRUE;
--- 2811,2828 ----
      return;
    }
    else {
!     if (token_type != OPCODE_NAME_TT && token_type != OPCODE_MACRO_TT) {
        ebf_error("an opcode name", token_text);
        panic_mode_error_recovery();
        return;
      }
      AI.internal_number = token_value;
!     if (token_type == OPCODE_MACRO_TT) {
!       O = internal_number_to_opmacro_g(AI.internal_number);
!       is_macro = TRUE;
!     }
!     else
!       O = internal_number_to_opcode_g(AI.internal_number);
    }

    return_sp_as_variable = TRUE;
***************
*** 2791,2798 ****
      error_flag = TRUE;
    }

!   if (!error_flag)
!     assembleg_instruction(&AI);

    if (error_flag) {
      make_opcode_syntax_g(O);
--- 2864,2875 ----
      error_flag = TRUE;
    }

!   if (!error_flag) {
!     if (is_macro)
!       assembleg_macro(&AI);
!     else
!       assembleg_instruction(&AI);
!   }

    if (error_flag) {
      make_opcode_syntax_g(O);
diff -c inform631-old/header.h inform631_source/header.h
*** inform631-old/header.h	Fri Feb 10 02:21:06 2006
--- inform631_source/header.h	Sat Jul 15 05:11:41 2006
***************
*** 1118,1123 ****
--- 1118,1131 ----
  #define callfii_gc 78
  #define callfiii_gc 79

+ /* ------------------------------------------------------------------------- */
+ /*   Index numbers into the keyword group "opcode_macros_g" (see "lexer.c")  */
+ /* ------------------------------------------------------------------------- */
+
+ #define pull_gm   0
+ #define push_gm   1
+
+
  #define SYMBOL_TT    0                      /* value = index in symbol table */
  #define NUMBER_TT    1                      /* value = the number            */
  #define DQ_TT        2                      /* no value                      */
***************
*** 1138,1143 ****
--- 1146,1152 ----
                                                 syntax for a directive        */
  #define TRACE_KEYWORD_TT  110               /* keyword used in debugging     */
  #define SYSTEM_CONSTANT_TT 111              /* such as "code_offset"         */
+ #define OPCODE_MACRO_TT   112               /* fake opcode for compatibility */

  #define OP_TT        200                    /* value = operator no           */
  #define ENDEXP_TT    201                    /* no value                      */
***************
*** 2345,2351 ****

  extern keyword_group directives, statements, segment_markers,
         conditions, system_functions, local_variables, opcode_names,
!        misc_keywords, directive_keywords, trace_keywords, system_constants;

  /* ------------------------------------------------------------------------- */
  /*   Extern definitions for "linker"                                         */
--- 2354,2361 ----

  extern keyword_group directives, statements, segment_markers,
         conditions, system_functions, local_variables, opcode_names,
!        misc_keywords, directive_keywords, trace_keywords, system_constants,
!        opcode_macros;

  /* ------------------------------------------------------------------------- */
  /*   Extern definitions for "linker"                                         */
diff -c inform631-old/lexer.c inform631_source/lexer.c
*** inform631-old/lexer.c	Sat Jan 28 06:14:30 2006
--- inform631_source/lexer.c	Sat Jul 15 05:22:36 2006
***************
*** 267,272 ****
--- 267,284 ----
      ""
  };

+ keyword_group opcode_macros =
+ { { "" },
+   OPCODE_MACRO_TT, FALSE, TRUE
+ };
+
+ static char *opmacro_list_z[] = { "" };
+
+ static char *opmacro_list_g[] = {
+     "pull", "push",
+     ""
+ };
+
  keyword_group directives =
  { { "abbreviate", "array", "attribute", "class", "constant",
      "default", "dictionary", "end", "endif", "extend", "fake_action",
***************
*** 364,373 ****
      SYSTEM_CONSTANT_TT, FALSE, TRUE
  };

! keyword_group *keyword_groups[11]
  = { NULL, &opcode_names, &directives, &trace_keywords, &segment_markers,
      &directive_keywords, &misc_keywords, &statements, &conditions,
!     &system_functions, &system_constants};

  keyword_group local_variables =
  { { "" },                                 /* Filled in when routine declared */
--- 376,385 ----
      SYSTEM_CONSTANT_TT, FALSE, TRUE
  };

! keyword_group *keyword_groups[12]
  = { NULL, &opcode_names, &directives, &trace_keywords, &segment_markers,
      &directive_keywords, &misc_keywords, &statements, &conditions,
!     &system_functions, &system_constants, &opcode_macros};

  keyword_group local_variables =
  { { "" },                                 /* Filled in when routine declared */
***************
*** 433,456 ****

  static void make_keywords_tables(void)
  {   int i, j, h, tp=0;
!     char **oplist;

!     if (!glulx_mode)
          oplist = opcode_list_z;
!     else
          oplist = opcode_list_g;

      for (j=0; *(oplist[j]); j++) {
          opcode_names.keywords[j] = oplist[j];
      }
      opcode_names.keywords[j] = "";

      for (i=0; i<HASH_TAB_SIZE; i++)
      {   keywords_hash_table[i] = -1;
          keywords_hash_ends_table[i] = -1;
      }

!     for (i=1; i<=10; i++)
      {   keyword_group *kg = keyword_groups[i];
          for (j=0; *(kg->keywords[j]) != 0; j++)
          {   h = hash_code_from_string(kg->keywords[j]);
--- 445,477 ----

  static void make_keywords_tables(void)
  {   int i, j, h, tp=0;
!     char **oplist, **maclist;

!     if (!glulx_mode) {
          oplist = opcode_list_z;
!         maclist = opmacro_list_z;
!     }
!     else {
          oplist = opcode_list_g;
+         maclist = opmacro_list_g;
+     }

      for (j=0; *(oplist[j]); j++) {
          opcode_names.keywords[j] = oplist[j];
      }
      opcode_names.keywords[j] = "";
+
+     for (j=0; *(maclist[j]); j++) {
+         opcode_macros.keywords[j] = maclist[j];
+     }
+     opcode_macros.keywords[j] = "";

      for (i=0; i<HASH_TAB_SIZE; i++)
      {   keywords_hash_table[i] = -1;
          keywords_hash_ends_table[i] = -1;
      }

!     for (i=1; i<=11; i++)
      {   keyword_group *kg = keyword_groups[i];
          for (j=0; *(kg->keywords[j]) != 0; j++)
          {   h = hash_code_from_string(kg->keywords[j]);


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.