Import v6.12.2 of the Inform 6 standard library
[informlib.git] / infix.h
1 ! ==============================================================================
2 !   INFIX:  Support for the optional library debugger extension "Infix".
3 !
4 !   Supplied for use with Inform 6 -- Release 6.12.2 -- Serial number 180520
5 !
6 !   Copyright Graham Nelson 1993-2004 and David Griffith 2012-2018
7 !
8 !   This file is free software: you can redistribute it and/or modify
9 !   it under the terms of the GNU Affero General Public License as
10 !   published by the Free Software Foundation, either version 3 of the
11 !   License, or (at your option) any later version.
12 !
13 !   This file is distributed in the hope that it will be useful, but
14 !   WITHOUT ANY WARRANTY; without even the implied warranty of
15 !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 !   Affero General Public License for more details.
17 !
18 !   You should have received a copy of the GNU Affero General Public
19 !   License along with this program. If not, see
20 !   https://gnu.org/licenses/
21 !
22 !   This file is automatically Included in your game file by "grammar" if you
23 !   supply the -X compiler switch.
24 ! ==============================================================================
25
26 System_file;
27
28 ! ------------------------------------------------------------------------------
29
30 #Ifdef DEBUG;
31
32 Constant INFIXTT_NUMBER          0;
33 Constant INFIXTT_ARRAY           1;
34 Constant INFIXTT_ROUTINE         2;
35 Constant INFIXTT_CONSTANT        3;
36 Constant INFIXTT_DWORD           4;
37 Constant INFIXTT_ACTION          5;
38 Constant INFIXTT_ATTRIBUTE       6;
39 Constant INFIXTT_PROPERTY        7;
40 Constant INFIXTT_GLOBAL          8;
41 Constant INFIXTT_NAMEDOBJECT     9;
42 Constant INFIXTT_SYSFUN         10;
43 Constant INFIXTT_STATICSTRING   11;
44 Constant INFIXTT_LOGICAL        12;
45
46 Global infix_term_type;
47 Global infix_data1;
48 Global infix_data2;
49 Global infix_lvalue;
50 Global infix_parsed_lvalue;
51 Array  infix_tolowercase -> 256;
52 #Ifdef VN_1630;
53 Array  infix_text buffer 126;
54 #Ifnot;
55 Array  infix_text -> 128;
56 #Endif; ! VN_
57
58
59 [ InfixPrintAttribute x; print (string) #attribute_names_array-->x; ];
60
61 [ InfixPrintProperty x;  print (property) x; ];
62
63 #Ifdef TARGET_GLULX;
64 [ InfixPrintGIProperty x;  print (property) x; ];
65 #Endif; ! TARGET_
66
67 [ InfixPrintGlobal x;    print (string) #global_names_array-->x; ];
68
69 [ InfixPrintAction x;    print (string) #action_names_array-->(x-#lowest_action_number); ];
70
71 [ InfixPrintRoutine x;   print (string) #routine_names_array-->(x-#lowest_routine_number); ];
72
73 [ InfixPrintConstant x;  print (string) #constant_names_array-->(x-#lowest_constant_number); ];
74
75 [ InfixPrintArray x;     print (string) #array_names_array-->(x-#lowest_array_number); ];
76
77 [ InfixPrintFakeAction x;
78                          print (string) #fake_action_names_array-->(x-#lowest_fake_action_number); ];
79
80 [ InfixPrintPA x n;
81     for (n=#lowest_routine_number : n<=#highest_routine_number : n++) {
82         if (x == Symb__Tab(INFIXTT_ROUTINE, n)) {
83             print (InfixPrintRoutine) n; return;
84         }
85     }
86     print "Routine(", x, ")";
87 ];
88
89 [ InfixMatchPrule PrintingRule range1 range2 wa wl t i i2 it2 itlc j k plus;
90     itlc = infix_tolowercase;
91     if (itlc->255 == 0) {
92         for (j=0 : j<256 : j++) itlc->j = j;
93         itlc->'A' = 'a';    itlc->'B' = 'b';
94         itlc->'C' = 'c';    itlc->'D' = 'd';
95         itlc->'E' = 'e';    itlc->'F' = 'f';
96         itlc->'G' = 'g';    itlc->'H' = 'h';
97         itlc->'I' = 'i';    itlc->'J' = 'j';
98         itlc->'K' = 'k';    itlc->'L' = 'l';
99         itlc->'M' = 'm';    itlc->'N' = 'n';
100         itlc->'O' = 'o';    itlc->'P' = 'p';
101         itlc->'Q' = 'q';    itlc->'R' = 'r';
102         itlc->'S' = 's';    itlc->'T' = 't';
103         itlc->'U' = 'u';    itlc->'V' = 'v';
104         itlc->'W' = 'w';    itlc->'X' = 'x';
105         itlc->'Y' = 'y';    itlc->'Z' = 'z';
106     }
107     switch (PrintingRule) {
108       InfixPrintAttribute:
109         if (wa->0 == '~') { wl--; wa++; plus = 100; } ! A tilde
110         t = #attribute_names_array;
111       InfixPrintProperty:   t = #property_names_array;
112       #Ifdef TARGET_GLULX;
113       InfixPrintGIProperty: t = #identifiers_table-->2;
114       #Endif; ! TARGET_
115       InfixPrintAction:     t = #action_names_array;
116       InfixPrintFakeAction: t = #fake_action_names_array;
117       InfixPrintGlobal:     t = #global_names_array;
118       InfixPrintRoutine:    t = #routine_names_array;
119       InfixPrintAction:     t = #constant_names_array;
120       InfixPrintArray:      t = #array_names_array;
121     }
122
123     i2 = range2-range1; it2 = infix_text+WORDSIZE;
124     for (i=0 : i<=i2 : i++) {
125         #ifdef TARGET_ZCODE;
126         infix_text-->0 = 62; @output_stream 3 infix_text;
127         if (t) print (string) t-->i; else PrintingRule(i+range1);
128         @output_stream -3;
129         #ifnot; ! TARGET_GLULX
130         if (t) PrintToBuffer(infix_text, 62, t-->i);
131         else PrintToBuffer(infix_text, 62, PrintingRule, i+range1);
132         #endif; ! TARGET_
133         k = infix_text-->0;
134         if (k ~= wl) jump XL;
135         if (itlc->(it2->0) ~= itlc->(wa->0)) jump XL;
136         for (j=1 : j<k : j++)
137             if (itlc->(it2->j) ~= itlc->(wa->j)) jump XL;
138         parsed_number = i + range1 + plus;
139         rtrue;
140       .XL;
141     }
142     rfalse;
143 ];
144
145 [ InfixActionToken;
146     if (InfixMatchPrule(InfixPrintAction, #lowest_action_number,
147         #highest_action_number, WordAddress(wn), WordLength(wn))) {
148         wn++; infix_lvalue = parsed_number; return 0;
149     }
150     if (InfixMatchPrule(InfixPrintFakeAction, #lowest_fake_action_number,
151         #highest_fake_action_number, WordAddress(wn), WordLength(wn))) {
152         wn++; infix_lvalue = parsed_number; return 0;
153     }
154     return -1;
155 ];
156
157 [ InfixRvalueTerm n w i initial_wn wa wl sign base digit dcount;
158
159     initial_wn = wn;
160
161     infix_parsed_lvalue = -1;
162     infix_term_type = INFIXTT_NUMBER;
163
164     w = NextWordStopped();
165     if (w == -1) return -1;
166
167     wa = WordAddress(wn-1);
168     wl = WordLength(wn-1);
169     if (wa->0 == '-' or '$' or '0' or '1' or '2' or '3'
170               or '4' or '5' or '6' or '7' or '8' or '9') {
171         ! Parse decimal, hex or binary number
172
173         sign = 1; base = 10; dcount = 0;
174         if (wa->0 == '-') { sign = -1; wl--; wa++; }
175         else {
176             if (wa->0 == '$') { base = 16; wl--; wa++; }
177             if (wa->0 == '$') { base = 2; wl--; wa++; }
178         }
179         if (wl == 0) return -1;
180         n = 0;
181         while (wl > 0) {
182             if (wa->0 >= 'a') digit = wa->0 - 'a' + 10;
183             else digit = wa->0 - '0';
184             dcount++;
185             #Ifdef TARGET_ZCODE;
186             switch (base) {
187               2:
188                 if (dcount == 17) return -1;
189               10:
190                 if (dcount == 6) return -1;
191                 if (dcount == 5) {
192                     if (n > 3276) return -1;
193                     if (n == 3276) {
194                         if (sign == 1 && digit > 7) return -1;
195                         if (sign == -1 && digit > 8) return -1;
196                     }
197                 }
198               16:
199                 if (dcount == 5) return -1;
200             }
201             #Ifnot; ! TARGET_GLULX
202             switch (base) {
203               2:
204                 if (dcount == 33) return -1;
205               10:
206                 if (dcount == 11) return -1;
207                 if (dcount == 10) {
208                     if (n > 214748363) return -1;
209                 }
210               16:
211                 if (dcount == 9) return -1;
212             }
213             #Endif; ! TARGET_
214             if (digit >= 0 && digit < base) n = base*n + digit;
215             else return -1;
216             wl--; wa++;
217         }
218         parsed_number = n*sign; return 1;
219     }
220
221     ! Parse character constant 'a'
222
223     if (wl == 3 && wa->0 == ''' && wa->2 == ''') {
224         parsed_number = wa->1; return 1;
225     }
226
227     ! ##Action, 'dword'
228
229     switch (w) {
230       '##':
231         infix_term_type = INFIXTT_ACTION;
232         w = NextWordStopped(); if (w == -1) return -1;
233         wn--;
234         if (InfixActionToken() == 0) return 1;
235         return -1;
236       '^^':
237         infix_term_type = INFIXTT_DWORD;
238         w = NextWordStopped(); if (w == -1) return -1;
239         parsed_number = w; return 1;
240     }
241
242     ! Test for attribute, property, class name, variable name, array name, routine
243     ! name, constant name
244
245     wn--;
246     if ((wa->0 >= 'a' && wa->0 <= 'z') ||
247         (wa->0 >= 'A' && wa->0 <= 'Z') ||
248          wa->0 == '_') {
249
250
251         infix_term_type = INFIXTT_ATTRIBUTE;
252         if (InfixMatchPrule(InfixPrintAttribute, #lowest_attribute_number,
253             #highest_attribute_number, wa, wl)) {
254             wn++; return 1; }
255
256         infix_term_type = INFIXTT_PROPERTY;
257         #Ifdef TARGET_ZCODE;
258         if (InfixMatchPrule(InfixPrintProperty, #lowest_property_number,
259             #highest_property_number, wa, wl)) {
260             wn++; return 1;
261         }
262         #Ifnot; ! TARGET_
263         if (InfixMatchPrule(InfixPrintProperty, #lowest_property_number,
264             #identifiers_table-->1 - 1, wa, wl)) {
265             wn++; return 1;
266         }
267         if (InfixMatchPrule(InfixPrintGIProperty, INDIV_PROP_START,
268             #highest_property_number, wa, wl)) {
269             wn++; return 1;
270         }
271         #Endif; ! TARGET_
272
273
274         infix_term_type = INFIXTT_GLOBAL;
275         if (InfixMatchPrule(InfixPrintGlobal, #lowest_global_number,
276             #highest_global_number, wa, wl)) {
277             infix_parsed_lvalue = parsed_number-16;
278             parsed_number = #globals_array-->infix_parsed_lvalue;
279             wn++; return 1;
280         }
281
282         infix_term_type = INFIXTT_ARRAY;
283         if (InfixMatchPrule(InfixPrintArray, #lowest_array_number,
284             #highest_array_number, wa, wl)) {
285             infix_parsed_lvalue = parsed_number;
286             parsed_number = Symb__Tab(INFIXTT_ARRAY,parsed_number);
287             infix_data1 = temp__global3;
288             infix_data2 = temp__global2;
289             wn++; return 1;
290         }
291
292         infix_term_type = INFIXTT_ROUTINE;
293         if (InfixMatchPrule(InfixPrintRoutine, #lowest_routine_number,
294             #highest_routine_number, wa, wl)) {
295             infix_parsed_lvalue = parsed_number;
296             parsed_number = Symb__Tab(INFIXTT_ROUTINE,parsed_number);
297             infix_data1 = temp__global3;
298             infix_data2 = temp__global2;
299             wn++; return 1;
300         }
301
302         infix_term_type = INFIXTT_CONSTANT;
303         if (InfixMatchPrule(InfixPrintConstant, #lowest_constant_number,
304             #highest_constant_number, wa, wl)) {
305             infix_parsed_lvalue = parsed_number;
306             parsed_number = Symb__Tab(INFIXTT_CONSTANT,parsed_number);
307             infix_data1 = temp__global3;
308             infix_data2 = temp__global2;
309             wn++; return 1;
310         }
311
312         switch (w) {
313           'parent', 'child', 'children',
314           'random', 'metaclass', 'sibling':
315             parsed_number = w;
316             infix_parsed_lvalue = INFIXTT_SYSFUN;
317             wn++; return 1;
318         }
319     }
320
321     infix_term_type = INFIXTT_NAMEDOBJECT;
322
323     wn = initial_wn; i = ParseToken(SCOPE_TT, InfixBigScope);
324
325     if (i == GPR_REPARSE) return i;
326     if (i > GPR_MULTIPLE) {
327         print "(", (name) i, " (", i, "))^";
328         parsed_number = i; return 1;
329     }
330     return -1;
331 ]; ! end of InfixRvalueTerm
332
333 [ InfixBigScope x;
334     if (scope_stage == 1) return false;  ! No multiples here
335     if (scope_stage == 2) {
336         objectloop (x ofclass Object) PlaceInScope(x);
337         return true; ! That's the whole scope
338     }
339     print "; I'm unable to make any sense of that term.^";
340 ];
341
342 [ InfixCheckLineSpaced wa wl i force altered;
343     for (i=1 : i<=NumberWords() : i++) {
344         wa = WordAddress(i);
345         wl = WordLength(i);
346         if (wl > 3 && wa->0 == ''' && wa->(wl-1) == ''') {
347             wa->(wl-1) = ' ';
348             if (wa->(wl-2) == '/' && wa->(wl-3) == '/') {
349                 wa->(wl-2) = ' ';
350                 wa->(wl-3) = ' ';
351             }
352             LTI_Insert(wa-buffer, ''');
353             LTI_Insert(wa-buffer + 2, ' ');
354             altered = true; break;
355         }
356     }
357     for (i=WORDSIZE : i<GetKeyBufLength() + WORDSIZE : i++) {
358         #Ifdef TARGET_GLULX;
359         buffer->i = LowerCase(buffer->i);
360         #Endif; ! TARGET_
361         force = false;
362         if (buffer->i == '-' && buffer->(i+1) == '-' && buffer->(i+2) == '>')
363             force = true;
364         if (force) {
365             if (i>WORDSIZE && buffer->(i-1) ~= ' ') {
366                 LTI_Insert(i++, ' '); altered = true;
367             }
368             if (buffer->(i+3) ~= ' ') {
369                 LTI_Insert(i+3, ' '); i++; altered = true;
370             }
371             i = i + 2; continue;
372         }
373
374         if (buffer->i == ':' && buffer->(i+1) == ':') force = true;
375         if (buffer->i == '-' && buffer->(i+1) == '>') force = true;
376         if (buffer->i == '.' && buffer->(i+1) == '&') {
377             buffer->i = ']'; force = true;
378         }
379         if (buffer->i == '.' && buffer->(i+1) == '#') {
380             buffer->i = ']'; force = true;
381         }
382         if (buffer->i == ']' && buffer->(i+1) == '&') force = true;
383         if (buffer->i == ']' && buffer->(i+1) == '#') force = true;
384         if (buffer->i == '+' && buffer->(i+1) == '+') force = true;
385         if (buffer->i == '-' && buffer->(i+1) == '-') force = true;
386         if (buffer->i == '&' && buffer->(i+1) == '&') force = true;
387         if (buffer->i == '|' && buffer->(i+1) == '|') force = true;
388         if (buffer->i == '~' && buffer->(i+1) == '~') force = true;
389
390         if (buffer->i == '=' && buffer->(i+1) == '=') force = true;
391         if (buffer->i == '~' && buffer->(i+1) == '=') force = true;
392         if (buffer->i == '>' && buffer->(i+1) == '=') force = true;
393         if (buffer->i == '<' && buffer->(i+1) == '=') force = true;
394         if (buffer->i == '#' && buffer->(i+1) == '#') force = true;
395
396         if (force) {
397             if (i > WORDSIZE && buffer->(i-1) ~= ' ') {
398                 LTI_Insert(i++, ' '); altered = true;
399             }
400             if (buffer->(i+2) ~= ' ') {
401                 LTI_Insert(i+2, ' '); i++; altered = true;
402             }
403             i = i + 1; continue;
404         }
405
406         if (buffer->i == '+') force = true;
407         if (buffer->i == '-') force = true;
408         if (buffer->i == '*') force = true;
409         if (buffer->i == '/') force = true;
410         if (buffer->i == '%') force = true;
411         if (buffer->i == '(') force = true;
412         if (buffer->i == ')') force = true;
413         if (buffer->i == '<' && buffer->(i-1) ~= ';') force = true;
414         if (buffer->i == '>') force = true;
415         if (buffer->i == ',') force = true;
416         if (buffer->i == '.') force = true;
417         if (buffer->i == '&') force = true;
418         if (buffer->i == '|') force = true;
419         if (buffer->i == '~') force = true;
420         if (buffer->i == '=') force = true;
421         if (force) {
422             if (i > WORDSIZE && buffer->(i-1) ~= ' ') {
423                 LTI_Insert(i++, ' '); altered = true;
424             }
425             if (buffer->(i+1) ~= ' ') {
426                 LTI_Insert(i+1, ' '); i++; altered = true;
427             }
428         }
429     }
430     for (i=WORDSIZE : i<GetKeyBufLength() + WORDSIZE : i++)
431         if (buffer->i == '~') { buffer->i = '['; altered = true; }
432     return altered;
433 ]; ! end of InfixCheckLineSpaced
434
435 Array InfixRV_rvals --> 32;
436 Array InfixRV_lvals --> 32;
437 Array InfixRV_op --> 32;
438 Array InfixRV_lop --> 32;
439 Array InfixRV_rop --> 32;
440 Array InfixRV_types --> 32;
441 Array InfixRV_commas --> 32;
442
443 [ InfixInBounds addr index n;
444     if (addr < #array__start || addr > #array__end)
445         rtrue;
446     for (n=#lowest_array_number : n<=#highest_array_number : n++) {
447         if (addr == Symb__Tab(INFIXTT_ARRAY, n)) {
448             if (temp__global3 == 1 or 3)
449                 temp__global2=temp__global2*WORDSIZE+WORDSIZE-1;
450             if (index > temp__global2) {
451                 print "Array index out of range";
452                 rfalse;
453             }
454         }
455     }
456     rtrue;
457 ];
458
459 [ InfixRvalue acc w i n flag base expecting_term max maxi lop rop lvalside
460               a b sysfun_f;
461
462     if (InfixCheckLineSpaced()) return GPR_REPARSE;
463
464 !   w = wn; for (i=0 : i<10 : i++) { wn = w; InfixRvalueTerm(); print i, "^"; }
465 !   wn = w;
466
467     expecting_term = true; base = 0;
468     do {
469         w = NextWordStopped();
470         if (expecting_term) {
471             switch (w) {
472               '-//':
473                 InfixRV_rvals-->n = 'unary-'; InfixRV_types-->n = base + 8;
474               '[//':
475                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
476               '[[':
477                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
478               '++':
479                 InfixRV_rvals-->n = 'pre++'; InfixRV_types-->n = base + 9;
480               '--':
481                 InfixRV_rvals-->n = 'pre--'; InfixRV_types-->n = base + 9;
482               '(//':
483                 InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base+100;
484               ')//':
485                 InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base-100;
486                 if (base < 0) { wn--; flag = true; }
487               -1:
488                 flag = true;
489               default:
490                 wn--;
491                 if (InfixRValueTerm() == 1) {
492                     InfixRV_rvals-->n = parsed_number;
493                     InfixRV_lvals-->n = infix_parsed_lvalue;
494                     InfixRV_types-->n = -1;
495                     expecting_term = false;
496                 }
497                 else flag = true;
498             }
499         }
500         else {
501             expecting_term = true;
502             switch (w) {
503               comma_word:
504                 InfixRV_rvals-->n = w; InfixRV_types-->n = base;
505               '=//':
506                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 1;
507               '&&', '||':
508                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
509               '==', '[=', '>//', '>=', '<//', '<=', 'has', 'hasnt',
510               'in', 'notin', 'ofclass', 'provides':
511                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 3;
512               'or':
513                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 4;
514               '+//', '-//':
515                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 5;
516               '*//', '@{2f}//', '%//', '&//', '|//':
517                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
518               '->', '-->':
519                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 7;
520               ']&', ']#':
521                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 10;
522               THEN1__WD:
523                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 12;
524               '::':
525                 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 13;
526               '(//':
527                 InfixRV_rvals-->n = '(rcall';
528                 InfixRV_types-->n = base + 11; base = base + 100;
529               ')//':
530                 InfixRV_rvals-->n = w; InfixRV_types-->n = -3;
531                 base = base - 100;
532                 if (base < 0) { wn--; flag = true; }
533                 expecting_term = false;
534               '++':
535                 InfixRV_rvals-->n = 'post++'; InfixRV_types-->n = base + 9;
536                 expecting_term = false;
537               '--':
538                 InfixRV_rvals-->n = 'post--'; InfixRV_types-->n = base + 9;
539                 expecting_term = false;
540               default:
541                 flag = true;
542             }
543         }
544         n++;
545     } until (flag || n == 32);
546     if (base > 0) return -1;
547     n--; if (n == 0) return -1;
548     wn--;
549
550     for (i=0 : i<n : i++) {
551         acc = 0; if (InfixRV_types-->i ~= -3) acc = InfixRV_rvals-->i;
552         InfixRV_op-->i = acc;
553     }
554
555     for (::) {
556
557 !       for (i=0 : i<n : i++) {
558 !           if (InfixRV_types-->i == -1) print InfixRV_rvals-->i, " ";
559 !           else if (InfixRV_types-->i == -3) print " # ";
560 !           else if (InfixRV_types-->i == -2) print " ## ";
561 !           else print (address) InfixRV_rvals-->i, "_", InfixRV_types-->i, " ";
562 !       }
563 !       new_line;
564
565         max = -2;
566         for (i=0 : i<n : i++) if (InfixRV_types-->i > max) {
567                             max = InfixRV_types-->i; maxi = i; }
568         if (max == -1) { parsed_number = InfixRV_rvals-->maxi; return 1; }
569
570         lop = maxi-1; rop = maxi+1;
571         while (lop >= 0 && InfixRV_types-->lop < -1) lop--;
572         while (rop < n && InfixRV_types-->rop < -1) rop++;
573         if (lop >= 0) InfixRV_lop-->maxi = InfixRV_rvals-->lop;
574         if (rop < n) InfixRV_rop-->maxi = InfixRV_rvals-->rop;
575         flag = false;
576         infix_term_type = INFIXTT_NUMBER;
577         switch (InfixRV_rvals-->maxi) {
578           comma_word:
579             acc = (InfixRV_rvals-->rop);
580           '=//', 'pre++', 'post++', 'pre--', 'post--':
581             lvalside = lop;
582             switch (InfixRV_rvals-->maxi) {
583               '=//':        acc = (InfixRV_rvals-->rop);
584               'pre++':      acc = (InfixRV_rvals-->rop) + 1; lvalside = rop;
585               'pre--':      acc = (InfixRV_rvals-->rop) - 1; lvalside = rop;
586               'post++':     acc = (InfixRV_rvals-->lop) + 1;
587               'post--':     acc = (InfixRV_rvals-->lop) - 1;
588             }
589             switch (InfixRV_op-->lvalside) {
590               THEN1__WD:
591                 (InfixRV_lop-->lvalside).(InfixRV_rop-->lvalside) = acc;
592               '->':
593                 if (InfixInBounds(InfixRV_lop-->lvalside, InfixRV_rop-->lvalside))
594                     (InfixRV_lop-->lvalside)->(InfixRV_rop-->lvalside) = acc;
595               '-->':
596                 if (InfixInBounds(InfixRV_lop-->lvalside, WORDSIZE * InfixRV_rop-->lvalside))
597                     (InfixRV_lop-->lvalside)-->(InfixRV_rop-->lvalside) = acc;
598               default:
599                 w = InfixRV_lvals-->lvalside; if (w == -1) return -1;
600                 #ifdef TARGET_ZCODE;
601                 @storew #globals_array w acc;
602                 #ifnot;
603                 @astore #globals_array w acc;
604                 #endif;
605             }
606             switch(InfixRV_rvals-->maxi) {
607               'post++': acc--;
608               'post--': acc++;
609             }
610           '(rcall':
611             sysfun_f = false;
612             switch (InfixRV_op-->lop) {
613               THEN1__WD:
614                 a = InfixRV_lop-->lop; b = InfixRV_rop-->lop;
615               default:
616                 a = InfixRV_rvals-->lop; b = call;
617                 if (InfixRV_lvals-->lop == INFIXTT_SYSFUN)
618                     sysfun_f = true;
619             }
620             w = 0;
621             i = maxi + 1; base = 100;
622             if (InfixRV_types-->i == -1 && InfixRV_rvals-->i == ')//') {
623                 if (sysfun_f) return -1;
624                 acc = a.b();
625             }
626             else {
627                 while (base > 0) {
628                     if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == ')//') base = base - 100;
629                     if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == '(//') base = base + 100;
630                     if (InfixRV_op-->i == '(rcall') base = base + 100;
631                     if (base == 100 && InfixRV_op-->i == comma_word) {
632                         InfixRV_commas-->(w++) = i;
633 !                       print "Comma found at ", i, "^";
634                     }
635                     i++;
636                 }
637 !               print "Num args = ", w + 1, "^";
638 !               for (i=0 : i<w : i++)
639 !                   print "arg: ", InfixRV_lop-->(InfixRV_commas-->i), "^";
640 !               print "arg: ", InfixRV_rvals-->rop, "^";
641                 switch (w+1) {
642                   1:
643                     if (sysfun_f) {
644                         b = InfixRV_rvals-->rop;
645                         infix_term_type = INFIXTT_NAMEDOBJECT;
646                         switch(a) {
647                           'metaclass':
648                             acc = metaclass(b);
649                           'parent':
650                             acc = parent(b);
651                           'child':
652                             acc = child(b);
653                           'children':
654                             acc = children(b);
655                             infix_term_type = INFIXTT_NUMBER;
656                           'random':
657                             acc = random(b);
658                             infix_term_type = INFIXTT_NUMBER;
659                           'sibling':
660                             acc = sibling(b);
661                         }
662                     }
663                     else
664                         acc = a.b(InfixRV_rvals-->rop);
665                   2:
666                     if (sysfun_f) return -1;
667                     acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
668                               InfixRV_rvals-->rop);
669                   3:
670                     if (sysfun_f) return -1;
671                     acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
672                               InfixRV_lop-->(InfixRV_commas-->1),
673                               InfixRV_rvals-->rop);
674                   4:
675                     if (sysfun_f) return -1;
676                     acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
677                               InfixRV_lop-->(InfixRV_commas-->1),
678                               InfixRV_lop-->(InfixRV_commas-->2),
679                               InfixRV_rvals-->rop);
680                   5:
681                     if (sysfun_f) return -1;
682                     acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
683                               InfixRV_lop-->(InfixRV_commas-->1),
684                               InfixRV_lop-->(InfixRV_commas-->2),
685                               InfixRV_lop-->(InfixRV_commas-->3),
686                               InfixRV_rvals-->rop);
687                   default:
688                     return -1;
689                 }
690             }
691           '+//':        acc = (InfixRV_rvals-->lop) + (InfixRV_rvals-->rop);
692           '-//':        acc = (InfixRV_rvals-->lop) - (InfixRV_rvals-->rop);
693           '*//':        acc = (InfixRV_rvals-->lop) * (InfixRV_rvals-->rop);
694           '@{2f}//':    acc = (InfixRV_rvals-->lop) / (InfixRV_rvals-->rop);
695           '%//':        acc = (InfixRV_rvals-->lop) % (InfixRV_rvals-->rop);
696           THEN1__WD:    acc = (InfixRV_rvals-->lop) . (InfixRV_rvals-->rop);
697           '->':         acc = (InfixRV_rvals-->lop) -> (InfixRV_rvals-->rop);
698           '-->':        acc = (InfixRV_rvals-->lop) --> (InfixRV_rvals-->rop);
699           ']&':         acc = (InfixRV_rvals-->lop) .& (InfixRV_rvals-->rop);
700           ']#':         acc = (InfixRV_rvals-->lop) .# (InfixRV_rvals-->rop);
701           '::':         acc = (InfixRV_rvals-->lop) :: (InfixRV_rvals-->rop);
702           '&//':        acc = (InfixRV_rvals-->lop) & (InfixRV_rvals-->rop);
703           '|//':        acc = (InfixRV_rvals-->lop) | (InfixRV_rvals-->rop);
704           '&&':         acc = (InfixRV_rvals-->lop) && (InfixRV_rvals-->rop);
705                         infix_term_type = INFIXTT_LOGICAL;
706           '||':         acc = (InfixRV_rvals-->lop) || (InfixRV_rvals-->rop);
707                         infix_term_type = INFIXTT_LOGICAL;
708           '<//':        acc = (InfixRV_rvals-->lop) < (InfixRV_rvals-->rop);
709                         infix_term_type = INFIXTT_LOGICAL;
710           '<=':         acc = (InfixRV_rvals-->lop) <= (InfixRV_rvals-->rop);
711                         infix_term_type = INFIXTT_LOGICAL;
712           '>//':        acc = (InfixRV_rvals-->lop) > (InfixRV_rvals-->rop);
713                         infix_term_type = INFIXTT_LOGICAL;
714           '>=':         acc = (InfixRV_rvals-->lop) >= (InfixRV_rvals-->rop);
715                         infix_term_type = INFIXTT_LOGICAL;
716           '==':         acc = (InfixRV_rvals-->lop) == (InfixRV_rvals-->rop);
717                         infix_term_type = INFIXTT_LOGICAL;
718           '[=':         acc = (InfixRV_rvals-->lop) ~= (InfixRV_rvals-->rop);
719                         infix_term_type = INFIXTT_LOGICAL;
720           'has':        acc = (InfixRV_rvals-->lop) has (InfixRV_rvals-->rop);
721                         infix_term_type = INFIXTT_LOGICAL;
722           'hasnt':      acc = (InfixRV_rvals-->lop) hasnt (InfixRV_rvals-->rop);
723                         infix_term_type = INFIXTT_LOGICAL;
724           'in':         acc = (InfixRV_rvals-->lop) in (InfixRV_rvals-->rop);
725                         infix_term_type = INFIXTT_LOGICAL;
726           'notin':      acc = (InfixRV_rvals-->lop) notin (InfixRV_rvals-->rop);
727                         infix_term_type = INFIXTT_LOGICAL;
728           'provides':   acc = (InfixRV_rvals-->lop) provides (InfixRV_rvals-->rop);
729                         infix_term_type = INFIXTT_LOGICAL;
730           'ofclass':    acc = (InfixRV_rvals-->lop) ofclass (InfixRV_rvals-->rop);
731                         infix_term_type = INFIXTT_LOGICAL;
732           '[[':         acc = ~~ (InfixRV_rvals-->rop); flag = true;
733           '[//':        acc = ~ (InfixRV_rvals-->rop); flag = true;
734           'unary-':     acc = - (InfixRV_rvals-->rop); flag = true;
735         } ! end of switch(InfixRV_rvals-->maxi)
736         InfixRV_rvals-->maxi = acc;
737         InfixRV_types-->maxi = -1;
738         if (rop < n) InfixRV_types-->rop = -2;
739         if (flag == false && lop >= 0) InfixRV_types-->lop = -2;
740     } ! end of for (::)
741 ]; ! end of InfixRvalue
742
743 ! ------------------------------------------------------------------------
744
745 [ InfixWelcomeSub;
746     print "; Welcome to the ~Infix~ debugger (1/040828), which makes the
747         following verbs available:^^
748         ~; <expression>~: evaluates this Inform expression: e.g.
749         ~; location~ will print the value of the variable ~location~,
750         ~; 3*5+1~ will print 16, ~; children(old cloth bag)~ will tell you
751         how many items are in it. (You can name objects either by their
752         names inside the source code, such as ~d_obj~, or by typing the
753         names by which the game's parser would normally know them, such
754         as ~floor~: the effect is the same.)^
755         Any expression is allowed except that you can't use double-quoted
756         strings of text: but you can send messages, call routines or
757         assign values to variables, properties and array entries.
758         ^   ~; score++~ is one way to get on in the world.
759         ^   ~; deadflag = true~ is one way to get out of it.
760         ^   ~; StopDaemon(nasty little dwarf)~ will keep you from being pestered.^
761         Conditions like ~; score>20~ are also allowed and print
762         either 1 (if true) or 0 (if false).^^";
763     print "~;examine <something>~ or ~;x <something>~ gives full details
764         of whatever it is. For instance, ~;x ##Take~ describes the Take
765         action; ~;x Class~ the class Class; ~;x 'drop'~ the dictionary
766         word ~drop~ and so on for numbers, routines, arrays and of course
767         objects.  ~;xo~ examines something as an object, so for instance
768         ~;x location~ tells you about the variable ~location~, but ~;xo
769         location~ tells you what object it refers to.^^";
770     print "~;give~, ~;remove~ and ~;move~ work like the corresponding
771         Inform statements.^^";
772     print "~;<~ causes an action: for instance, ~;< Eat cheese~.^^";
773     print "~;watch~ or ~;w~ can set a watch on various activities:
774         type just ~;w~ for details.^^";
775     print "~;inventory~ or ~;i~ describes the contents of this story file.^";
776 ];
777
778 [ InfixEvalSub; InfixExamineP(true); ];
779
780 [ InfixActionSub;
781     print "; <", (InfixPrintAction) infix_lvalue;
782     if (noun) print " (", (the) noun, ")";
783     if (second) print " (", (the) second, ")";
784     print ">^";
785     if (second) <<(infix_lvalue) noun second>>;
786     if (noun) <<(infix_lvalue) noun>>;
787     <<(infix_lvalue)>>;
788 ];
789
790 [ InfixGiveSub f t;
791     print "; give (", (the) noun, ") ";
792     if (second < 0) { second = ~second; f=true; }
793     #Ifdef VN_1630;
794     t = NUM_ATTR_BYTES * 8;
795     #Ifnot;
796     t = 48;
797     #Endif; ! VN_
798     if (second < 0 || second >= t) "<No such attribute>";
799     if (f) print "@@126";
800     print (DebugAttribute) second;
801     #Ifdef TARGET_ZCODE;
802     if (f) @clear_attr noun second;
803     else   @set_attr noun second;
804     #Ifnot; ! TARGET_GLULX
805     t = second + 8;
806     if (f) @astorebit noun t 0; ! give noun ~second;
807     else   @astorebit noun t 1; ! give noun second;
808     #Endif; ! TARGET_
809     if (t);  ! quell unused n variable warning
810     new_line;
811 ];
812
813 [ InfixMoveSub;
814     print "; move (", (the) noun, ") to (", (the) second, ")^";
815     move noun to second;
816 ];
817
818 [ InfixRemoveSub;
819     print "; remove (", (the) noun, ")^";
820     remove noun;
821 ];
822
823 [ InfixHex x y;
824     #Ifdef TARGET_ZCODE;
825     y = (x & $7f00) / $100;
826     if (x < 0) y = y + $80;
827     #Ifnot; ! TARGET_GLULX
828     y = (x & $7f000000) / $1000000;
829     if (x < 0) y = y + $80;
830     print (Infixhexdigit) y/$10, (Infixhexdigit) y;
831     y = x & $ff0000 / $10000;
832     print (Infixhexdigit) y/$10, (Infixhexdigit) y;
833     y = (x & $ff00) / $100;
834     #Endif; ! TARGET_
835     x = x & $ff;
836     print (Infixhexdigit) y/$10, (Infixhexdigit) y, (Infixhexdigit) x/$10, (Infixhexdigit) x;
837 ];
838
839 [ Infixhexdigit x; x = x % $10; if (x < 10) print x; else print (char) 'a'+x-10; ];
840
841 [ InfixExamineOSub;
842     infix_data1 = metaclass(noun);
843     #Ifdef TARGET_GLULX; ! different coding for Glulx
844     if (infix_data1 == Object) infix_data1 = 2;
845     if (infix_data1 == Class) infix_data1 = 1;
846     #Endif; ! TARGET_
847     infix_term_type = INFIXTT_CONSTANT;
848     InfixExamineP(false);
849 ];
850
851 [ InfixExamineSSub;
852     infix_term_type = INFIXTT_STATICSTRING;
853     InfixExamineP(false);
854 ];
855
856 [ InfixExamineSub;     InfixExamineP(false); ];
857
858 [ InfixExamineP brief x a b w flag lines;
859     switch (infix_term_type) {
860       INFIXTT_NUMBER:
861         if (brief) "; == ", noun;
862         print "; The number ", noun, " == $", (InfixHex) noun;
863         if (noun >= 32 && noun < 127) print " == '", (char) noun, "'";
864         new_line;
865       INFIXTT_NAMEDOBJECT:
866         print "~", (name) noun, "~ (", noun, ")^"; if (brief) return;
867         <<Showobj noun>>;
868       INFIXTT_CONSTANT:
869         if (brief) "; == ", noun;
870         switch (infix_data1 & 15) {
871             nothing:
872                 print "; Constant ", (InfixPrintConstant) infix_parsed_lvalue,
873                 " == ", noun, "^";
874             2: <<Showobj noun>>;
875             1:
876                 print "Class ", (name) noun, "^";
877                 objectloop (a ofclass noun) {
878                     if (flag) print ", "; else print "Contains: ";
879                     print (name) a, " (", a, ")"; flag=true;
880                 }
881                 if (flag == false) "No object is of this class";
882         }
883         new_line;
884       INFIXTT_ATTRIBUTE:
885         if (brief) "; == ", noun;
886         if (noun >= 48 || noun < 0) "; No such attribute";
887         print "; Attribute ", (InfixPrintAttribute) noun,
888             " (numbered ", noun, ")^";
889         objectloop (x has noun) {
890             if (flag) print ", ";
891             else print "Each of these ~has ", (InfixPrintAttribute) noun, "~: ";
892             print (name) x, " (", x, ")"; flag = true;
893         }
894         if (flag == false) "No object ~has ", (InfixPrintAttribute) noun, "~";
895         new_line;
896       INFIXTT_PROPERTY:
897         if (brief) "; == ", noun;
898         print "; Property ", (property) noun, " (numbered ", noun, ")^";
899         objectloop (x provides noun) {
900             if (flag) print ", "; else print "Provided by: ";
901             print (name) x, " (", x, ")"; flag = true;
902         }
903         if (flag == false) "Which is not provided by any object";
904         new_line;
905       INFIXTT_DWORD:
906         if (brief) "; == ", noun;
907         if (noun == 0) "; This word is not in the dictionary";
908         a = noun->#dict_par1;
909         print "; Dictionary word '", (address) noun;
910         if (a & 4) print "//p";
911         print "' (address ", noun, ")";
912         if (a) {
913             print ": ";
914             if (a & 2)   print "meta ";
915             if (a & 1)   print "verb   ";
916             if (a & 8)   print "preposition   ";
917             if (a & 4)   print "pluralising ";
918             if (a & 128) print "noun ";
919         }
920         new_line;
921         if (a & 1) <<Showverb noun>>;
922       INFIXTT_ROUTINE:
923         if (brief) "; == ", noun;
924         print "; Routine ", (InfixPrintRoutine) infix_parsed_lvalue, " (number ",
925           infix_parsed_lvalue, ", packed address ", noun, ")^";
926       INFIXTT_GLOBAL:
927         if (brief) "; == ", noun;
928         print "; Global ", (InfixPrintGlobal) infix_parsed_lvalue, " == ", noun, "^";
929       INFIXTT_ARRAY:
930         if (brief) "; == ", noun;
931         print "; Array ", (InfixPrintArray) infix_parsed_lvalue, " ";
932         infix_data1 = infix_data1 % 16;
933         switch (infix_data1) {
934           0:    print "->"; a=0;
935           1:    print "-->"; a=0;
936           2:    print "string"; a=1;
937           3:    print "table"; a=1;
938           4:    print "buffer"; a=WORDSIZE;
939         }
940         print " ", infix_data2 + 1 - a, "^; == "; b = infix_data2;
941         for (w=b : w>=a : w--)
942             if (infix_data1 == 0 or 2 or 4) { if (noun->w) break; }
943             else { if (noun-->w) break; }
944         if (b-w < 5) w=b;
945         for (: x<=w : x++) {
946             if (infix_data1 == 0 or 2 or 4) print noun->x, " ";
947             else print noun-->x, " ";
948             if (x+1 == a) print ": ";
949             }
950         if (w < b) print "(then ", b-w, " zero entries)";
951         new_line;
952       INFIXTT_ACTION:
953         if (brief) "; == ", noun;
954         if (noun >= #lowest_fake_action_number && noun <= #highest_fake_action_number)
955            "; Fake action ", (InfixPrintFakeAction) noun,
956             " (numbered ", noun, ")^Is not generated by any grammar";
957         print "; Action ", (InfixPrintAction) noun,
958             " (numbered ", noun, ")^";
959         #Ifdef TARGET_ZCODE;
960         w = HDR_DICTIONARY-->0;
961         for (b=0 : b<(HDR_DICTIONARY-->0 + 5)-->0 : b++) {
962             w = HDR_DICTIONARY-->0 + 7 + b*9;
963             if ((w->#dict_par1) & 1) {
964                 a = (HDR_STATICMEMORY-->0)-->($ff-(w->#dict_par2));
965                 lines = a->0; a++;
966                 for (: lines>0 : lines--) {
967                     a = UnpackGrammarLine(a);
968                     if (action_to_be == noun) {
969                         print "'", (address) w, "' "; DebugGrammarLine();
970                         new_line;
971                         flag = true;
972                     }
973                 }
974             }
975         }
976         #Ifnot; ! TARGET_GLULX
977         for (b=0 : b < #dictionary_table-->0 : b++) {
978             w = #dictionary_table + WORDSIZE + b*(DICT_WORD_SIZE + 7);
979             if ((w->#dict_par1) & 1) {
980                 a = (#grammar_table)-->(DictionaryWordToVerbNum(w) + 1);
981                 lines = a->0; a++;
982                 for (: lines>0 : lines--) {
983                     a = UnpackGrammarLine(a);
984                     if (action_to_be == noun) {
985                         print "'", (address) w, "' "; DebugGrammarLine();
986                         new_line;
987                         flag = true;
988                     }
989                 }
990             }
991         }
992         #Endif; ! TARGET_
993
994         if (flag == 0) "Is not generated by any grammar";
995       INFIXTT_SYSFUN:
996         if (brief) "; == ", noun;
997         "; System function ~", (address) infix_parsed_lvalue, "~ has
998         not been overridden by any routine and so has its standard definition.";
999       INFIXTT_STATICSTRING:
1000         if (brief) "; == ", noun;
1001         if (metaclass(noun) ~= String) "; ", noun, " is not a string.";
1002         print "~", (string) noun, "~^";
1003       INFIXTT_LOGICAL:
1004         if (noun == true) "; true"; if (noun == false) "; false";
1005         "; ", noun;
1006     }
1007     new_line;
1008 ]; ! end of InfixExamineP
1009
1010 [ InfixDescribeWatchSub x y z s flag aflag;
1011     print "; The Infix ~;watch~ verb allows you to set a watch on any named
1012         routine(s) or objects: for instance ~;watch ScoreSub~ or
1013         ~;watch silver bars~. You can also:
1014         ^    ~;watch objects~: changes to attribute or property settings";
1015     if (debug_flag & 8) print " (on)"; else print " (off)";
1016
1017     print ";^    ~;watch timers~: the running of timers and daemons each turn";
1018     if (debug_flag & 4) print " (on)"; else print " (off)";
1019
1020     print ";^    ~;watch messages~: all messages sent";
1021     if (debug_flag & 1) print " (on)"; else print " (off)";
1022
1023     print ";^    ~;watch actions~: all actions generated";
1024     if (debug_flag & 2) print " (on)"; else print " (off)";
1025
1026     print ".^~~;watch~ can be abbreviated to ~;w~ and use ~off~ to stop
1027         watching: for instance ~;w location off~.^";
1028     aflag = debug_flag;
1029     objectloop (x has infix__watching) flag = true; aflag = aflag || flag;
1030     if (flag) print "The following objects are currently being watched: ";
1031     flag = false;
1032     objectloop (x has infix__watching) {
1033         if (flag) print ", "; flag = true;
1034         print (name) x, " (", x, ")";
1035     }
1036     if (flag) new_line;
1037     s = (#highest_routine_number - #lowest_routine_number);
1038     if (s%8 == 0) s=s/8; else s=s/8+1;
1039     for (flag=false,x=0 : x<s : x++) if (#routine_flags_array->x) flag = true;
1040     aflag = aflag || flag;
1041     if (flag) print "The following routines are currently being watched: ";
1042     for (x=0,flag=false : x<s : x++) {
1043         for (y=1,z=0 : y<256 : z++,y=y*2) {
1044             if ((#routine_flags_array->x) & y) {
1045                 if (flag) print ", "; flag = true;
1046                 print (InfixPrintRoutine)
1047                     #lowest_routine_number + x*8 + z;
1048             }
1049         }
1050     }
1051     if (flag) new_line;
1052     if (aflag == false) "At present, nothing is being watched.";
1053 ];
1054
1055 [ InfixWatchOnSub i j k l;
1056     if (noun == 0) return InfixDescribeWatchSub();
1057     if (infix_term_type == INFIXTT_ROUTINE) {
1058         i = infix_parsed_lvalue/8;
1059         for (j=0,k=1 : j<infix_parsed_lvalue%8 : j++) k=k*2;
1060         l = #routine_flags_array->i;
1061         l = l | k;
1062         #ifdef TARGET_ZCODE;
1063         @storeb #routine_flags_array i l;
1064         #ifnot; ! TARGET_GLULX
1065         @astoreb #routine_flags_array i l;
1066         #endif; ! TARGET_
1067        "; Watching routine ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
1068     }
1069     if (metaclass(noun) == Object) {
1070         give noun infix__watching;
1071        "; Watching object ~", (name) noun, "~ (", noun, ").";
1072     }
1073     InfixDescribeWatchSub();
1074   ];
1075
1076 [ InfixWatchOffSub i j k l;
1077     if (noun == 0) return InfixDescribeWatchSub();
1078     if (infix_term_type == INFIXTT_ROUTINE) {
1079         i = infix_parsed_lvalue/8;
1080         for (j=0,k=1 : j<infix_parsed_lvalue%8 : j++) k=k*2;
1081         l = #routine_flags_array->i;
1082         l = l & (~k);
1083         #ifdef TARGET_ZCODE;
1084         @storeb #routine_flags_array i l;
1085         #ifnot; ! TARGET_GLULX
1086         @astoreb #routine_flags_array i l;
1087         #endif; ! TARGET
1088        "; Not watching ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
1089     }
1090     if (metaclass(noun) == Object) {
1091         #ifdef TARGET_ZCODE;
1092         @clear_attr noun infix__watching;
1093         #ifnot; ! TARGET_GLULX
1094         @astorebit noun (infix__watching+8) 0;
1095         #endif; ! TARGET_
1096        "; Not watching object ~", (name) noun, "~ (", noun, ").";
1097     }
1098     InfixDescribeWatchSub();
1099 ];
1100
1101 [ InfixList from to tab filter i flag;
1102     print "^    ";
1103     for (i=from : i<=to : i++)
1104         if (tab-->(i-from)) {
1105             flag = true;
1106             if (tab == #array_names_array) {
1107                 Symb__Tab(INFIXTT_ARRAY, i);
1108                 flag = ~~(temp__global3 & 16);
1109             }
1110             if (tab == #routine_names_array) {
1111                 Symb__Tab(INFIXTT_ROUTINE,i);
1112                 flag = ~~(temp__global3 & 16);
1113             }
1114             if (tab == #constant_names_array) {
1115                 Symb__Tab(INFIXTT_CONSTANT,i);
1116                 flag = (~~(temp__global3 & 16)) && (temp__global3 % 16 == filter);
1117             }
1118             if (flag) print (string) tab-->(i-from), " ";
1119         }
1120         new_line;
1121 ];
1122
1123 [ InfixInvSub i;
1124
1125     print (string) Story, (string) Headline;
1126     print "  ", (number) #highest_object_number - #lowest_object_number + 1,
1127         " objects;^";
1128
1129     print "  non-library object-name constants:";
1130     InfixList(#lowest_constant_number, #highest_constant_number, #constant_names_array, 2);
1131
1132     print "  ", (number) #highest_class_number - #lowest_class_number + 1, "  classes:^    ";
1133     for (i=#lowest_class_number : i<=#highest_class_number : i++)
1134         print (name) #class_objects_array-->i, " ";
1135     new_line;
1136
1137     print "  non-library arrays:";
1138     InfixList(#lowest_array_number, #highest_array_number, #array_names_array);
1139
1140     print "  non-library routines:";
1141     InfixList(#lowest_routine_number, #highest_routine_number, #routine_names_array);
1142
1143     print "  non-library constants:";
1144     InfixList(#lowest_constant_number, #highest_constant_number, #constant_names_array, 0);
1145
1146     print "  (common) properties:";
1147     #Ifdef TARGET_ZCODE;
1148     InfixList(#lowest_property_number, INDIV_PROP_START-1, #property_names_array);
1149     #Ifnot; ! TARGET_GLULX
1150     InfixList(#lowest_property_number, #identifiers_table-->1 - 1, #property_names_array);
1151     #Endif; ! TARGET_
1152
1153     print "  (individual) properties:";
1154     #Ifdef TARGET_ZCODE;
1155     InfixList(INDIV_PROP_START, #highest_property_number, #property_names_array + 126);
1156     #Ifnot; ! TARGET_GLULX
1157     InfixList(INDIV_PROP_START, #highest_property_number, #identifiers_table-->2);
1158     #Endif; ! TARGET_
1159
1160     print "  attributes:";
1161     InfixList(#lowest_attribute_number, #highest_attribute_number, #attribute_names_array);
1162
1163     if (true) return;
1164
1165     print "  variables:";
1166     InfixList(#lowest_global_number, #highest_global_number, #global_names_array);
1167
1168     print "  actions:";
1169     InfixList(#lowest_action_number, #highest_action_number, #action_names_array);
1170
1171     print "  fake actions:";
1172     InfixList(#lowest_fake_action_number, #highest_fake_action_number, #fake_action_names_array);
1173 ];
1174
1175 Verb meta ';i' ';inv' ';inventory'
1176     *                                           -> InfixInv;
1177 Verb meta ';x' ';examine'
1178     * InfixRvalue                               -> InfixExamine;
1179 Verb meta ';xo' ';examineo'
1180     * InfixRvalue                               -> InfixExamineO;
1181 Verb meta ';xs' ';examines'
1182     * InfixRvalue                               -> InfixExamineS;
1183 Verb meta ';<'
1184     * InfixActionToken                          -> InfixAction
1185     * InfixActionToken InfixRvalue              -> InfixAction
1186     * InfixActionToken InfixRvalue InfixRvalue  -> InfixAction;
1187 Verb meta ';//'
1188     *                                           -> InfixWelcome
1189     * InfixRvalue                               -> InfixEval;
1190 Verb meta ';give'
1191     * InfixRvalue InfixRvalue                   -> InfixGive;
1192 Verb meta ';move'
1193     * InfixRvalue "to" InfixRvalue              -> InfixMove;
1194 Verb meta ';remove'
1195     * InfixRvalue                               -> InfixRemove;
1196 Verb meta ';watch' ';w'
1197     *                                           -> InfixWatchOn
1198     * "timers"/"daemons"                        -> TimersOn
1199     * "timers"/"daemons" "off"                  -> TimersOff
1200     * "actions"                                 -> ActionsOn
1201     * "actions" "off"                           -> ActionsOff
1202     * "messages"                                -> RoutinesOn
1203     * "messages" "off"                          -> RoutinesOff
1204     * "objects"                                 -> ChangesOn
1205     * "objects" "off"                           -> ChangesOff
1206     * InfixRvalueTerm                           -> InfixWatchOn
1207     * InfixRvalueTerm "off"                     -> InfixWatchOff;
1208
1209 #Endif; ! DEBUG
1210
1211 ! ==============================================================================