1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "glk/jacl/jacl.h"
24 #include "glk/jacl/language.h"
25 #include "glk/jacl/types.h"
26 #include "glk/jacl/prototypes.h"
27
28 namespace Glk {
29 namespace JACL {
30
31 #ifdef GLK
32 extern uint status_width, status_height;
33 extern winid_t statuswin;
34 #endif
35
36 #ifdef __NDS__
37 extern int screen_width;
38 extern int screen_depth;
39 #endif
40
41 extern struct object_type *object[];
42 extern struct integer_type *integer_table;
43 extern struct integer_type *integer[];
44 extern struct cinteger_type *cinteger_table;
45 extern struct attribute_type *attribute_table;
46 extern struct string_type *string_table;
47 extern struct string_type *cstring_table;
48 extern struct function_type *function_table;
49 extern struct function_type *executing_function;
50 extern struct command_type *completion_list;
51 extern struct word_type *grammar_table;
52 extern struct synonym_type *synonym_table;
53 extern struct filter_type *filter_table;
54
55 extern char function_name[];
56 extern char temp_buffer[];
57 extern char error_buffer[];
58 extern char integer_buffer[16];
59
60 #ifndef GLK
61 #ifndef __NDS__
62 extern char game_url[];
63 extern char user_id[];
64 #endif
65 #endif
66
67 extern int noun[];
68 extern int quoted[];
69 extern int percented[];
70 extern const char *word[];
71
72 extern int resolved_attribute;
73
74 extern int objects;
75 extern int integers;
76 extern int player;
77 extern int oec;
78 extern int *object_element_address;
79 extern int *object_backup_address;
80
81 extern int value_resolved;
82
83 char macro_function[84];
84 int value_has_been_resolved;
85
container_resolve(const char * container_name)86 int *container_resolve(const char *container_name) {
87 container_name = arg_text_of(container_name);
88
89 /* IN JACL, A 'CONTAINER' IS ANYTHING THAT CAN STORE AN INTEGER */
90 struct integer_type *resolved_integer;
91
92 if ((resolved_integer = integer_resolve(container_name)) != NULL)
93 return (&resolved_integer->value);
94 else if (object_element_resolve(container_name))
95 return (object_element_address);
96 else if (!strcmp(container_name, "noun1"))
97 return (&noun[0]);
98 else if (!strcmp(container_name, "noun2"))
99 return (&noun[1]);
100 else if (!strcmp(container_name, "noun3"))
101 return (&noun[2]);
102 else if (!strcmp(container_name, "noun4"))
103 return (&noun[3]);
104 else if (!strcmp(container_name, "player"))
105 return (&player);
106 else if (!strcmp(container_name, "here"))
107 return (&object[player]->PARENT);
108 else
109 return ((int *) NULL);
110 }
111
var_text_of_word(int wordnumber)112 const char *var_text_of_word(int wordnumber) {
113 const char *value;
114
115 if (percented[wordnumber] == FALSE) {
116 return (word[wordnumber]);
117 } else {
118 value_has_been_resolved = TRUE;
119 value = arg_text_of(word[wordnumber]);
120 while (value_has_been_resolved && percented[wordnumber]) {
121 value = arg_text_of(value);
122 percented[wordnumber]--;
123 }
124
125 return (value);
126 }
127 }
128
arg_text_of_word(int wordnumber)129 const char *arg_text_of_word(int wordnumber) {
130 const char *value;
131
132 if (quoted[wordnumber] == 1) {
133 return (word[wordnumber]);
134 } else {
135 value_has_been_resolved = TRUE;
136 value = arg_text_of(word[wordnumber]);
137 while (value_has_been_resolved && percented[wordnumber]) {
138 value = arg_text_of(value);
139 percented[wordnumber]--;
140 }
141
142 return (value);
143 }
144 }
145
text_of_word(int wordnumber)146 const char *text_of_word(int wordnumber) {
147 const char *value;
148
149 if (quoted[wordnumber] == 1) {
150 return (word[wordnumber]);
151 } else {
152 value_has_been_resolved = TRUE;
153 value = text_of(word[wordnumber]);
154 while (value_has_been_resolved && percented[wordnumber]) {
155 value = text_of(value);
156 percented[wordnumber]--;
157 }
158
159 return (value);
160 }
161 }
162
text_of(const char * string)163 const char *text_of(const char *string) {
164 struct integer_type *resolved_integer;
165 struct cinteger_type *resolved_cinteger;
166 struct string_type *resolved_string;
167 struct string_type *resolved_cstring;
168 char *return_string;
169
170 int index;
171
172 /* CHECK IF THE SUPPLIED STRING IS THE NAME OF A STRING CONSTANT,
173 * IF NOT, RETURN THE STRING LITERAL */
174 if ((return_string = macro_resolve(string)) != NULL) {
175 value_has_been_resolved = FALSE;
176 return (return_string);
177 } else if ((resolved_integer = integer_resolve(string)) != NULL) {
178 value_has_been_resolved = FALSE;
179 integer_buffer[0] = 0;
180 sprintf(integer_buffer, "%d", resolved_integer->value);
181 return (integer_buffer);
182 } else if ((resolved_cinteger = cinteger_resolve(string)) != NULL) {
183 value_has_been_resolved = FALSE;
184 integer_buffer[0] = 0;
185 sprintf(integer_buffer, "%d", resolved_cinteger->value);
186 return (integer_buffer);
187 } else if (object_element_resolve(string)) {
188 value_has_been_resolved = FALSE;
189 integer_buffer[0] = 0;
190 sprintf(integer_buffer, "%d", oec);
191 return (integer_buffer);
192 } else if ((index = object_resolve(string)) != -1) {
193 value_has_been_resolved = FALSE;
194 if (index < 1 || index > objects) {
195 badptrrun(string, index);
196 return ("");
197 } else {
198 return (object[index]->label);
199 }
200 } else if ((resolved_string = string_resolve(string)) != NULL) {
201 return (resolved_string->value);
202 } else if ((resolved_cstring = cstring_resolve(string)) != NULL) {
203 return (resolved_cstring->value);
204 } else if (function_resolve(string) != NULL) {
205 value_has_been_resolved = FALSE;
206 sprintf(integer_buffer, "%d", execute(string));
207 return (integer_buffer);
208 #ifndef GLK
209 #ifndef __NDS__
210 } else if (!strcmp(string, "$url")) {
211 value_has_been_resolved = FALSE;
212 return (game_url);
213 } else if (!strcmp(string, "$user_id")) {
214 value_has_been_resolved = FALSE;
215 return (user_id);
216 #endif
217 #endif
218 } else {
219 value_has_been_resolved = FALSE;
220 return (string);
221 }
222 }
223
arg_text_of(const char * string)224 const char *arg_text_of(const char *string) {
225 struct string_type *resolved_string;
226 struct string_type *resolved_cstring;
227 char *macro_text;
228
229 /* CHECK IF THE SUPPLIED STRING IS THE NAME OF A STRING CONSTANT,
230 * IF NOT, RETURN THE STRING LITERAL */
231 if ((macro_text = macro_resolve(string)) != NULL) {
232 value_has_been_resolved = FALSE;
233 return (macro_text);
234 } else if ((resolved_string = string_resolve(string)) != NULL) {
235 return (resolved_string->value);
236 } else if ((resolved_cstring = cstring_resolve(string)) != NULL) {
237 value_has_been_resolved = FALSE;
238 return (resolved_cstring->value);
239 } else {
240 value_has_been_resolved = FALSE;
241 return (string);
242 }
243 }
244
validate(const char * string)245 int validate(const char *string) {
246 int index,
247 count;
248
249 if (string == NULL) {
250 return (FALSE);
251 }
252
253 /* CHECK IF THE SUPPLIED STRING IS A VALID INTEGER */
254 count = strlen(string);
255
256 /* LOOP OVER THE WHOLE STRING MAKING SURE THAT EACH CHARACTER IS EITHER
257 * A DIGIT OR A MINUS SIGN */
258 for (index = 0; index < count; index++) {
259 if (!Common::isDigit((int) * (string + index)) && string[index] != '-') {
260 //printf ("'%c' is not a digit\n", *(string + index));
261 return (FALSE);
262 }
263 }
264
265 return (TRUE);
266 }
267
value_of(const char * value,int run_time)268 long value_of(const char *value, int run_time) {
269 long compare;
270
271 value_resolved = TRUE;
272
273 value = arg_text_of(value);
274
275 /* RETURN THE INTEGER VALUE OF A STRING */
276 struct integer_type *resolved_integer;
277 struct cinteger_type *resolved_cinteger;
278
279 if (!strcmp(value, "**held")) {
280 return (FALSE);
281 } else if (!strcmp(value, "**here")) {
282 return (FALSE);
283 } else if (!strcmp(value, "**anywhere")) {
284 return (FALSE);
285 } else if (!strcmp(value, "**present")) {
286 return (FALSE);
287 } else if (!strcmp(value, "*held")) {
288 return (FALSE);
289 } else if (!strcmp(value, "*here")) {
290 return (FALSE);
291 } else if (!strcmp(value, "*anywhere")) {
292 return (FALSE);
293 } else if (!strcmp(value, "*present")) {
294 return (FALSE);
295 } else if (!strcmp(value, "random")) {
296 return random_number();
297 #ifdef GLK
298 } else if (!strcmp(value, "status_height")) {
299 g_vm->glk_window_get_size(statuswin, &status_width, &status_height);
300 return status_height;
301 } else if (!strcmp(value, "status_width")) {
302 g_vm->glk_window_get_size(statuswin, &status_width, &status_height);
303 return status_width;
304 #else
305 #ifdef __NDS__
306 } else if (!strcmp(value, "status_height")) {
307 return screen_depth;
308 } else if (!strcmp(value, "status_width")) {
309 return screen_width;
310 #else
311 } else if (!strcmp(value, "status_height")) {
312 value_resolved = FALSE;
313 return -1;
314 } else if (!strcmp(value, "status_width")) {
315 value_resolved = FALSE;
316 return -1;
317 #endif
318 #endif
319 } else if (!strcmp(value, "unixtime")) {
320 return g_system->getMillis() / 1000;
321 } else if (validate(value)) {
322 return (atoi(value));
323 } else if ((resolved_cinteger = cinteger_resolve(value)) != NULL) {
324 return (resolved_cinteger->value);
325 } else if ((resolved_integer = integer_resolve(value)) != NULL) {
326 return (resolved_integer->value);
327 } else if (function_resolve(value) != NULL) {
328 return (execute(value));
329 } else if (object_element_resolve(value)) {
330 return (oec);
331 } else if ((compare = attribute_resolve(value))) {
332 resolved_attribute = SYSTEM_ATTRIBUTE;
333 return (compare);
334 } else if ((compare = user_attribute_resolve(value))) {
335 resolved_attribute = USER_ATTRIBUTE;
336 return (compare);
337 } else if ((compare = object_resolve(value)) != -1) {
338 return (compare);
339 } else if (*value == '@') {
340 return (count_resolve(value));
341 } else {
342 if (run_time) {
343 unkvarrun(value);
344 }
345 value_resolved = FALSE;
346 return (-1);
347 }
348 }
349
integer_resolve(const char * name)350 struct integer_type *integer_resolve(const char *name) {
351 int index,
352 iterator,
353 counter;
354 int delimiter = 0;
355 char expression[84];
356
357 strncpy(expression, name, 80);
358
359 counter = strlen(expression);
360
361 for (index = 0; index < counter; index++) {
362 if (expression[index] == '[') {
363 /* THIS MAY STILL BE AN OBJECT ELEMENT IF A CLOSING ] */
364 /* IS FOUND BEFORE AN OPENING ( */
365 expression[index] = 0;
366 delimiter = index + 1;
367 /* LOOK FOR THE CLOSING ], BUT IF YOU FIND A ( FIRST */
368 /* THEN THIS EXPRESSION IS NOT AN ARRAY */
369 for (iterator = counter; iterator > 0; iterator--) {
370 if (expression[iterator] == ']') {
371 expression[iterator] = 0;
372 break;
373 } else if (expression[iterator] == '(') {
374 /* NOT A VARIABLE ARRAY */
375 return (FALSE);
376 }
377 }
378 break;
379 } else if (expression[index] == '<') {
380 /* HIT A < BEFORE A [ THEREFORE */
381 /* IS A FUNCTION CALL, NOT AN ARRAY */
382 return (NULL);
383 } else if (expression[index] == '(') {
384 /* HIT A ( BEFORE A [ THEREFORE */
385 /* IS AN OBJECT ELEMENT, NOT AN ARRAY */
386 return (NULL);
387 } else if (expression[index] == ' ')
388 return (NULL);
389 }
390
391 // NO DELIMITER FOUND, TRY AS UNINDEXED VARIABLE
392 if (delimiter == 0) {
393 return (integer_resolve_indexed(name, 0));
394 }
395
396 // NO STRING BEFORE DELIMITER
397 if (delimiter == 1) {
398 return (NULL);
399 }
400
401 counter = value_of(&expression[delimiter], TRUE);
402
403 if (counter > -1) {
404 return (integer_resolve_indexed(expression, counter));
405 } else {
406 /* INDEX OUT OF RANGE */
407 return (NULL);
408 }
409 }
410
integer_resolve_indexed(const char * name,int index)411 struct integer_type *integer_resolve_indexed(const char *name, int index) {
412 struct integer_type *pointer = integer_table;
413
414 if (pointer == NULL)
415 return (NULL);
416
417 do {
418 if (!strcmp(name, pointer->name)) {
419 if (index == 0) {
420 return (pointer);
421 } else {
422 /* THIS VARIABLE DOES MATCH, BUT WERE NOT AT THE
423 * RIGHT INDEX YET SO MOVE ON */
424 pointer = pointer->next_integer;
425 index--;
426 }
427 } else
428 pointer = pointer->next_integer;
429 } while (pointer != NULL);
430
431 /* IF index != 0, INDEX OUT OF RANGE, OTHERWISE NOT VARIABLE */
432 return (NULL);
433 }
434
cinteger_resolve(const char * name)435 struct cinteger_type *cinteger_resolve(const char *name) {
436 int index,
437 iterator,
438 counter;
439 int delimiter = 0;
440 char expression[84];
441
442 strncpy(expression, name, 80);
443
444 counter = strlen(expression);
445
446 for (index = 0; index < counter; index++) {
447 if (expression[index] == '[') {
448 /* THIS MAY STILL BE AN OBJECT ELEMENT IF A CLOSING ] */
449 /* IS FOUND BEFORE AN OPENING ( */
450 expression[index] = 0;
451 delimiter = index + 1;
452 /* LOOK FOR THE CLOSING ], BUT IF YOU FIND A ( FIRST */
453 /* THEN THIS EXPRESSION IS NOT AN ARRAY */
454 for (iterator = counter; iterator > 0; iterator--) {
455 if (expression[iterator] == ']') {
456 expression[iterator] = 0;
457 break;
458 } else if (expression[iterator] == '(') {
459 /* NOT A CONSTANT ARRAY */
460 return (FALSE);
461 }
462 }
463 break;
464 } else if (expression[index] == '<') {
465 /* HIT A < BEFORE A [ THEREFORE */
466 /* IS A FUNCTION CALL, NOT AN ARRAY */
467 return (NULL);
468 } else if (expression[index] == '(') {
469 /* HIT A ( BEFORE A [ THEREFORE */
470 /* IS AN OBJECT ELEMENT, NOT AN ARRAY */
471 return (NULL);
472 } else if (expression[index] == ' ')
473 return (NULL);
474 }
475
476 // NO DELIMITER FOUND, TRY AS UNINDEXED CONSTANT
477 if (delimiter == 0) {
478 return (cinteger_resolve_indexed(name, 0));
479 }
480
481 // NO STRING BEFORE DELIMITER
482 if (delimiter == 1) {
483 return (NULL);
484 }
485
486 counter = value_of(&expression[delimiter], TRUE);
487
488 if (counter > -1) {
489 return (cinteger_resolve_indexed(expression, counter));
490 } else {
491 /* INDEX OUT OF RANGE */
492 return (NULL);
493 }
494 }
495
cinteger_resolve_indexed(const char * name,int index)496 struct cinteger_type *cinteger_resolve_indexed(const char *name, int index) {
497 struct cinteger_type *pointer = cinteger_table;
498
499 if (pointer == NULL)
500 return (NULL);
501
502 do {
503 if (!strcmp(name, pointer->name)) {
504 if (index == 0) {
505 return (pointer);
506 } else {
507 /* THIS VARIABLE DOES MATCH, BUT WERE NOT AT THE
508 * RIGHT INDEX YET SO MOVE ON */
509 pointer = pointer->next_cinteger;
510 index--;
511 }
512 } else
513 pointer = pointer->next_cinteger;
514 } while (pointer != NULL);
515
516 /* IF index != 0, INDEX OUT OF RANGE, OTHERWISE NOT VARIABLE */
517 return (NULL);
518 }
519
string_resolve(const char * name)520 struct string_type *string_resolve(const char *name) {
521 int index,
522 iterator,
523 counter;
524 int delimiter = 0;
525 char expression[84];
526
527 strncpy(expression, name, 80);
528
529 counter = strlen(expression);
530
531 for (index = 0; index < counter; index++) {
532 if (expression[index] == '[') {
533 expression[index] = 0;
534 delimiter = index + 1;
535 for (iterator = counter; iterator > 0; iterator--) {
536 if (expression[iterator] == ']') {
537 expression[iterator] = 0;
538 break;
539 }
540 }
541 break;
542 } else if (expression[index] == '<') {
543 /* HIT A < BEFORE A [ THEREFORE */
544 /* IS A FUNCTION CALL, NOT AN ARRAY */
545 return (NULL);
546 } else if (expression[index] == '(') {
547 /* HIT A ( BEFORE A [ THEREFORE */
548 /* IS AN OBJECT ELEMENT, NOT AN ARRAY */
549 return (NULL);
550 } else if (expression[index] == ' ')
551 return (NULL);
552 }
553
554 if (delimiter == 0) {
555 /* NO DELIMITER FOUND, TRY AS UNINDEXED VARIABLE */
556 return (string_resolve_indexed(name, 0));
557 }
558
559 if (delimiter == 1) {
560 /* NO STRING BEFORE DELIMITER */
561 return (NULL);
562 }
563
564 counter = value_of(&expression[delimiter], TRUE);
565
566 if (counter > -1) {
567 return (string_resolve_indexed(expression, counter));
568 } else
569 return (NULL);
570 }
571
string_resolve_indexed(const char * name,int index)572 struct string_type *string_resolve_indexed(const char *name, int index) {
573 struct string_type *pointer = string_table;
574
575 if (pointer == NULL)
576 return (NULL);
577
578 do {
579 if (!strcmp(name, pointer->name)) {
580 if (index == 0) {
581 return (pointer);
582 } else {
583 /* THIS STRING DOES MATCH, BUT WERE NOT AT THE
584 * RIGHT INDEX YET SO MOVE ON */
585 pointer = pointer->next_string;
586 index--;
587 }
588 } else {
589 pointer = pointer->next_string;
590 }
591 } while (pointer != NULL);
592
593 return (NULL);
594 }
595
cstring_resolve(const char * name)596 struct string_type *cstring_resolve(const char *name) {
597 int index,
598 iterator,
599 counter;
600 int delimiter = 0;
601 char expression[84];
602
603 strncpy(expression, name, 80);
604
605 counter = strlen(expression);
606
607 for (index = 0; index < counter; index++) {
608 if (expression[index] == '[') {
609 expression[index] = 0;
610 delimiter = index + 1;
611 for (iterator = counter; iterator > 0; iterator--) {
612 if (expression[iterator] == ']') {
613 expression[iterator] = 0;
614 break;
615 }
616 }
617 break;
618 } else if (expression[index] == '<') {
619 /* HIT A < BEFORE A [ THEREFORE */
620 /* IS A FUNCTION CALL, NOT AN ARRAY */
621 return (NULL);
622 } else if (expression[index] == '(') {
623 /* HIT A ( BEFORE A [ THEREFORE */
624 /* IS AN OBJECT ELEMENT, NOT AN ARRAY */
625 return (NULL);
626 } else if (expression[index] == ' ')
627 return (NULL);
628 }
629
630 if (delimiter == 0) {
631 /* NO DELIMITER FOUND, TRY AS UNINDEXED VARIABLE */
632 return (cstring_resolve_indexed(name, 0));
633 }
634
635 if (delimiter == 1) {
636 /* NO STRING BEFORE DELIMITER */
637 return (NULL);
638 }
639
640 counter = value_of(&expression[delimiter], TRUE);
641
642 if (counter > -1) {
643 return (cstring_resolve_indexed(expression, counter));
644 } else
645 return (NULL);
646 }
647
cstring_resolve_indexed(const char * name,int index)648 struct string_type *cstring_resolve_indexed(const char *name, int index) {
649 struct string_type *pointer = cstring_table;
650
651 if (pointer == NULL)
652 return (NULL);
653
654 do {
655 if (!strcmp(name, pointer->name)) {
656 if (index == 0) {
657 return (pointer);
658 } else {
659 /* THIS STRING DOES MATCH, BUT WERE NOT AT THE
660 * RIGHT INDEX YET SO MOVE ON */
661 pointer = pointer->next_string;
662 index--;
663 }
664 } else {
665 pointer = pointer->next_string;
666 }
667 } while (pointer != NULL);
668
669 return (NULL);
670 }
671
function_resolve(const char * name)672 struct function_type *function_resolve(const char *name) {
673 const char *full_name;
674 char core_name[84];
675 int index;
676
677 struct function_type *pointer = function_table;
678
679 if (function_table == NULL)
680 return (NULL);
681
682 /* STRIP ARGUMENTS OFF FIRST, THEN EXPAND RESOLVE NAME */
683 index = 0;
684
685 while (*name && index < 80) {
686 if (*name == '<') {
687 break;
688 } else {
689 core_name[index++] = *name++;
690 }
691 }
692 core_name[index] = 0;
693
694 /* GET A POINTER TO A STRING THAT REPRESENTS THE EXPANDED NAME OF THE FUNCTION */
695 full_name = (const char *)expand_function(core_name);
696
697 /* LOOP THROUGH ALL THE FUNCTIONS LOOKING FOR A FUNCTION THAT
698 * HAS THIS EXPANDED FULL NAME */
699 do {
700 if (!strcmp(full_name, pointer->name))
701 return (pointer);
702 else
703 pointer = pointer->next_function;
704 } while (pointer != NULL);
705
706 /* RETURN A POINTER TO THE STRUCTURE THAT ENCAPSULATES THE FUNCTION */
707 return (NULL);
708 }
709
expand_function(const char * name)710 const char *expand_function(const char *name) {
711 /* THIS FUNCTION TAKES A SCOPE FUNCTION CALL SUCH AS noun1.function
712 * AND REOLVE THE ACTUAL FUNCTION NAME SUCH AS function_key */
713 int index,
714 counter;
715 int delimiter = 0;
716 char expression[84];
717
718 strncpy(expression, name, 80);
719
720 counter = strlen(expression);
721
722 for (index = 0; index < counter; index++) {
723 if (expression[index] == '.') {
724 expression[index] = 0;
725 delimiter = index + 1;
726 break;
727 }
728 }
729
730 if (delimiter == FALSE) {
731 /* THIS FUNCTION DOESN'T CONTAIN A '.', SO RETURN IT AS IS */
732 return (arg_text_of(name));
733 }
734
735 /* THE ORIGINAL STRING IS NOW CUT INTO TWO STRINGS:
736 * expression.delimiter */
737
738 index = value_of(expression, TRUE);
739
740 if (index < 1 || index > objects) {
741 return ((const char *) name);
742 }
743
744 if (cinteger_resolve(&expression[delimiter]) != NULL ||
745 integer_resolve(&expression[delimiter]) != NULL ||
746 object_element_resolve(&expression[delimiter])) {
747 /* THE DELIMETER RESOLVES TO A CONSTANT, VARIABLE OR OBJECT
748 * ELEMENT, SO TAKE NOTE OF THAT */
749 sprintf(function_name, "%ld", value_of(&expression[delimiter], TRUE));
750 } else {
751 strcpy(function_name, &expression[delimiter]);
752 }
753 strcat(function_name, "_");
754 strcat(function_name, object[index]->label);
755
756 return ((const char *) function_name);
757 }
758
macro_resolve(const char * testString)759 char *macro_resolve(const char *testString) {
760 int index,
761 counter;
762 int delimiter = 0;
763 char expression[84];
764
765 strncpy(expression, testString, 80);
766
767 counter = strlen(expression);
768
769 for (index = 0; index < counter; index++) {
770 if (expression[index] == '{' || expression[index] == '}') {
771 expression[index] = 0;
772 if (!delimiter)
773 delimiter = index + 1;
774 }
775 }
776
777 if (delimiter == FALSE)
778 return (NULL);
779
780 if (*expression != 0) {
781 index = value_of(expression, TRUE);
782 } else {
783 index = 0;
784 }
785
786 if (!strcmp(&expression[delimiter], "list")) {
787 if (index < 1 || index > objects) {
788 badptrrun(expression, index);
789 return (NULL);
790 } else {
791 return (list_output(index, FALSE));
792 }
793 } else if (!strcmp(&expression[delimiter], "plain")) {
794 if (index < 1 || index > objects) {
795 badptrrun(expression, index);
796 return (NULL);
797 } else {
798 return (plain_output(index, FALSE));
799 }
800 } else if (!strcmp(&expression[delimiter], "long")) {
801 if (index < 1 || index > objects) {
802 badptrrun(expression, index);
803 return (NULL);
804 } else {
805 return (long_output(index));
806 }
807 } else if (!strcmp(&expression[delimiter], "sub")) {
808 if (index < 1 || index > objects) {
809 badptrrun(expression, index);
810 return (NULL);
811 } else {
812 return (sub_output(index, FALSE));
813 }
814 } else if (!strcmp(&expression[delimiter], "obj")) {
815 if (index < 1 || index > objects) {
816 badptrrun(expression, index);
817 return (NULL);
818 } else {
819 return (obj_output(index, FALSE));
820 }
821 } else if (!strcmp(&expression[delimiter], "that")) {
822 if (index < 1 || index > objects) {
823 badptrrun(expression, index);
824 return (NULL);
825 } else {
826 return (that_output(index, FALSE));
827 }
828 } else if (!strcmp(&expression[delimiter], "it")) {
829 if (index < 1 || index > objects) {
830 badptrrun(expression, index);
831 return (NULL);
832 } else {
833 return (it_output(index, FALSE));
834 }
835 } else if (!strcmp(&expression[delimiter], "doesnt")) {
836 if (index < 1 || index > objects) {
837 badptrrun(expression, index);
838 return (NULL);
839 } else {
840 return (doesnt_output(index, FALSE));
841 }
842 } else if (!strcmp(&expression[delimiter], "does")) {
843 if (index < 1 || index > objects) {
844 badptrrun(expression, index);
845 return (NULL);
846 } else {
847 return (does_output(index, FALSE));
848 }
849 } else if (!strcmp(&expression[delimiter], "isnt")) {
850 if (index < 1 || index > objects) {
851 badptrrun(expression, index);
852 return (NULL);
853 } else {
854 return (isnt_output(index, FALSE));
855 }
856 } else if (!strcmp(&expression[delimiter], "is")) {
857 if (index < 1 || index > objects) {
858 badptrrun(expression, index);
859 return (NULL);
860 } else {
861 return (is_output(index, FALSE));
862 }
863 } else if (!strcmp(&expression[delimiter], "the")) {
864 if (index < 1 || index > objects) {
865 badptrrun(expression, index);
866 return (NULL);
867 } else {
868 return (sentence_output(index, FALSE));
869 }
870 } else if (!strcmp(&expression[delimiter], "s")) {
871 if (index < 1 || index > objects) {
872 badptrrun(expression, index);
873 return (NULL);
874 } else {
875 if (object[index]->attributes & PLURAL) {
876 strcpy(temp_buffer, "");
877 } else {
878 strcpy(temp_buffer, "s");
879 }
880 return (temp_buffer);
881 }
882 } else if (!strcmp(&expression[delimiter], "names")) {
883 if (index < 1 || index > objects) {
884 badptrrun(expression, index);
885 return (NULL);
886 } else {
887 return (object_names(index, temp_buffer));
888 }
889 } else if (!strcmp(&expression[delimiter], "label")) {
890 if (index < 1 || index > objects) {
891 badptrrun(expression, index);
892 return (NULL);
893 } else {
894 return (object[index]->label);
895 }
896 } else if (!strcmp(&expression[delimiter], "List")) {
897 if (index < 1 || index > objects) {
898 badptrrun(expression, index);
899 return (NULL);
900 } else {
901 return (list_output(index, TRUE));
902 }
903 } else if (!strcmp(&expression[delimiter], "Plain")) {
904 if (index < 1 || index > objects) {
905 badptrrun(expression, index);
906 return (NULL);
907 } else {
908 return (plain_output(index, TRUE));
909 }
910 } else if (!strcmp(&expression[delimiter], "Sub")) {
911 if (index < 1 || index > objects) {
912 badptrrun(expression, index);
913 return (NULL);
914 } else {
915 return (sub_output(index, TRUE));
916 }
917 } else if (!strcmp(&expression[delimiter], "Obj")) {
918 if (index < 1 || index > objects) {
919 badptrrun(expression, index);
920 return (NULL);
921 } else {
922 return (obj_output(index, TRUE));
923 }
924 } else if (!strcmp(&expression[delimiter], "That")) {
925 if (index < 1 || index > objects) {
926 badptrrun(expression, index);
927 return (NULL);
928 } else {
929 return (that_output(index, TRUE));
930 }
931 } else if (!strcmp(&expression[delimiter], "It")) {
932 if (index < 1 || index > objects) {
933 badptrrun(expression, index);
934 return (NULL);
935 } else {
936 return (it_output(index, TRUE));
937 }
938 } else if (!strcmp(&expression[delimiter], "Doesnt")) {
939 if (index < 1 || index > objects) {
940 badptrrun(expression, index);
941 return (NULL);
942 } else {
943 return (doesnt_output(index, TRUE));
944 }
945 } else if (!strcmp(&expression[delimiter], "Does")) {
946 if (index < 1 || index > objects) {
947 badptrrun(expression, index);
948 return (NULL);
949 } else {
950 return (does_output(index, TRUE));
951 }
952 } else if (!strcmp(&expression[delimiter], "Isnt")) {
953 if (index < 1 || index > objects) {
954 badptrrun(expression, index);
955 return (NULL);
956 } else {
957 return (isnt_output(index, TRUE));
958 }
959 } else if (!strcmp(&expression[delimiter], "Is")) {
960 if (index < 1 || index > objects) {
961 badptrrun(expression, index);
962 return (NULL);
963 } else {
964 return (is_output(index, TRUE));
965 }
966 } else if (!strcmp(&expression[delimiter], "The")) {
967 if (index < 1 || index > objects) {
968 badptrrun(expression, index);
969 return (NULL);
970 } else {
971 return (sentence_output(index, TRUE));
972 }
973 } else {
974 strcpy(macro_function, "+macro_");
975 strcat(macro_function, &expression[delimiter]);
976 strcat(macro_function, "<");
977 sprintf(temp_buffer, "%d", index);
978 strcat(macro_function, temp_buffer);
979
980 // BUILD THE FUNCTION NAME AND PASS THE OBJECT AS
981 // THE ONLY ARGUMENT
982 if (execute(macro_function)) {
983 return (string_resolve("return_value")->value);
984 }
985 }
986
987 return (NULL);
988 }
989
count_resolve(const char * testString)990 int count_resolve(const char *testString) {
991 struct function_type *resolved_function = NULL;
992
993 if (*(testString + 1) == 0) {
994 // @ ON ITS OWN, SO RETURN THE CALL COUNT OF THE CURRENTLY EXECUTING
995 // FUNCTION
996 return (executing_function->call_count);
997 } else if ((resolved_function = function_resolve(testString + 1)) != NULL) {
998 return (resolved_function->call_count);
999 } else {
1000 return array_length_resolve(testString);
1001 }
1002 }
1003
array_length_resolve(const char * testString)1004 int array_length_resolve(const char *testString) {
1005 int counter = 0;
1006 const char *array_name = &testString[1];
1007
1008 struct integer_type *integer_pointer = integer_table;
1009 struct cinteger_type *cinteger_pointer = cinteger_table;
1010 struct string_type *string_pointer = string_table;
1011 struct string_type *cstring_pointer = cstring_table;
1012
1013 if (integer_pointer != NULL) {
1014 do {
1015 if (!strcmp(array_name, integer_pointer->name)) {
1016 counter++;
1017 }
1018 integer_pointer = integer_pointer->next_integer;
1019 } while (integer_pointer != NULL);
1020 }
1021
1022 /* IF ONE OR MORE INTEGERS WITH THIS NAME WERE FOUND
1023 RETURN THE COUNT */
1024 if (counter)
1025 return (counter);
1026
1027 if (string_pointer != NULL) {
1028 do {
1029 if (!strcmp(array_name, string_pointer->name)) {
1030 counter++;
1031 }
1032 string_pointer = string_pointer->next_string;
1033 } while (string_pointer != NULL);
1034 }
1035
1036 /* IF ONE OR MORE STRINGS WITH THIS NAME WERE FOUND
1037 RETURN THE COUNT */
1038 if (counter)
1039 return (counter);
1040
1041 if (cinteger_pointer != NULL) {
1042 do {
1043 if (!strcmp(array_name, cinteger_pointer->name)) {
1044 counter++;
1045 }
1046 cinteger_pointer = cinteger_pointer->next_cinteger;
1047 } while (cinteger_pointer != NULL);
1048 }
1049
1050 /* IF ONE OR MORE INTEGER CONSTANTS WITH THIS NAME WERE FOUND
1051 RETURN THE COUNT */
1052 if (counter)
1053 return (counter);
1054
1055 if (cstring_pointer != NULL) {
1056 do {
1057 if (!strcmp(array_name, cstring_pointer->name)) {
1058 counter++;
1059 }
1060 cstring_pointer = cstring_pointer->next_string;
1061 } while (cstring_pointer != NULL);
1062 }
1063
1064 /* IF ONE OR MORE STRING CONSTANTS WITH THIS NAME WERE FOUND
1065 RETURN THE COUNT */
1066 if (counter)
1067 return (counter);
1068
1069 /* NO VARIABLES OR STRINGS FOUND */
1070 return (0);
1071 }
1072
object_element_resolve(const char * testString)1073 int object_element_resolve(const char *testString) {
1074 int index,
1075 iterator,
1076 counter;
1077 int delimiter = 0;
1078 char expression[84];
1079
1080 struct integer_type *resolved_integer;
1081 struct cinteger_type *resolved_cinteger;
1082
1083 strncpy(expression, testString, 80);
1084
1085 //sprintf(temp_buffer, "incoming = %s^", testString);
1086 //write_text (temp_buffer);
1087
1088 counter = strlen(expression);
1089
1090 for (index = 0; index < counter; index++) {
1091 if (expression[index] == '(') {
1092 expression[index] = 0;
1093 delimiter = index + 1;
1094 for (iterator = counter; iterator > 0; iterator--) {
1095 if (expression[iterator] == ')') {
1096 expression[iterator] = 0;
1097 break;
1098 }
1099 }
1100 break;
1101 } else if (expression[index] == '<') {
1102 /* HIT A < BEFORE A [ THEREFORE */
1103 /* IS A FUNCTION CALL, NOT AN ARRAY */
1104 return (FALSE);
1105 } else if (expression[index] == '[') {
1106 /* HIT A [ BEFORE A ( THEREFORE */
1107 /* THIS EXPRESSION IS AN ARRAY, NOT AN OBJECT ELEMENT */
1108 /* UNLESS A CLOSING ] IS FOUND BEFORE THE OPENING ( */
1109 /* ie. COULD BE AN array[index](element) FORMAT */
1110 /* SEARCH FORWARD... */
1111 for (; index < counter; index++) {
1112 if (expression[index] == ']') {
1113 /* BREAK OUT AND KEEP LOOKING FOR A ( */
1114 break;
1115 } else if (expression[index] == '(') {
1116 /* THIS EXPRESSION IS DEFINITELY AN ARRAY WITH AN */
1117 /* OBJECT ELEMENT AS THE INDEX */
1118 return (FALSE);
1119 }
1120 }
1121 } else if (expression[index] == ' ')
1122 return (FALSE);
1123 }
1124
1125 // NO DELIMITER FOUND OR NO STRING BEFORE DELIMITER
1126 if (delimiter == FALSE || delimiter == 1)
1127 return (FALSE);
1128
1129 index = object_resolve(expression);
1130
1131 if (index == -1) {
1132 //sprintf(temp_buffer, "expression %s is not an object^", expression);
1133 //write_text(temp_buffer);
1134
1135 // COULDN'T BE RESOLVED AS AN OBJECT, TRY AS A VARIABLE
1136 if ((resolved_integer = integer_resolve(expression)) != NULL) {
1137 index = resolved_integer->value;
1138 } else if ((resolved_cinteger = cinteger_resolve(expression)) != NULL) {
1139 index = resolved_cinteger->value;
1140 }
1141 }
1142
1143 if (index < 1 || index > objects) {
1144 badptrrun(expression, index);
1145 return (FALSE);
1146 }
1147
1148 counter = value_of(&expression[delimiter], TRUE);
1149
1150 if (counter < 0 || counter > 15) {
1151 sprintf(error_buffer,
1152 "ERROR: In function \"%s\", element \"%s\" out of range (%d).^",
1153 executing_function->name, &expression[delimiter], counter);
1154 write_text(error_buffer);
1155 return (FALSE);
1156 } else {
1157 oec = object[index]->integer[counter];
1158 object_element_address = &object[index]->integer[counter];
1159 return (TRUE);
1160 }
1161 }
1162
object_resolve(const char * object_string)1163 int object_resolve(const char *object_string) {
1164 int index;
1165
1166 if (!strcmp(object_string, "noun1"))
1167 return (noun[0]);
1168 else if (!strcmp(object_string, "noun2"))
1169 return (noun[1]);
1170 else if (!strcmp(object_string, "noun3"))
1171 return (noun[2]);
1172 else if (!strcmp(object_string, "noun4"))
1173 return (noun[3]);
1174 else if (!strcmp(object_string, "player"))
1175 return (player);
1176 else if (!strcmp(object_string, "here"))
1177 return (HERE);
1178 else if (!strcmp(object_string, "self") ||
1179 !strcmp(object_string, "this")) {
1180 if (executing_function != NULL && executing_function->self == 0) {
1181 sprintf(error_buffer,
1182 "ERROR: Reference to 'self' from global function \"%s\".^",
1183 executing_function->name);
1184 write_text(error_buffer);
1185 } else
1186 return (executing_function->self);
1187 } else {
1188 for (index = 1; index <= objects; index++) {
1189 if (!strcmp(object_string, object[index]->label))
1190 return (index);
1191 }
1192 }
1193
1194 return (-1);
1195 }
1196
attribute_resolve(const char * attribute)1197 long attribute_resolve(const char *attribute) {
1198 long bit_mask;
1199
1200 if (!strcmp(attribute, "VISITED"))
1201 return (VISITED);
1202 else if (!strcmp(attribute, "DARK"))
1203 return (DARK);
1204 else if (!strcmp(attribute, "ON_WATER"))
1205 return (ON_WATER);
1206 else if (!strcmp(attribute, "UNDER_WATER"))
1207 return (UNDER_WATER);
1208 else if (!strcmp(attribute, "WITHOUT_AIR"))
1209 return (WITHOUT_AIR);
1210 else if (!strcmp(attribute, "OUTDOORS"))
1211 return (OUTDOORS);
1212 else if (!strcmp(attribute, "MID_AIR"))
1213 return (MID_AIR);
1214 else if (!strcmp(attribute, "TIGHT_ROPE"))
1215 return (TIGHT_ROPE);
1216 else if (!strcmp(attribute, "POLLUTED"))
1217 return (POLLUTED);
1218 else if (!strcmp(attribute, "SOLVED"))
1219 return (SOLVED);
1220 else if (!strcmp(attribute, "MID_WATER"))
1221 return (MID_WATER);
1222 else if (!strcmp(attribute, "DARKNESS")) {
1223 bit_mask = DARKNESS;
1224 if (check_light(HERE)) {
1225 bit_mask = ~bit_mask;
1226 object[HERE]->attributes = object[HERE]->attributes & bit_mask;
1227 } else {
1228 object[HERE]->attributes = object[HERE]->attributes | bit_mask;
1229 }
1230 return (DARKNESS);
1231 } else if (!strcmp(attribute, "MAPPED"))
1232 return (MAPPED);
1233 else if (!strcmp(attribute, "KNOWN"))
1234 return (KNOWN);
1235 else if (!strcmp(attribute, "CLOSED"))
1236 return (CLOSED);
1237 else if (!strcmp(attribute, "LOCKED"))
1238 return (LOCKED);
1239 else if (!strcmp(attribute, "DEAD"))
1240 return (DEAD);
1241 else if (!strcmp(attribute, "IGNITABLE"))
1242 return (IGNITABLE);
1243 else if (!strcmp(attribute, "WORN"))
1244 return (WORN);
1245 else if (!strcmp(attribute, "CONCEALING"))
1246 return (CONCEALING);
1247 else if (!strcmp(attribute, "LUMINOUS"))
1248 return (LUMINOUS);
1249 else if (!strcmp(attribute, "WEARABLE"))
1250 return (WEARABLE);
1251 else if (!strcmp(attribute, "CLOSABLE"))
1252 return (CLOSABLE);
1253 else if (!strcmp(attribute, "LOCKABLE"))
1254 return (LOCKABLE);
1255 else if (!strcmp(attribute, "ANIMATE"))
1256 return (ANIMATE);
1257 else if (!strcmp(attribute, "LIQUID"))
1258 return (LIQUID);
1259 else if (!strcmp(attribute, "CONTAINER"))
1260 return (CONTAINER);
1261 else if (!strcmp(attribute, "SURFACE"))
1262 return (SURFACE);
1263 else if (!strcmp(attribute, "PLURAL"))
1264 return (PLURAL);
1265 else if (!strcmp(attribute, "FLAMMABLE"))
1266 return (FLAMMABLE);
1267 else if (!strcmp(attribute, "BURNING"))
1268 return (BURNING);
1269 else if (!strcmp(attribute, "LOCATION"))
1270 return (LOCATION);
1271 else if (!strcmp(attribute, "ON"))
1272 return (ON);
1273 else if (!strcmp(attribute, "DAMAGED"))
1274 return (DAMAGED);
1275 else if (!strcmp(attribute, "FEMALE"))
1276 return (FEMALE);
1277 else if (!strcmp(attribute, "POSSESSIVE"))
1278 return (POSSESSIVE);
1279 else if (!strcmp(attribute, "OUT_OF_REACH"))
1280 return (OUT_OF_REACH);
1281 else if (!strcmp(attribute, "TOUCHED"))
1282 return (TOUCHED);
1283 else if (!strcmp(attribute, "SCORED"))
1284 return (SCORED);
1285 else if (!strcmp(attribute, "SITTING"))
1286 return (SITTING);
1287 else if (!strcmp(attribute, "NPC"))
1288 return (NPC);
1289 else if (!strcmp(attribute, "DONE"))
1290 return (DONE);
1291 else if (!strcmp(attribute, "GAS"))
1292 return (MAPPED);
1293 else if (!strcmp(attribute, "NO_TAB"))
1294 return (NO_TAB);
1295 else if (!strcmp(attribute, "NOT_IMPORTANT"))
1296 return (NOT_IMPORTANT);
1297 else
1298 return (0);
1299 }
1300
user_attribute_resolve(const char * name)1301 long user_attribute_resolve(const char *name) {
1302 struct attribute_type *pointer = attribute_table;
1303
1304 if (pointer == NULL)
1305 return (0);
1306
1307 do {
1308 if (!strcmp(name, pointer->name)) {
1309 return (pointer->value);
1310 } else
1311 pointer = pointer->next_attribute;
1312 } while (pointer != NULL);
1313
1314 /* ATTRIBUTE NOT FOUND */
1315 return (0);
1316 }
1317
1318 } // End of namespace JACL
1319 } // End of namespace Glk
1320