Inform - Support - Source

Back to List

Inventory
Complete

Plain
Coloured
Gaudy

Browsing infix.h

This is the complete source code of the example game infix.inf.

0001  ! ==============================================================================
0002  !   INFIX:  Support for the optional library debugger extension "Infix".
0003  !
0004  !   Supplied for use with Inform 6 -- Release 6/11 -- Serial number 040227
0005  !
0006  !   Copyright Graham Nelson 1993-2004 but freely usable (see manuals)
0007  !
0008  !   This file is automatically Included in your game file by "Grammar" if you
0009  !   supply the -X compiler switch.
0010  ! ==============================================================================
0011   
0012  System_file;
0013   
0014  ! ------------------------------------------------------------------------------
0015   
0016  #Ifdef DEBUG;
0017   
0018  Constant INFIXTT_NUMBER          0;
0019  Constant INFIXTT_ARRAY           1;
0020  Constant INFIXTT_ROUTINE         2;
0021  Constant INFIXTT_CONSTANT        3;
0022  Constant INFIXTT_DWORD           4;
0023  Constant INFIXTT_ACTION          5;
0024  Constant INFIXTT_ATTRIBUTE       6;
0025  Constant INFIXTT_PROPERTY        7;
0026  Constant INFIXTT_GLOBAL          8;
0027  Constant INFIXTT_NAMEDOBJECT     9;
0028  Constant INFIXTT_SYSFUN         10;
0029  Constant INFIXTT_STATICSTRING   11;
0030  Constant INFIXTT_LOGICAL        12;
0031   
0032  Global infix_term_type;
0033  Global infix_data1;
0034  Global infix_data2;
0035  Global infix_lvalue;
0036  Global infix_parsed_lvalue;
0037  Array  infix_tolowercase -> 256;
0038  #Ifdef VN_1630;
0039  Array  infix_text buffer 126;
0040  #Ifnot;
0041  Array  infix_text -> 128;
0042  #Endif; ! VN_
0043   
0044   
0045  [ InfixPrintAttribute x; print (string) #attribute_names_array-->x; ];
0046   
0047  [ InfixPrintProperty x;  print (property) x; ];
0048   
0049  [ InfixPrintGlobal x;    print (string) #global_names_array-->x; ];
0050   
0051  [ InfixPrintAction x;    print (string) #action_names_array-->(x-#lowest_action_number); ];
0052   
0053  [ InfixPrintRoutine x;   print (string) #routine_names_array-->(x-#lowest_routine_number); ];
0054   
0055  [ InfixPrintConstant x;  print (string) #constant_names_array-->(x-#lowest_constant_number); ];
0056   
0057  [ InfixPrintArray x;     print (string) #array_names_array-->(x-#lowest_array_number); ];
0058   
0059  [ InfixPrintFakeAction x;
0060                          print (string) #fake_action_names_array-->(x-#lowest_fake_action_number); ];
0061   
0062  [ InfixPrintPA x n;
0063      for (n=#lowest_routine_number : n<=#highest_routine_number : n++) {
0064          if (x == Symb__Tab(INFIXTT_ROUTINE, n)) {
0065              print (InfixPrintRoutine) n; return;
0066          }
0067      }
0068      print "Routine(", x, ")";
0069  ];
0070   
0071  [ InfixMatchPrule PrintingRule range1 range2 wa wl t i i2 it2 itlc j k plus;
0072      itlc = infix_tolowercase;
0073      if (itlc->255 == 0) {
0074          for (j=0 : j<256 : j++) itlc->j = j;
0075          itlc->'A' = 'a';    itlc->'B' = 'b';
0076          itlc->'C' = 'c';    itlc->'D' = 'd';
0077          itlc->'E' = 'e';    itlc->'F' = 'f';
0078          itlc->'G' = 'g';    itlc->'H' = 'h';
0079          itlc->'I' = 'i';    itlc->'J' = 'j';
0080          itlc->'K' = 'k';    itlc->'L' = 'l';
0081          itlc->'M' = 'm';    itlc->'N' = 'n';
0082          itlc->'O' = 'o';    itlc->'P' = 'p';
0083          itlc->'Q' = 'q';    itlc->'R' = 'r';
0084          itlc->'S' = 's';    itlc->'T' = 't';
0085          itlc->'U' = 'u';    itlc->'V' = 'v';
0086          itlc->'W' = 'w';    itlc->'X' = 'x';
0087          itlc->'Y' = 'y';    itlc->'Z' = 'z';
0088      }
0089      switch(PrintingRule) {
0090        InfixPrintAttribute:
0091          if (wa->0 == '~') { wl--; wa++; plus = 100; } ! A tilde
0092          t = #attribute_names_array;
0093        InfixPrintProperty:   t = #property_names_array;
0094        InfixPrintAction:     t = #action_names_array;
0095        InfixPrintFakeAction: t = #fake_action_names_array;
0096        InfixPrintGlobal:     t = #global_names_array;
0097        InfixPrintRoutine:    t = #routine_names_array;
0098        InfixPrintAction:     t = #constant_names_array;
0099        InfixPrintArray:      t = #array_names_array;
0100      }
0101   
0102      i2 = range2-range1; it2 = infix_text+2;
0103      for (i=0 : i<=i2 : i++) {
0104          infix_text-->0 = 62; @output_stream 3 infix_text;
0105          if (t) print (string) t-->i; else PrintingRule(i+range1);
0106          @output_stream -3;
0107          k = infix_text-->0;
0108          if (k ~= wl) jump XL;
0109          if (itlc->(it2->0) ~= wa->0) jump XL;
0110          for (j=1 : j<k : j++)
0111              if (itlc->(it2->j) ~= wa->j) jump XL;
0112          parsed_number = i + range1 + plus;
0113          rtrue;
0114        .XL;
0115      }
0116      rfalse;
0117  ];
0118   
0119  [ InfixActionToken;
0120      if (InfixMatchPrule(InfixPrintAction, #lowest_action_number,
0121          #highest_action_number, WordAddress(wn), WordLength(wn))) {
0122          wn++; infix_lvalue = parsed_number; return 0;
0123      }
0124      if (InfixMatchPrule(InfixPrintFakeAction, #lowest_fake_action_number,
0125          #highest_fake_action_number, WordAddress(wn), WordLength(wn))) {
0126          wn++; infix_lvalue = parsed_number; return 0;
0127      }
0128      return -1;
0129  ];
0130   
0131  [ InfixRvalueTerm n w i initial_wn wa wl sign base digit dcount;
0132   
0133      initial_wn = wn;
0134   
0135      infix_parsed_lvalue = -1;
0136      infix_term_type = INFIXTT_NUMBER;
0137   
0138      w = NextWordStopped();
0139      if (w == -1) return -1;
0140   
0141      wa = WordAddress(wn-1);
0142      wl = WordLength(wn-1);
0143      if (wa->0 == '-' or '$' or '0' or '1' or '2' or '3'
0144                or '4' or '5' or '6' or '7' or '8' or '9') {
0145          ! Parse decimal, hex or binary number
0146   
0147          sign = 1; base = 10; dcount = 0;
0148          if (wa->0 == '-') { sign = -1; wl--; wa++; }
0149          else {
0150              if (wa->0 == '$') { base = 16; wl--; wa++; }
0151              if (wa->0 == '$') { base = 2; wl--; wa++; }
0152          }
0153          if (wl == 0) return -1;
0154          n = 0;
0155          while (wl > 0) {
0156              if (wa->0 >= 'a') digit = wa->0 - 'a' + 10;
0157              else digit = wa->0 - '0';
0158              dcount++;
0159              switch (base) {
0160                2:
0161                  if (dcount == 17) return -1;
0162                10:
0163                  if (dcount == 6) return -1;
0164                  if (dcount == 5) {
0165                      if (n > 3276) return -1;
0166                      if (n == 3276) {
0167                          if (sign == 1 && digit > 7) return -1;
0168                          if (sign == -1 && digit > 8) return -1;
0169                      }
0170                  }
0171                16:
0172                  if (dcount == 5) return -1;
0173              }
0174              if (digit >= 0 && digit < base) n = base*n + digit;
0175              else return -1;
0176              wl--; wa++;
0177          }
0178          parsed_number = n*sign; return 1;
0179      }
0180   
0181      ! Parse character constant 'a'
0182   
0183      if (wl == 3 && wa->0 == ''' && wa->2 == ''') {
0184          parsed_number = wa->1; return 1;
0185      }
0186   
0187      ! ##Action, 'dword'
0188   
0189      switch (w) {
0190        '##':
0191          infix_term_type = INFIXTT_ACTION;
0192          w = NextWordStopped(); if (w == -1) return -1;
0193          wn--;
0194          if (InfixActionToken() == 0) return 1;
0195          return -1;
0196        '^^':
0197          infix_term_type = INFIXTT_DWORD;
0198          w = NextWordStopped(); if (w == -1) return -1;
0199          parsed_number = w; return 1;
0200      }
0201   
0202      ! Test for attribute, property, class name, variable name, array name, routine
0203      ! name, constant name
0204   
0205      wn--;
0206      if ((wa->0 >= 'a' && wa->0 <= 'z') ||
0207          (wa->0 >= 'A' && wa->0 <= 'Z') ||
0208           wa->0 == '_') {
0209   
0210   
0211          infix_term_type = INFIXTT_ATTRIBUTE;
0212          if (InfixMatchPrule(InfixPrintAttribute, #lowest_attribute_number,
0213              #highest_attribute_number, wa, wl)) {
0214              wn++; return 1; }
0215   
0216          infix_term_type = INFIXTT_PROPERTY;
0217          if (InfixMatchPrule(InfixPrintProperty, #lowest_property_number,
0218              #highest_property_number, wa, wl)) {
0219              wn++; return 1; }
0220   
0221          infix_term_type = INFIXTT_GLOBAL;
0222          if (InfixMatchPrule(InfixPrintGlobal, #lowest_global_number,
0223              #highest_global_number, wa, wl)) {
0224              infix_parsed_lvalue = parsed_number-16;
0225              parsed_number = #globals_array-->infix_parsed_lvalue;
0226              wn++; return 1;
0227          }
0228   
0229          infix_term_type = INFIXTT_ARRAY;
0230          if (InfixMatchPrule(InfixPrintArray, #lowest_array_number,
0231              #highest_array_number, wa, wl)) {
0232              infix_parsed_lvalue = parsed_number;
0233              parsed_number = Symb__Tab(INFIXTT_ARRAY,parsed_number);
0234              infix_data1 = temp__global3;
0235              infix_data2 = temp__global2;
0236              wn++; return 1;
0237          }
0238   
0239          infix_term_type = INFIXTT_ROUTINE;
0240          if (InfixMatchPrule(InfixPrintRoutine, #lowest_routine_number,
0241              #highest_routine_number, wa, wl)) {
0242              infix_parsed_lvalue = parsed_number;
0243              parsed_number = Symb__Tab(INFIXTT_ROUTINE,parsed_number);
0244              infix_data1 = temp__global3;
0245              infix_data2 = temp__global2;
0246              wn++; return 1;
0247          }
0248   
0249          infix_term_type = INFIXTT_CONSTANT;
0250          if (InfixMatchPrule(InfixPrintConstant, #lowest_constant_number,
0251              #highest_constant_number, wa, wl)) {
0252              infix_parsed_lvalue = parsed_number;
0253              parsed_number = Symb__Tab(INFIXTT_CONSTANT,parsed_number);
0254              infix_data1 = temp__global3;
0255              infix_data2 = temp__global2;
0256              wn++; return 1;
0257          }
0258   
0259          switch (w) {
0260            'parent', 'child', 'children',
0261            'random', 'metaclass', 'sibling':
0262              parsed_number = w;
0263              infix_parsed_lvalue = INFIXTT_SYSFUN;
0264              wn++; return 1;
0265          }
0266      }
0267   
0268      infix_term_type = INFIXTT_NAMEDOBJECT;
0269   
0270      wn = initial_wn; i = ParseToken(SCOPE_TT, InfixBigScope);
0271   
0272      if (i == GPR_REPARSE) return i;
0273      if (i > GPR_MULTIPLE) {
0274          print "(", (name) i, " (", i, "))^";
0275          parsed_number = i; return 1;
0276      }
0277      return -1;
0278  ]; ! end of InfixRvalueTerm
0279   
0280  [ InfixBigScope x;
0281      if (scope_stage == 1) return false;  ! No multiples here
0282      if (scope_stage == 2) {
0283          objectloop (x ofclass Object) PlaceInScope(x);
0284          return true; ! That's the whole scope
0285      }
0286      print "; I'm unable to make any sense of that term.^";
0287  ];
0288   
0289  [ InfixCheckLineSpaced wa wl i force altered;
0290      for (i=1 : i<=parse->1 : i++) {
0291          wa = WordAddress(i);
0292          wl = WordLength(i);
0293          if (wl > 3 && wa->0 == ''' && wa->(wl-1) == ''') {
0294              wa->(wl-1) = ' ';
0295              if (wa->(wl-2) == '/' && wa->(wl-3) == '/') {
0296                  wa->(wl-2) = ' ';
0297                  wa->(wl-3) = ' ';
0298              }
0299              LTI_Insert(wa-buffer, ''');
0300              LTI_Insert(wa-buffer + 2, ' ');
0301              altered = true; break;
0302          }
0303      }
0304      for (i=2 : i1 + 2 : i++) {
0305          force = false;
0306          if (buffer->i == '-' && buffer->(i+1) == '-' && buffer->(i+2) == '>')
0307              force = true;
0308          if (force) {
0309              if (i>2 && buffer->(i-1) ~= ' ') {
0310                  LTI_Insert(i++, ' '); altered = true;
0311              }
0312              if (buffer->(i+3) ~= ' ') {
0313                  LTI_Insert(i+3, ' '); i++; altered = true;
0314              }
0315              i = i + 2; continue;
0316          }
0317   
0318          if (buffer->i == ':' && buffer->(i+1) == ':') force = true;
0319          if (buffer->i == '-' && buffer->(i+1) == '>') force = true;
0320          if (buffer->i == '.' && buffer->(i+1) == '&') {
0321              buffer->i = ']'; force = true;
0322          }
0323          if (buffer->i == '.' && buffer->(i+1) == '#') {
0324              buffer->i = ']'; force = true;
0325          }
0326          if (buffer->i == ']' && buffer->(i+1) == '&') force = true;
0327          if (buffer->i == ']' && buffer->(i+1) == '#') force = true;
0328          if (buffer->i == '+' && buffer->(i+1) == '+') force = true;
0329          if (buffer->i == '-' && buffer->(i+1) == '-') force = true;
0330          if (buffer->i == '&' && buffer->(i+1) == '&') force = true;
0331          if (buffer->i == '|' && buffer->(i+1) == '|') force = true;
0332          if (buffer->i == '~' && buffer->(i+1) == '~') force = true;
0333   
0334          if (buffer->i == '=' && buffer->(i+1) == '=') force = true;
0335          if (buffer->i == '~' && buffer->(i+1) == '=') force = true;
0336          if (buffer->i == '>' && buffer->(i+1) == '=') force = true;
0337          if (buffer->i == '<' && buffer->(i+1) == '=') force = true;
0338          if (buffer->i == '#' && buffer->(i+1) == '#') force = true;
0339   
0340          if (force) {
0341              if (i > 2 && buffer->(i-1) ~= ' ') {
0342                  LTI_Insert(i++, ' '); altered = true;
0343              }
0344              if (buffer->(i+2) ~= ' ') {
0345                  LTI_Insert(i+2, ' '); i++; altered = true;
0346              }
0347              i = i + 1; continue;
0348          }
0349   
0350          if (buffer->i == '+') force = true;
0351          if (buffer->i == '-') force = true;
0352          if (buffer->i == '*') force = true;
0353          if (buffer->i == '/') force = true;
0354          if (buffer->i == '%') force = true;
0355          if (buffer->i == '(') force = true;
0356          if (buffer->i == ')') force = true;
0357          if (buffer->i == '<' && buffer->(i-1) ~= ';') force = true;
0358          if (buffer->i == '>') force = true;
0359          if (buffer->i == ',') force = true;
0360          if (buffer->i == '.') force = true;
0361          if (buffer->i == '&') force = true;
0362          if (buffer->i == '|') force = true;
0363          if (buffer->i == '~') force = true;
0364          if (buffer->i == '=') force = true;
0365          if (force) {
0366              if (i > 2 && buffer->(i-1) ~= ' ') {
0367                  LTI_Insert(i++, ' '); altered = true;
0368              }
0369              if (buffer->(i+1) ~= ' ') {
0370                  LTI_Insert(i+1, ' '); i++; altered = true;
0371              }
0372          }
0373      }
0374      for (i=2 : i1 + 2 : i++)
0375          if (buffer->i == '~') { buffer->i = '['; altered = true; }
0376      return altered;
0377  ]; ! end of InfixCheckLineSpaced
0378   
0379  Array InfixRV_rvals --> 32;
0380  Array InfixRV_lvals --> 32;
0381  Array InfixRV_op --> 32;
0382  Array InfixRV_lop --> 32;
0383  Array InfixRV_rop --> 32;
0384  Array InfixRV_types --> 32;
0385  Array InfixRV_commas --> 32;
0386   
0387  [ InfixInBounds addr index n;
0388      if (addr < #array__start || addr > #array__end)
0389          rtrue;
0390      for (n=#lowest_array_number : n<=#highest_array_number : n++) {
0391          if (addr == Symb__Tab(INFIXTT_ARRAY, n)) {
0392              if (temp__global3 == 1 or 3)
0393                  temp__global2=temp__global2*WORDSIZE+WORDSIZE-1;
0394              if (index > temp__global2) {
0395                  print "Array index out of range";
0396                  rfalse;
0397              }
0398          }
0399      }
0400      rtrue;
0401  ];
0402   
0403  [ InfixRvalue acc w i n flag base expecting_term max maxi lop rop lvalside
0404                a b sysfun_f;
0405   
0406      if (InfixCheckLineSpaced()) return GPR_REPARSE;
0407   
0408  !   w = wn; for (i=0 : i<10 : i++) { wn = w; InfixRvalueTerm(); print i, "^"; }
0409  !   wn = w;
0410   
0411      expecting_term = true; base = 0;
0412      do {
0413          w = NextWordStopped();
0414          if (expecting_term) {
0415              switch (w) {
0416                '-//':
0417                  InfixRV_rvals-->n = 'unary-'; InfixRV_types-->n = base + 8;
0418                '[//':
0419                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
0420                '[[':
0421                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
0422                '++':
0423                  InfixRV_rvals-->n = 'pre++'; InfixRV_types-->n = base + 9;
0424                '--':
0425                  InfixRV_rvals-->n = 'pre--'; InfixRV_types-->n = base + 9;
0426                '(//':
0427                  InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base+100;
0428                ')//':
0429                  InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base-100;
0430                  if (base < 0) { wn--; flag = true; }
0431                -1:
0432                  flag = true;
0433                default:
0434                  wn--;
0435                  if (InfixRValueTerm() == 1) {
0436                      InfixRV_rvals-->n = parsed_number;
0437                      InfixRV_lvals-->n = infix_parsed_lvalue;
0438                      InfixRV_types-->n = -1;
0439                      expecting_term = false;
0440                  }
0441                  else flag = true;
0442              }
0443          }
0444          else {
0445              expecting_term = true;
0446              switch (w) {
0447                comma_word:
0448                  InfixRV_rvals-->n = w; InfixRV_types-->n = base;
0449                '=//':
0450                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 1;
0451                '&&', '||':
0452                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
0453                '==', '[=', '>//', '>=', '', '<=', 'has', 'hasnt',
0454                'in', 'notin', 'ofclass', 'provides':
0455                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 3;
0456                'or':
0457                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 4;
0458                '+//', '-//':
0459                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 5;
0460                '*//', '@{2f}//', '%//', '&//', '|//':
0461                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
0462                '->', '-->':
0463                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 7;
0464                ']&', ']#':
0465                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 10;
0466                THEN1__WD:
0467                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 12;
0468                '::':
0469                  InfixRV_rvals-->n = w; InfixRV_types-->n = base + 13;
0470                '(//':
0471                  InfixRV_rvals-->n = '(rcall';
0472                  InfixRV_types-->n = base + 11; base = base + 100;
0473                ')//':
0474                  InfixRV_rvals-->n = w; InfixRV_types-->n = -3;
0475                  base = base - 100;
0476                  if (base < 0) { wn--; flag = true; }
0477                  expecting_term = false;
0478                '++':
0479                  InfixRV_rvals-->n = 'post++'; InfixRV_types-->n = base + 9;
0480                  expecting_term = false;
0481                '--':
0482                  InfixRV_rvals-->n = 'post--'; InfixRV_types-->n = base + 9;
0483                  expecting_term = false;
0484                default:
0485                  flag = true;
0486              }
0487          }
0488          n++;
0489      } until (flag || n == 32);
0490      if (base > 0) return -1;
0491      n--; if (n == 0) return -1;
0492      wn--;
0493   
0494      for (i=0 : i
0495          acc = 0; if (InfixRV_types-->i ~= -3) acc = InfixRV_rvals-->i;
0496          InfixRV_op-->i = acc;
0497      }
0498   
0499      for (::) {
0500   
0501  !       for (i=0 : i
0502  !           if (InfixRV_types-->i == -1) print InfixRV_rvals-->i, " ";
0503  !           else if (InfixRV_types-->i == -3) print " # ";
0504  !           else if (InfixRV_types-->i == -2) print " ## ";
0505  !           else print (address) InfixRV_rvals-->i, "_", InfixRV_types-->i, " ";
0506  !       }
0507  !       new_line;
0508   
0509          max = -2;
0510          for (i=0 : ii > max) {
0511                              max = InfixRV_types-->i; maxi = i; }
0512          if (max == -1) { parsed_number = InfixRV_rvals-->maxi; return 1; }
0513   
0514          lop = maxi-1; rop = maxi+1;
0515          while (lop >= 0 && InfixRV_types-->lop < -1) lop--;
0516          while (rop < n && InfixRV_types-->rop < -1) rop++;
0517          if (lop >= 0) InfixRV_lop-->maxi = InfixRV_rvals-->lop;
0518          if (rop < n) InfixRV_rop-->maxi = InfixRV_rvals-->rop;
0519          flag = false;
0520          infix_term_type = INFIXTT_NUMBER;
0521          switch (InfixRV_rvals-->maxi) {
0522            comma_word:
0523              acc = (InfixRV_rvals-->rop);
0524            '=//', 'pre++', 'post++', 'pre--', 'post--':
0525              lvalside = lop;
0526              switch (InfixRV_rvals-->maxi) {
0527                '=//':        acc = (InfixRV_rvals-->rop);
0528                'pre++':      acc = (InfixRV_rvals-->rop) + 1; lvalside = rop;
0529                'pre--':      acc = (InfixRV_rvals-->rop) - 1; lvalside = rop;
0530                'post++':     acc = (InfixRV_rvals-->lop) + 1;
0531                'post--':     acc = (InfixRV_rvals-->lop) - 1;
0532              }
0533              switch (InfixRV_op-->lvalside) {
0534                THEN1__WD:
0535                  (InfixRV_lop-->lvalside).(InfixRV_rop-->lvalside) = acc;
0536                '->':
0537                  if (InfixInBounds(InfixRV_lop-->lvalside, InfixRV_rop-->lvalside))
0538                      (InfixRV_lop-->lvalside)->(InfixRV_rop-->lvalside) = acc;
0539                '-->':
0540                  if (InfixInBounds(InfixRV_lop-->lvalside, WORDSIZE * InfixRV_rop-->lvalside))
0541                      (InfixRV_lop-->lvalside)-->(InfixRV_rop-->lvalside) = acc;
0542                default:
0543                  w = InfixRV_lvals-->lvalside; if (w == -1) return -1;
0544                  @storew #globals_array w acc;
0545              }
0546              switch(InfixRV_rvals-->maxi) {
0547                'post++': acc--;
0548                'post--': acc++;
0549              }
0550            '(rcall':
0551              sysfun_f = false;
0552              switch (InfixRV_op-->lop) {
0553                THEN1__WD:
0554                  a = InfixRV_lop-->lop; b = InfixRV_rop-->lop;
0555                default:
0556                  a = InfixRV_rvals-->lop; b = call;
0557                  if (InfixRV_lvals-->lop == INFIXTT_SYSFUN)
0558                      sysfun_f = true;
0559              }
0560              w = 0;
0561              i = maxi + 1; base = 100;
0562              if (InfixRV_types-->i == -1 && InfixRV_rvals-->i == ')//') {
0563                  if (sysfun_f) return -1;
0564                  acc = a.b();
0565              }
0566              else {
0567                  while (base > 0) {
0568                      if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == ')//') base = base - 100;
0569                      if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == '(//') base = base + 100;
0570                      if (InfixRV_op-->i == '(rcall') base = base + 100;
0571                      if (base == 100 && InfixRV_op-->i == comma_word) {
0572                          InfixRV_commas-->(w++) = i;
0573  !                       print "Comma found at ", i, "^";
0574                      }
0575                      i++;
0576                  }
0577  !               print "Num args = ", w + 1, "^";
0578  !               for (i=0 : i
0579  !                   print "arg: ", InfixRV_lop-->(InfixRV_commas-->i), "^";
0580  !               print "arg: ", InfixRV_rvals-->rop, "^";
0581                  switch (w+1) {
0582                    1:
0583                      if (sysfun_f) {
0584                          b = InfixRV_rvals-->rop;
0585                          infix_term_type = INFIXTT_NAMEDOBJECT;
0586                          switch(a) {
0587                            'metaclass':
0588                              acc = metaclass(b);
0589                            'parent':
0590                              acc = parent(b);
0591                            'child':
0592                              acc = child(b);
0593                            'children':
0594                              acc = children(b);
0595                              infix_term_type = INFIXTT_NUMBER;
0596                            'random':
0597                              acc = random(b);
0598                              infix_term_type = INFIXTT_NUMBER;
0599                            'sibling':
0600                              acc = sibling(b);
0601                          }
0602                      }
0603                      else
0604                          acc = a.b(InfixRV_rvals-->rop);
0605                    2:
0606                      if (sysfun_f) return -1;
0607                      acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
0608                                InfixRV_rvals-->rop);
0609                    3:
0610                      if (sysfun_f) return -1;
0611                      acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
0612                                InfixRV_lop-->(InfixRV_commas-->1),
0613                                InfixRV_rvals-->rop);
0614                    4:
0615                      if (sysfun_f) return -1;
0616                      acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
0617                                InfixRV_lop-->(InfixRV_commas-->1),
0618                                InfixRV_lop-->(InfixRV_commas-->2),
0619                                InfixRV_rvals-->rop);
0620                    5:
0621                      if (sysfun_f) return -1;
0622                      acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
0623                                InfixRV_lop-->(InfixRV_commas-->1),
0624                                InfixRV_lop-->(InfixRV_commas-->2),
0625                                InfixRV_lop-->(InfixRV_commas-->3),
0626                                InfixRV_rvals-->rop);
0627                    default:
0628                      return -1;
0629                  }
0630              }
0631            '+//':        acc = (InfixRV_rvals-->lop) + (InfixRV_rvals-->rop);
0632            '-//':        acc = (InfixRV_rvals-->lop) - (InfixRV_rvals-->rop);
0633            '*//':        acc = (InfixRV_rvals-->lop) * (InfixRV_rvals-->rop);
0634            '@{2f}//':    acc = (InfixRV_rvals-->lop) / (InfixRV_rvals-->rop);
0635            '%//':        acc = (InfixRV_rvals-->lop) % (InfixRV_rvals-->rop);
0636            THEN1__WD:    acc = (InfixRV_rvals-->lop) . (InfixRV_rvals-->rop);
0637            '->':         acc = (InfixRV_rvals-->lop) -> (InfixRV_rvals-->rop);
0638            '-->':        acc = (InfixRV_rvals-->lop) --> (InfixRV_rvals-->rop);
0639            ']&':         acc = (InfixRV_rvals-->lop) .& (InfixRV_rvals-->rop);
0640            ']#':         acc = (InfixRV_rvals-->lop) .# (InfixRV_rvals-->rop);
0641            '::':         acc = (InfixRV_rvals-->lop) :: (InfixRV_rvals-->rop);
0642            '&//':        acc = (InfixRV_rvals-->lop) & (InfixRV_rvals-->rop);
0643            '|//':        acc = (InfixRV_rvals-->lop) | (InfixRV_rvals-->rop);
0644            '&&':         acc = (InfixRV_rvals-->lop) && (InfixRV_rvals-->rop);
0645                          infix_term_type = INFIXTT_LOGICAL;
0646            '||':         acc = (InfixRV_rvals-->lop) || (InfixRV_rvals-->rop);
0647                          infix_term_type = INFIXTT_LOGICAL;
0648            '':        acc = (InfixRV_rvals-->lop) < (InfixRV_rvals-->rop);
0649                          infix_term_type = INFIXTT_LOGICAL;
0650            '<=':         acc = (InfixRV_rvals-->lop) <= (InfixRV_rvals-->rop);
0651                          infix_term_type = INFIXTT_LOGICAL;
0652            '>//':        acc = (InfixRV_rvals-->lop) > (InfixRV_rvals-->rop);
0653                          infix_term_type = INFIXTT_LOGICAL;
0654            '>=':         acc = (InfixRV_rvals-->lop) >= (InfixRV_rvals-->rop);
0655                          infix_term_type = INFIXTT_LOGICAL;
0656            '==':         acc = (InfixRV_rvals-->lop) == (InfixRV_rvals-->rop);
0657                          infix_term_type = INFIXTT_LOGICAL;
0658            '[=':         acc = (InfixRV_rvals-->lop) ~= (InfixRV_rvals-->rop);
0659                          infix_term_type = INFIXTT_LOGICAL;
0660            'has':        acc = (InfixRV_rvals-->lop) has (InfixRV_rvals-->rop);
0661                          infix_term_type = INFIXTT_LOGICAL;
0662            'hasnt':      acc = (InfixRV_rvals-->lop) hasnt (InfixRV_rvals-->rop);
0663                          infix_term_type = INFIXTT_LOGICAL;
0664            'in':         acc = (InfixRV_rvals-->lop) in (InfixRV_rvals-->rop);
0665                          infix_term_type = INFIXTT_LOGICAL;
0666            'notin':      acc = (InfixRV_rvals-->lop) notin (InfixRV_rvals-->rop);
0667                          infix_term_type = INFIXTT_LOGICAL;
0668            'provides':   acc = (InfixRV_rvals-->lop) provides (InfixRV_rvals-->rop);
0669                          infix_term_type = INFIXTT_LOGICAL;
0670            'ofclass':    acc = (InfixRV_rvals-->lop) ofclass (InfixRV_rvals-->rop);
0671                          infix_term_type = INFIXTT_LOGICAL;
0672            '[[':         acc = ~~ (InfixRV_rvals-->rop); flag = true;
0673            '[//':        acc = ~ (InfixRV_rvals-->rop); flag = true;
0674            'unary-':     acc = - (InfixRV_rvals-->rop); flag = true;
0675          } ! end of switch(InfixRV_rvals-->maxi)
0676          InfixRV_rvals-->maxi = acc;
0677          InfixRV_types-->maxi = -1;
0678          if (rop < n) InfixRV_types-->rop = -2;
0679          if (flag == false && lop >= 0) InfixRV_types-->lop = -2;
0680      } ! end of for (::)
0681  ]; ! end of InfixRvalue
0682   
0683  ! ------------------------------------------------------------------------
0684   
0685  [ InfixWelcomeSub;
0686      print "; Welcome to the ~Infix~ debugger (1/990428), which makes the
0687          following verbs available:^^
0688          ~; ~: evaluates this Inform expression: e.g.
0689          ~; location~ will print the value of the variable ~location~,
0690          ~; 3*5+1~ will print 16, ~; children(old cloth bag)~ will tell you
0691          how many items are in it. (You can name objects either by their
0692          names inside the source code, such as ~n_obj~, or by typing the
0693          names by which the game's parser would normally know them, such
0694          as ~north wall~: the effect is the same.)^
0695          Any expression is allowed except that you can't use double-quoted
0696          strings of text: but you can send messages, call routines or
0697          assign values to variables, properties and array entries.
0698          ^   ~; score++~ is one way to get on in the world.
0699          ^   ~; deadflag = true~ is one way to get out of it.
0700          ^   ~; StopDaemon(nasty little dwarf)~ will keep you from being pestered.^
0701          Conditions like ~; score>20~ are also allowed and print
0702          either 1 (if true) or 0 (if false).^^";
0703      print "~;examine ~ or ~;x ~ gives full details
0704          of whatever it is. For instance, ~;x ##Take~ describes the Take
0705          action; ~;x Class~ the class Class; ~;x 'drop'~ the dictionary
0706          word ~drop~ and so on for numbers, routines, arrays and of course
0707          objects.  ~;xo~ examines something as an object, so for instance
0708          ~;x location~ tells you about the variable ~location~, but ~;xo
0709          location~ tells you what object it refers to.^^";
0710      print "~;give~, ~;remove~ and ~;move~ work like the corresponding
0711          Inform statements.^^";
0712      print "~;<~ causes an action: for instance, ~;< Eat cheese~.^^";
0713      print "~;watch~ or ~;w~ can set a watch on various activities:
0714          type just ~;w~ for details.^^";
0715      print "~;inventory~ or ~;i~ describes the contents of this story file.^";
0716  ];
0717   
0718  [ InfixEvalSub; InfixExamineP(true); ];
0719   
0720  [ InfixActionSub;
0721      print "; <", (InfixPrintAction) infix_lvalue;
0722      if (noun) print " (", (the) noun, ")";
0723      if (second) print " (", (the) second, ")";
0724      print ">^";
0725      if (second) <<(infix_lvalue) noun second>>;
0726      if (noun) <<(infix_lvalue) noun>>;
0727      <<(infix_lvalue)>>;
0728  ];
0729   
0730  [ InfixGiveSub f;
0731      print "; give (", (the) noun, ") ";
0732      if (second < 0) { second = ~second; f=true; }
0733      if (second < 0 || second >= 48) "";
0734      if (f) print "@@126";
0735      print (DebugAttribute) second;
0736      if (f) @clear_attr noun second;
0737      else @set_attr noun second;
0738  ];
0739   
0740  [ InfixMoveSub;
0741      print "; move (", (the) noun, ") to (", (the) second, ")";
0742      move noun to second;
0743  ];
0744   
0745  [ InfixRemoveSub;
0746      print "; remove (", (the) noun, ")";
0747      remove noun;
0748  ];
0749   
0750  [ InfixHex x y;
0751      y = (x & $7f00) / $100;
0752      if (x < 0) y = y + $80;
0753      x = x & $ff;
0754      print (Infixhexdigit) y/$10, (Infixhexdigit) y, (Infixhexdigit) x/$10, (Infixhexdigit) x;
0755  ];
0756   
0757  [ Infixhexdigit x; x = x % $10; if (x < 10) print x; else print (char) 'a'+x-10; ];
0758   
0759  [ InfixExamineOSub;
0760      infix_data1 = metaclass(noun);
0761      infix_term_type = INFIXTT_CONSTANT;
0762      InfixExamineP(false);
0763  ];
0764   
0765  [ InfixExamineSSub;
0766      infix_term_type = INFIXTT_STATICSTRING;
0767      InfixExamineP(false);
0768  ];
0769   
0770  [ InfixExamineSub;     InfixExamineP(false); ];
0771   
0772  [ InfixExamineP brief x a b w flag lines;
0773      switch (infix_term_type) {
0774        INFIXTT_NUMBER:
0775          if (brief) "; == ", noun;
0776          print "; The number ", noun, " == $", (InfixHex) noun;
0777          if (noun >= 32 && noun < 127) print " == '", (char) noun, "'";
0778          new_line;
0779        INFIXTT_NAMEDOBJECT:
0780          print "~", (name) noun, "~ (", noun, ")^"; if (brief) return;
0781          <>;
0782        INFIXTT_CONSTANT:
0783          if (brief) "; == ", noun;
0784          switch (infix_data1 & 15) {
0785              nothing:
0786                  print "; Constant ", (InfixPrintConstant) infix_parsed_lvalue,
0787                  " == ", noun, "^";
0788              Object: <>;
0789              Class:
0790                  print "Class ", (name) noun, "^";
0791                  objectloop (a ofclass noun) {
0792                      if (flag) print ", "; else print "Contains: ";
0793                      print (name) a, " (", a, ")"; flag=true;
0794                  }
0795                  if (flag == false) "No object is of this class";
0796          }
0797          new_line;
0798        INFIXTT_ATTRIBUTE:
0799          if (brief) "; == ", noun;
0800          if (noun >= 48 || noun < 0) "; No such attribute";
0801          print "; Attribute ", (InfixPrintAttribute) noun,
0802              " (numbered ", noun, ")^";
0803          objectloop (x has noun) {
0804              if (flag) print ", ";
0805              else print "Each of these ~has ", (InfixPrintAttribute) noun, "~: ";
0806              print (name) x, " (", x, ")"; flag = true;
0807          }
0808          if (flag == false) "No object ~has ", (InfixPrintAttribute) noun, "~";
0809          new_line;
0810        INFIXTT_PROPERTY:
0811          if (brief) "; == ", noun;
0812          print "; Property ", (property) noun, " (numbered ", noun, ")^";
0813          objectloop (x provides noun) {
0814              if (flag) print ", "; else print "Provided by: ";
0815              print (name) x, " (", x, ")"; flag = true;
0816          }
0817          if (flag == false) "Which is not provided by any object";
0818          new_line;
0819        INFIXTT_DWORD:
0820          if (brief) "; == ", noun;
0821          if (noun == 0) "; This word is not in the dictionary";
0822          a = noun->#dict_par1;
0823          print "; Dictionary word '", (address) noun;
0824          if (a & 4) print "//p";
0825          print "' (address ", noun, ")";
0826          if (a) {
0827              print ": ";
0828              if (a & 2)   print "meta ";
0829              if (a & 1)   print "verb   ";
0830              if (a & 8)   print "preposition   ";
0831              if (a & 4)   print "pluralising ";
0832              if (a & 128) print "noun ";
0833          }
0834          new_line;
0835          if (a & 1) <>;
0836        INFIXTT_ROUTINE:
0837          if (brief) "; == ", noun;
0838          print "; Routine ", (InfixPrintRoutine) infix_parsed_lvalue, " (number ",
0839            infix_parsed_lvalue, ", packed address ", noun, ")^";
0840        INFIXTT_GLOBAL:
0841          if (brief) "; == ", noun;
0842          print "; Global ", (InfixPrintGlobal) infix_parsed_lvalue, " == ", noun, "^";
0843        INFIXTT_ARRAY:
0844          if (brief) "; == ", noun;
0845          print "; Array ", (InfixPrintArray) infix_parsed_lvalue, " ";
0846          infix_data1 = infix_data1 % 16;
0847          switch (infix_data1) {
0848            0:    print "->"; a=0;
0849            1:    print "-->"; a=0;
0850            2:    print "string"; a=1;
0851            3:    print "table"; a=1;
0852            4:    print "buffer"; a=WORDSIZE;
0853          }
0854          print " ", infix_data2 + 1 - a, "^; == "; b = infix_data2;
0855          for (w=b : w>=a : w--)
0856              if (infix_data1 == 0 or 2 or 4) { if (noun->w) break; }
0857              else { if (noun-->w) break; }
0858          if (b-w < 5) w=b;
0859          for (: x<=w : x++) {
0860              if (infix_data1 == 0 or 2 or 4) print noun->x, " ";
0861              else print noun-->x, " ";
0862              if (x+1 == a) print ": ";
0863              }
0864          if (w < b) print "(then ", b-w, " zero entries)";
0865          new_line;
0866        INFIXTT_ACTION:
0867          if (brief) "; == ", noun;
0868          if (noun >= #lowest_fake_action_number && noun <= #highest_fake_action_number)
0869             "; Fake action ", (InfixPrintFakeAction) noun,
0870              " (numbered ", noun, ")^Is not generated by any grammar";
0871          print "; Action ", (InfixPrintAction) noun,
0872              " (numbered ", noun, ")^";
0873          w = HDR_DICTIONARY-->0;
0874          for (b=0 : b<(HDR_DICTIONARY-->0 + 5)-->0 : b++) {
0875              w = HDR_DICTIONARY-->0 + 7 + b*9;
0876              if ((w->#dict_par1) & 1) {
0877                  a = (HDR_STATICMEMORY-->0)-->($ff-(w->#dict_par2));
0878                  lines = a->0; a++;
0879                  for (: lines>0 : lines--) {
0880                      a = UnpackGrammarLine(a);
0881                      if (action_to_be == noun) {
0882                          print "'", (address) w, "' "; DebugGrammarLine();
0883                          new_line;
0884                          flag = true;
0885                      }
0886                  }
0887              }
0888          }
0889          if (flag == 0) "Is not generated by any grammar";
0890        INFIXTT_SYSFUN:
0891          if (brief) "; == ", noun;
0892          "; System function ~", (address) infix_parsed_lvalue, "~ has
0893          not been overridden by any routine and so has its standard definition.";
0894        INFIXTT_STATICSTRING:
0895          if (brief) "; == ", noun;
0896          if (metaclass(noun) ~= String) "; ", noun, " is not a string.";
0897          print "~", (string) noun, "~^";
0898        INFIXTT_LOGICAL:
0899          if (noun == true) "; true"; if (noun == false) "; false";
0900          "; ", noun;
0901      }
0902  ]; ! end of InfixExamineP
0903   
0904  [ InfixDescribeWatchSub x y z s flag aflag;
0905      print "; The Infix ~;watch~ verb allows you to set a watch on any named
0906          routine(s) or objects: for instance ~;watch ScoreSub~ or
0907          ~;watch silver bars~. You can also:
0908          ^    ~;watch objects~: changes to attribute or property settings";
0909      if (debug_flag & 8) print " (on)"; else print " (off)";
0910   
0911      print ";^    ~;watch timers~: the running of timers and daemons each turn";
0912      if (debug_flag & 4) print " (on)"; else print " (off)";
0913   
0914      print ";^    ~;watch messages~: all messages sent";
0915      if (debug_flag & 1) print " (on)"; else print " (off)";
0916   
0917      print ";^    ~;watch actions~: all actions generated";
0918      if (debug_flag & 2) print " (on)"; else print " (off)";
0919   
0920      print ".^~~;watch~ can be abbreviated to ~;w~ and use ~off~ to stop
0921          watching: for instance ~;w location off~.^";
0922      aflag = debug_flag;
0923      objectloop (x has infix__watching) flag = true; aflag = aflag || flag;
0924      if (flag) print "The following objects are currently being watched: ";
0925      flag = false;
0926      objectloop (x has infix__watching) {
0927          if (flag) print ", "; flag = true;
0928          print (name) x, " (", x, ")";
0929      }
0930      if (flag) new_line;
0931      s = (#highest_routine_number - #lowest_routine_number);
0932      if (s%8 == 0) s=s/8; else s=s/8+1;
0933      for (flag=false,x=0 : xx) flag = true;
0934      aflag = aflag || flag;
0935      if (flag) print "The following routines are currently being watched: ";
0936      for (x=0,flag=false : x
0937          for (y=1,z=0 : y<256 : z++,y=y*2) {
0938              if ((#routine_flags_array->x) & y) {
0939                  if (flag) print ", "; flag = true;
0940                  print (InfixPrintRoutine)
0941                      #lowest_routine_number + x*8 + z;
0942              }
0943          }
0944      }
0945      if (flag) new_line;
0946      if (aflag == false) "At present, nothing is being watched.";
0947  ];
0948   
0949  [ InfixWatchOnSub i j k l;
0950      if (noun == 0) return InfixDescribeWatchSub();
0951      if (infix_term_type == INFIXTT_ROUTINE) {
0952          i = infix_parsed_lvalue/8;
0953          for (j=0,k=1 : j
0954          l = #routine_flags_array->i;
0955          l = l | k;
0956          @storeb #routine_flags_array i l;
0957         "; Watching routine ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
0958      }
0959      if (metaclass(noun) == Object) {
0960          give noun infix__watching;
0961         "; Watching object ~", (name) noun, "~ (", noun, ").";
0962      }
0963      InfixDescribeWatchSub();
0964    ];
0965   
0966  [ InfixWatchOffSub i j k l;
0967      if (noun == 0) return InfixDescribeWatchSub();
0968      if (infix_term_type == INFIXTT_ROUTINE) {
0969          i = infix_parsed_lvalue/8;
0970          for (j=0,k=1 : j
0971          l = #routine_flags_array->i;
0972          l = l & (~k);
0973          @storeb #routine_flags_array i l;
0974         "; Not watching ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
0975      }
0976      if (metaclass(noun) == Object) {
0977