scummvm/engines/glk/jacl/resolvers.cpp
Orgad Shaneh 0111a08560 GLK: Use nullptr
Using clang-tidy modernize-use-nullptr
2021-11-14 15:51:59 +02:00

1319 lines
35 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "glk/jacl/jacl.h"
#include "glk/jacl/language.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
namespace Glk {
namespace JACL {
#ifdef GLK
extern uint status_width, status_height;
extern winid_t statuswin;
#endif
#ifdef __NDS__
extern int screen_width;
extern int screen_depth;
#endif
extern struct object_type *object[];
extern struct integer_type *integer_table;
extern struct integer_type *integer[];
extern struct cinteger_type *cinteger_table;
extern struct attribute_type *attribute_table;
extern struct string_type *string_table;
extern struct string_type *cstring_table;
extern struct function_type *function_table;
extern struct function_type *executing_function;
extern struct command_type *completion_list;
extern struct word_type *grammar_table;
extern struct synonym_type *synonym_table;
extern struct filter_type *filter_table;
extern char function_name[];
extern char temp_buffer[];
extern char error_buffer[];
extern char integer_buffer[16];
#ifndef GLK
#ifndef __NDS__
extern char game_url[];
extern char user_id[];
#endif
#endif
extern int noun[];
extern int quoted[];
extern int percented[];
extern const char *word[];
extern int resolved_attribute;
extern int objects;
extern int integers;
extern int player;
extern int oec;
extern int *object_element_address;
extern int *object_backup_address;
extern int value_resolved;
char macro_function[84];
int value_has_been_resolved;
int *container_resolve(const char *container_name) {
container_name = arg_text_of(container_name);
/* IN JACL, A 'CONTAINER' IS ANYTHING THAT CAN STORE AN INTEGER */
struct integer_type *resolved_integer;
if ((resolved_integer = integer_resolve(container_name)) != nullptr)
return (&resolved_integer->value);
else if (object_element_resolve(container_name))
return (object_element_address);
else if (!strcmp(container_name, "noun1"))
return (&noun[0]);
else if (!strcmp(container_name, "noun2"))
return (&noun[1]);
else if (!strcmp(container_name, "noun3"))
return (&noun[2]);
else if (!strcmp(container_name, "noun4"))
return (&noun[3]);
else if (!strcmp(container_name, "player"))
return (&player);
else if (!strcmp(container_name, "here"))
return (&object[player]->PARENT);
else
return ((int *) nullptr);
}
const char *var_text_of_word(int wordnumber) {
const char *value;
if (percented[wordnumber] == FALSE) {
return (word[wordnumber]);
} else {
value_has_been_resolved = TRUE;
value = arg_text_of(word[wordnumber]);
while (value_has_been_resolved && percented[wordnumber]) {
value = arg_text_of(value);
percented[wordnumber]--;
}
return (value);
}
}
const char *arg_text_of_word(int wordnumber) {
const char *value;
if (quoted[wordnumber] == 1) {
return (word[wordnumber]);
} else {
value_has_been_resolved = TRUE;
value = arg_text_of(word[wordnumber]);
while (value_has_been_resolved && percented[wordnumber]) {
value = arg_text_of(value);
percented[wordnumber]--;
}
return (value);
}
}
const char *text_of_word(int wordnumber) {
const char *value;
if (quoted[wordnumber] == 1) {
return (word[wordnumber]);
} else {
value_has_been_resolved = TRUE;
value = text_of(word[wordnumber]);
while (value_has_been_resolved && percented[wordnumber]) {
value = text_of(value);
percented[wordnumber]--;
}
return (value);
}
}
const char *text_of(const char *string) {
struct integer_type *resolved_integer;
struct cinteger_type *resolved_cinteger;
struct string_type *resolved_string;
struct string_type *resolved_cstring;
char *return_string;
int index;
/* CHECK IF THE SUPPLIED STRING IS THE NAME OF A STRING CONSTANT,
* IF NOT, RETURN THE STRING LITERAL */
if ((return_string = macro_resolve(string)) != nullptr) {
value_has_been_resolved = FALSE;
return (return_string);
} else if ((resolved_integer = integer_resolve(string)) != nullptr) {
value_has_been_resolved = FALSE;
integer_buffer[0] = 0;
sprintf(integer_buffer, "%d", resolved_integer->value);
return (integer_buffer);
} else if ((resolved_cinteger = cinteger_resolve(string)) != nullptr) {
value_has_been_resolved = FALSE;
integer_buffer[0] = 0;
sprintf(integer_buffer, "%d", resolved_cinteger->value);
return (integer_buffer);
} else if (object_element_resolve(string)) {
value_has_been_resolved = FALSE;
integer_buffer[0] = 0;
sprintf(integer_buffer, "%d", oec);
return (integer_buffer);
} else if ((index = object_resolve(string)) != -1) {
value_has_been_resolved = FALSE;
if (index < 1 || index > objects) {
badptrrun(string, index);
return ("");
} else {
return (object[index]->label);
}
} else if ((resolved_string = string_resolve(string)) != nullptr) {
return (resolved_string->value);
} else if ((resolved_cstring = cstring_resolve(string)) != nullptr) {
return (resolved_cstring->value);
} else if (function_resolve(string) != nullptr) {
value_has_been_resolved = FALSE;
sprintf(integer_buffer, "%d", execute(string));
return (integer_buffer);
#ifndef GLK
#ifndef __NDS__
} else if (!strcmp(string, "$url")) {
value_has_been_resolved = FALSE;
return (game_url);
} else if (!strcmp(string, "$user_id")) {
value_has_been_resolved = FALSE;
return (user_id);
#endif
#endif
} else {
value_has_been_resolved = FALSE;
return (string);
}
}
const char *arg_text_of(const char *string) {
struct string_type *resolved_string;
struct string_type *resolved_cstring;
char *macro_text;
/* CHECK IF THE SUPPLIED STRING IS THE NAME OF A STRING CONSTANT,
* IF NOT, RETURN THE STRING LITERAL */
if ((macro_text = macro_resolve(string)) != nullptr) {
value_has_been_resolved = FALSE;
return (macro_text);
} else if ((resolved_string = string_resolve(string)) != nullptr) {
return (resolved_string->value);
} else if ((resolved_cstring = cstring_resolve(string)) != nullptr) {
value_has_been_resolved = FALSE;
return (resolved_cstring->value);
} else {
value_has_been_resolved = FALSE;
return (string);
}
}
int validate(const char *string) {
int index,
count;
if (string == nullptr) {
return (FALSE);
}
/* CHECK IF THE SUPPLIED STRING IS A VALID INTEGER */
count = strlen(string);
/* LOOP OVER THE WHOLE STRING MAKING SURE THAT EACH CHARACTER IS EITHER
* A DIGIT OR A MINUS SIGN */
for (index = 0; index < count; index++) {
if (!Common::isDigit((int) * (string + index)) && string[index] != '-') {
//printf ("'%c' is not a digit\n", *(string + index));
return (FALSE);
}
}
return (TRUE);
}
long value_of(const char *value, int run_time) {
long compare;
value_resolved = TRUE;
value = arg_text_of(value);
/* RETURN THE INTEGER VALUE OF A STRING */
struct integer_type *resolved_integer;
struct cinteger_type *resolved_cinteger;
if (!strcmp(value, "**held")) {
return (FALSE);
} else if (!strcmp(value, "**here")) {
return (FALSE);
} else if (!strcmp(value, "**anywhere")) {
return (FALSE);
} else if (!strcmp(value, "**present")) {
return (FALSE);
} else if (!strcmp(value, "*held")) {
return (FALSE);
} else if (!strcmp(value, "*here")) {
return (FALSE);
} else if (!strcmp(value, "*anywhere")) {
return (FALSE);
} else if (!strcmp(value, "*present")) {
return (FALSE);
} else if (!strcmp(value, "random")) {
return random_number();
#ifdef GLK
} else if (!strcmp(value, "status_height")) {
g_vm->glk_window_get_size(statuswin, &status_width, &status_height);
return status_height;
} else if (!strcmp(value, "status_width")) {
g_vm->glk_window_get_size(statuswin, &status_width, &status_height);
return status_width;
#else
#ifdef __NDS__
} else if (!strcmp(value, "status_height")) {
return screen_depth;
} else if (!strcmp(value, "status_width")) {
return screen_width;
#else
} else if (!strcmp(value, "status_height")) {
value_resolved = FALSE;
return -1;
} else if (!strcmp(value, "status_width")) {
value_resolved = FALSE;
return -1;
#endif
#endif
} else if (!strcmp(value, "unixtime")) {
return g_system->getMillis() / 1000;
} else if (validate(value)) {
return (atoi(value));
} else if ((resolved_cinteger = cinteger_resolve(value)) != nullptr) {
return (resolved_cinteger->value);
} else if ((resolved_integer = integer_resolve(value)) != nullptr) {
return (resolved_integer->value);
} else if (function_resolve(value) != nullptr) {
return (execute(value));
} else if (object_element_resolve(value)) {
return (oec);
} else if ((compare = attribute_resolve(value))) {
resolved_attribute = SYSTEM_ATTRIBUTE;
return (compare);
} else if ((compare = user_attribute_resolve(value))) {
resolved_attribute = USER_ATTRIBUTE;
return (compare);
} else if ((compare = object_resolve(value)) != -1) {
return (compare);
} else if (*value == '@') {
return (count_resolve(value));
} else {
if (run_time) {
unkvarrun(value);
}
value_resolved = FALSE;
return (-1);
}
}
struct integer_type *integer_resolve(const char *name) {
int index,
iterator,
counter;
int delimiter = 0;
char expression[84];
strncpy(expression, name, 80);
counter = strlen(expression);
for (index = 0; index < counter; index++) {
if (expression[index] == '[') {
/* THIS MAY STILL BE AN OBJECT ELEMENT IF A CLOSING ] */
/* IS FOUND BEFORE AN OPENING ( */
expression[index] = 0;
delimiter = index + 1;
/* LOOK FOR THE CLOSING ], BUT IF YOU FIND A ( FIRST */
/* THEN THIS EXPRESSION IS NOT AN ARRAY */
for (iterator = counter; iterator > 0; iterator--) {
if (expression[iterator] == ']') {
expression[iterator] = 0;
break;
} else if (expression[iterator] == '(') {
/* NOT A VARIABLE ARRAY */
return (FALSE);
}
}
break;
} else if (expression[index] == '<') {
/* HIT A < BEFORE A [ THEREFORE */
/* IS A FUNCTION CALL, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == '(') {
/* HIT A ( BEFORE A [ THEREFORE */
/* IS AN OBJECT ELEMENT, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == ' ')
return (nullptr);
}
// NO DELIMITER FOUND, TRY AS UNINDEXED VARIABLE
if (delimiter == 0) {
return (integer_resolve_indexed(name, 0));
}
// NO STRING BEFORE DELIMITER
if (delimiter == 1) {
return (nullptr);
}
counter = value_of(&expression[delimiter], TRUE);
if (counter > -1) {
return (integer_resolve_indexed(expression, counter));
} else {
/* INDEX OUT OF RANGE */
return (nullptr);
}
}
struct integer_type *integer_resolve_indexed(const char *name, int index) {
struct integer_type *pointer = integer_table;
if (pointer == nullptr)
return (nullptr);
do {
if (!strcmp(name, pointer->name)) {
if (index == 0) {
return (pointer);
} else {
/* THIS VARIABLE DOES MATCH, BUT WERE NOT AT THE
* RIGHT INDEX YET SO MOVE ON */
pointer = pointer->next_integer;
index--;
}
} else
pointer = pointer->next_integer;
} while (pointer != nullptr);
/* IF index != 0, INDEX OUT OF RANGE, OTHERWISE NOT VARIABLE */
return (nullptr);
}
struct cinteger_type *cinteger_resolve(const char *name) {
int index,
iterator,
counter;
int delimiter = 0;
char expression[84];
strncpy(expression, name, 80);
counter = strlen(expression);
for (index = 0; index < counter; index++) {
if (expression[index] == '[') {
/* THIS MAY STILL BE AN OBJECT ELEMENT IF A CLOSING ] */
/* IS FOUND BEFORE AN OPENING ( */
expression[index] = 0;
delimiter = index + 1;
/* LOOK FOR THE CLOSING ], BUT IF YOU FIND A ( FIRST */
/* THEN THIS EXPRESSION IS NOT AN ARRAY */
for (iterator = counter; iterator > 0; iterator--) {
if (expression[iterator] == ']') {
expression[iterator] = 0;
break;
} else if (expression[iterator] == '(') {
/* NOT A CONSTANT ARRAY */
return (FALSE);
}
}
break;
} else if (expression[index] == '<') {
/* HIT A < BEFORE A [ THEREFORE */
/* IS A FUNCTION CALL, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == '(') {
/* HIT A ( BEFORE A [ THEREFORE */
/* IS AN OBJECT ELEMENT, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == ' ')
return (nullptr);
}
// NO DELIMITER FOUND, TRY AS UNINDEXED CONSTANT
if (delimiter == 0) {
return (cinteger_resolve_indexed(name, 0));
}
// NO STRING BEFORE DELIMITER
if (delimiter == 1) {
return (nullptr);
}
counter = value_of(&expression[delimiter], TRUE);
if (counter > -1) {
return (cinteger_resolve_indexed(expression, counter));
} else {
/* INDEX OUT OF RANGE */
return (nullptr);
}
}
struct cinteger_type *cinteger_resolve_indexed(const char *name, int index) {
struct cinteger_type *pointer = cinteger_table;
if (pointer == nullptr)
return (nullptr);
do {
if (!strcmp(name, pointer->name)) {
if (index == 0) {
return (pointer);
} else {
/* THIS VARIABLE DOES MATCH, BUT WERE NOT AT THE
* RIGHT INDEX YET SO MOVE ON */
pointer = pointer->next_cinteger;
index--;
}
} else
pointer = pointer->next_cinteger;
} while (pointer != nullptr);
/* IF index != 0, INDEX OUT OF RANGE, OTHERWISE NOT VARIABLE */
return (nullptr);
}
struct string_type *string_resolve(const char *name) {
int index,
iterator,
counter;
int delimiter = 0;
char expression[84];
strncpy(expression, name, 80);
counter = strlen(expression);
for (index = 0; index < counter; index++) {
if (expression[index] == '[') {
expression[index] = 0;
delimiter = index + 1;
for (iterator = counter; iterator > 0; iterator--) {
if (expression[iterator] == ']') {
expression[iterator] = 0;
break;
}
}
break;
} else if (expression[index] == '<') {
/* HIT A < BEFORE A [ THEREFORE */
/* IS A FUNCTION CALL, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == '(') {
/* HIT A ( BEFORE A [ THEREFORE */
/* IS AN OBJECT ELEMENT, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == ' ')
return (nullptr);
}
if (delimiter == 0) {
/* NO DELIMITER FOUND, TRY AS UNINDEXED VARIABLE */
return (string_resolve_indexed(name, 0));
}
if (delimiter == 1) {
/* NO STRING BEFORE DELIMITER */
return (nullptr);
}
counter = value_of(&expression[delimiter], TRUE);
if (counter > -1) {
return (string_resolve_indexed(expression, counter));
} else
return (nullptr);
}
struct string_type *string_resolve_indexed(const char *name, int index) {
struct string_type *pointer = string_table;
if (pointer == nullptr)
return (nullptr);
do {
if (!strcmp(name, pointer->name)) {
if (index == 0) {
return (pointer);
} else {
/* THIS STRING DOES MATCH, BUT WERE NOT AT THE
* RIGHT INDEX YET SO MOVE ON */
pointer = pointer->next_string;
index--;
}
} else {
pointer = pointer->next_string;
}
} while (pointer != nullptr);
return (nullptr);
}
struct string_type *cstring_resolve(const char *name) {
int index,
iterator,
counter;
int delimiter = 0;
char expression[84];
strncpy(expression, name, 80);
counter = strlen(expression);
for (index = 0; index < counter; index++) {
if (expression[index] == '[') {
expression[index] = 0;
delimiter = index + 1;
for (iterator = counter; iterator > 0; iterator--) {
if (expression[iterator] == ']') {
expression[iterator] = 0;
break;
}
}
break;
} else if (expression[index] == '<') {
/* HIT A < BEFORE A [ THEREFORE */
/* IS A FUNCTION CALL, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == '(') {
/* HIT A ( BEFORE A [ THEREFORE */
/* IS AN OBJECT ELEMENT, NOT AN ARRAY */
return (nullptr);
} else if (expression[index] == ' ')
return (nullptr);
}
if (delimiter == 0) {
/* NO DELIMITER FOUND, TRY AS UNINDEXED VARIABLE */
return (cstring_resolve_indexed(name, 0));
}
if (delimiter == 1) {
/* NO STRING BEFORE DELIMITER */
return (nullptr);
}
counter = value_of(&expression[delimiter], TRUE);
if (counter > -1) {
return (cstring_resolve_indexed(expression, counter));
} else
return (nullptr);
}
struct string_type *cstring_resolve_indexed(const char *name, int index) {
struct string_type *pointer = cstring_table;
if (pointer == nullptr)
return (nullptr);
do {
if (!strcmp(name, pointer->name)) {
if (index == 0) {
return (pointer);
} else {
/* THIS STRING DOES MATCH, BUT WERE NOT AT THE
* RIGHT INDEX YET SO MOVE ON */
pointer = pointer->next_string;
index--;
}
} else {
pointer = pointer->next_string;
}
} while (pointer != nullptr);
return (nullptr);
}
struct function_type *function_resolve(const char *name) {
const char *full_name;
char core_name[84];
int index;
struct function_type *pointer = function_table;
if (function_table == nullptr)
return (nullptr);
/* STRIP ARGUMENTS OFF FIRST, THEN EXPAND RESOLVE NAME */
index = 0;
while (*name && index < 80) {
if (*name == '<') {
break;
} else {
core_name[index++] = *name++;
}
}
core_name[index] = 0;
/* GET A POINTER TO A STRING THAT REPRESENTS THE EXPANDED NAME OF THE FUNCTION */
full_name = (const char *)expand_function(core_name);
/* LOOP THROUGH ALL THE FUNCTIONS LOOKING FOR A FUNCTION THAT
* HAS THIS EXPANDED FULL NAME */
do {
if (!strcmp(full_name, pointer->name))
return (pointer);
else
pointer = pointer->next_function;
} while (pointer != nullptr);
/* RETURN A POINTER TO THE STRUCTURE THAT ENCAPSULATES THE FUNCTION */
return (nullptr);
}
const char *expand_function(const char *name) {
/* THIS FUNCTION TAKES A SCOPE FUNCTION CALL SUCH AS noun1.function
* AND REOLVE THE ACTUAL FUNCTION NAME SUCH AS function_key */
int index,
counter;
int delimiter = 0;
char expression[84];
strncpy(expression, name, 80);
counter = strlen(expression);
for (index = 0; index < counter; index++) {
if (expression[index] == '.') {
expression[index] = 0;
delimiter = index + 1;
break;
}
}
if (delimiter == FALSE) {
/* THIS FUNCTION DOESN'T CONTAIN A '.', SO RETURN IT AS IS */
return (arg_text_of(name));
}
/* THE ORIGINAL STRING IS NOW CUT INTO TWO STRINGS:
* expression.delimiter */
index = value_of(expression, TRUE);
if (index < 1 || index > objects) {
return ((const char *) name);
}
if (cinteger_resolve(&expression[delimiter]) != nullptr ||
integer_resolve(&expression[delimiter]) != nullptr ||
object_element_resolve(&expression[delimiter])) {
/* THE DELIMETER RESOLVES TO A CONSTANT, VARIABLE OR OBJECT
* ELEMENT, SO TAKE NOTE OF THAT */
sprintf(function_name, "%ld", value_of(&expression[delimiter], TRUE));
} else {
strcpy(function_name, &expression[delimiter]);
}
strcat(function_name, "_");
strcat(function_name, object[index]->label);
return ((const char *) function_name);
}
char *macro_resolve(const char *testString) {
int index,
counter;
int delimiter = 0;
char expression[84];
strncpy(expression, testString, 80);
counter = strlen(expression);
for (index = 0; index < counter; index++) {
if (expression[index] == '{' || expression[index] == '}') {
expression[index] = 0;
if (!delimiter)
delimiter = index + 1;
}
}
if (delimiter == FALSE)
return (nullptr);
if (*expression != 0) {
index = value_of(expression, TRUE);
} else {
index = 0;
}
if (!strcmp(&expression[delimiter], "list")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (list_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "plain")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (plain_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "long")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (long_output(index));
}
} else if (!strcmp(&expression[delimiter], "sub")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (sub_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "obj")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (obj_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "that")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (that_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "it")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (it_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "doesnt")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (doesnt_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "does")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (does_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "isnt")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (isnt_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "is")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (is_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "the")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (sentence_output(index, FALSE));
}
} else if (!strcmp(&expression[delimiter], "s")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
if (object[index]->attributes & PLURAL) {
strcpy(temp_buffer, "");
} else {
strcpy(temp_buffer, "s");
}
return (temp_buffer);
}
} else if (!strcmp(&expression[delimiter], "names")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (object_names(index, temp_buffer));
}
} else if (!strcmp(&expression[delimiter], "label")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (object[index]->label);
}
} else if (!strcmp(&expression[delimiter], "List")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (list_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "Plain")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (plain_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "Sub")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (sub_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "Obj")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (obj_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "That")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (that_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "It")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (it_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "Doesnt")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (doesnt_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "Does")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (does_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "Isnt")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (isnt_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "Is")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (is_output(index, TRUE));
}
} else if (!strcmp(&expression[delimiter], "The")) {
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (nullptr);
} else {
return (sentence_output(index, TRUE));
}
} else {
strcpy(macro_function, "+macro_");
strcat(macro_function, &expression[delimiter]);
strcat(macro_function, "<");
sprintf(temp_buffer, "%d", index);
strcat(macro_function, temp_buffer);
// BUILD THE FUNCTION NAME AND PASS THE OBJECT AS
// THE ONLY ARGUMENT
if (execute(macro_function)) {
return (string_resolve("return_value")->value);
}
}
return (nullptr);
}
int count_resolve(const char *testString) {
struct function_type *resolved_function = nullptr;
if (*(testString + 1) == 0) {
// @ ON ITS OWN, SO RETURN THE CALL COUNT OF THE CURRENTLY EXECUTING
// FUNCTION
return (executing_function->call_count);
} else if ((resolved_function = function_resolve(testString + 1)) != nullptr) {
return (resolved_function->call_count);
} else {
return array_length_resolve(testString);
}
}
int array_length_resolve(const char *testString) {
int counter = 0;
const char *array_name = &testString[1];
struct integer_type *integer_pointer = integer_table;
struct cinteger_type *cinteger_pointer = cinteger_table;
struct string_type *string_pointer = string_table;
struct string_type *cstring_pointer = cstring_table;
if (integer_pointer != nullptr) {
do {
if (!strcmp(array_name, integer_pointer->name)) {
counter++;
}
integer_pointer = integer_pointer->next_integer;
} while (integer_pointer != nullptr);
}
/* IF ONE OR MORE INTEGERS WITH THIS NAME WERE FOUND
RETURN THE COUNT */
if (counter)
return (counter);
if (string_pointer != nullptr) {
do {
if (!strcmp(array_name, string_pointer->name)) {
counter++;
}
string_pointer = string_pointer->next_string;
} while (string_pointer != nullptr);
}
/* IF ONE OR MORE STRINGS WITH THIS NAME WERE FOUND
RETURN THE COUNT */
if (counter)
return (counter);
if (cinteger_pointer != nullptr) {
do {
if (!strcmp(array_name, cinteger_pointer->name)) {
counter++;
}
cinteger_pointer = cinteger_pointer->next_cinteger;
} while (cinteger_pointer != nullptr);
}
/* IF ONE OR MORE INTEGER CONSTANTS WITH THIS NAME WERE FOUND
RETURN THE COUNT */
if (counter)
return (counter);
if (cstring_pointer != nullptr) {
do {
if (!strcmp(array_name, cstring_pointer->name)) {
counter++;
}
cstring_pointer = cstring_pointer->next_string;
} while (cstring_pointer != nullptr);
}
/* IF ONE OR MORE STRING CONSTANTS WITH THIS NAME WERE FOUND
RETURN THE COUNT */
if (counter)
return (counter);
/* NO VARIABLES OR STRINGS FOUND */
return (0);
}
int object_element_resolve(const char *testString) {
int index,
iterator,
counter;
int delimiter = 0;
char expression[84];
struct integer_type *resolved_integer;
struct cinteger_type *resolved_cinteger;
strncpy(expression, testString, 80);
//sprintf(temp_buffer, "incoming = %s^", testString);
//write_text (temp_buffer);
counter = strlen(expression);
for (index = 0; index < counter; index++) {
if (expression[index] == '(') {
expression[index] = 0;
delimiter = index + 1;
for (iterator = counter; iterator > 0; iterator--) {
if (expression[iterator] == ')') {
expression[iterator] = 0;
break;
}
}
break;
} else if (expression[index] == '<') {
/* HIT A < BEFORE A [ THEREFORE */
/* IS A FUNCTION CALL, NOT AN ARRAY */
return (FALSE);
} else if (expression[index] == '[') {
/* HIT A [ BEFORE A ( THEREFORE */
/* THIS EXPRESSION IS AN ARRAY, NOT AN OBJECT ELEMENT */
/* UNLESS A CLOSING ] IS FOUND BEFORE THE OPENING ( */
/* ie. COULD BE AN array[index](element) FORMAT */
/* SEARCH FORWARD... */
for (; index < counter; index++) {
if (expression[index] == ']') {
/* BREAK OUT AND KEEP LOOKING FOR A ( */
break;
} else if (expression[index] == '(') {
/* THIS EXPRESSION IS DEFINITELY AN ARRAY WITH AN */
/* OBJECT ELEMENT AS THE INDEX */
return (FALSE);
}
}
} else if (expression[index] == ' ')
return (FALSE);
}
// NO DELIMITER FOUND OR NO STRING BEFORE DELIMITER
if (delimiter == FALSE || delimiter == 1)
return (FALSE);
index = object_resolve(expression);
if (index == -1) {
//sprintf(temp_buffer, "expression %s is not an object^", expression);
//write_text(temp_buffer);
// COULDN'T BE RESOLVED AS AN OBJECT, TRY AS A VARIABLE
if ((resolved_integer = integer_resolve(expression)) != nullptr) {
index = resolved_integer->value;
} else if ((resolved_cinteger = cinteger_resolve(expression)) != nullptr) {
index = resolved_cinteger->value;
}
}
if (index < 1 || index > objects) {
badptrrun(expression, index);
return (FALSE);
}
counter = value_of(&expression[delimiter], TRUE);
if (counter < 0 || counter > 15) {
sprintf(error_buffer,
"ERROR: In function \"%s\", element \"%s\" out of range (%d).^",
executing_function->name, &expression[delimiter], counter);
write_text(error_buffer);
return (FALSE);
} else {
oec = object[index]->integer[counter];
object_element_address = &object[index]->integer[counter];
return (TRUE);
}
}
int object_resolve(const char *object_string) {
int index;
if (!strcmp(object_string, "noun1"))
return (noun[0]);
else if (!strcmp(object_string, "noun2"))
return (noun[1]);
else if (!strcmp(object_string, "noun3"))
return (noun[2]);
else if (!strcmp(object_string, "noun4"))
return (noun[3]);
else if (!strcmp(object_string, "player"))
return (player);
else if (!strcmp(object_string, "here"))
return (HERE);
else if (!strcmp(object_string, "self") ||
!strcmp(object_string, "this")) {
if (executing_function != nullptr && executing_function->self == 0) {
sprintf(error_buffer,
"ERROR: Reference to 'self' from global function \"%s\".^",
executing_function->name);
write_text(error_buffer);
} else
return (executing_function->self);
} else {
for (index = 1; index <= objects; index++) {
if (!strcmp(object_string, object[index]->label))
return (index);
}
}
return (-1);
}
long attribute_resolve(const char *attribute) {
long bit_mask;
if (!strcmp(attribute, "VISITED"))
return (VISITED);
else if (!strcmp(attribute, "DARK"))
return (DARK);
else if (!strcmp(attribute, "ON_WATER"))
return (ON_WATER);
else if (!strcmp(attribute, "UNDER_WATER"))
return (UNDER_WATER);
else if (!strcmp(attribute, "WITHOUT_AIR"))
return (WITHOUT_AIR);
else if (!strcmp(attribute, "OUTDOORS"))
return (OUTDOORS);
else if (!strcmp(attribute, "MID_AIR"))
return (MID_AIR);
else if (!strcmp(attribute, "TIGHT_ROPE"))
return (TIGHT_ROPE);
else if (!strcmp(attribute, "POLLUTED"))
return (POLLUTED);
else if (!strcmp(attribute, "SOLVED"))
return (SOLVED);
else if (!strcmp(attribute, "MID_WATER"))
return (MID_WATER);
else if (!strcmp(attribute, "DARKNESS")) {
bit_mask = DARKNESS;
if (check_light(HERE)) {
bit_mask = ~bit_mask;
object[HERE]->attributes = object[HERE]->attributes & bit_mask;
} else {
object[HERE]->attributes = object[HERE]->attributes | bit_mask;
}
return (DARKNESS);
} else if (!strcmp(attribute, "MAPPED"))
return (MAPPED);
else if (!strcmp(attribute, "KNOWN"))
return (KNOWN);
else if (!strcmp(attribute, "CLOSED"))
return (CLOSED);
else if (!strcmp(attribute, "LOCKED"))
return (LOCKED);
else if (!strcmp(attribute, "DEAD"))
return (DEAD);
else if (!strcmp(attribute, "IGNITABLE"))
return (IGNITABLE);
else if (!strcmp(attribute, "WORN"))
return (WORN);
else if (!strcmp(attribute, "CONCEALING"))
return (CONCEALING);
else if (!strcmp(attribute, "LUMINOUS"))
return (LUMINOUS);
else if (!strcmp(attribute, "WEARABLE"))
return (WEARABLE);
else if (!strcmp(attribute, "CLOSABLE"))
return (CLOSABLE);
else if (!strcmp(attribute, "LOCKABLE"))
return (LOCKABLE);
else if (!strcmp(attribute, "ANIMATE"))
return (ANIMATE);
else if (!strcmp(attribute, "LIQUID"))
return (LIQUID);
else if (!strcmp(attribute, "CONTAINER"))
return (CONTAINER);
else if (!strcmp(attribute, "SURFACE"))
return (SURFACE);
else if (!strcmp(attribute, "PLURAL"))
return (PLURAL);
else if (!strcmp(attribute, "FLAMMABLE"))
return (FLAMMABLE);
else if (!strcmp(attribute, "BURNING"))
return (BURNING);
else if (!strcmp(attribute, "LOCATION"))
return (LOCATION);
else if (!strcmp(attribute, "ON"))
return (ON);
else if (!strcmp(attribute, "DAMAGED"))
return (DAMAGED);
else if (!strcmp(attribute, "FEMALE"))
return (FEMALE);
else if (!strcmp(attribute, "POSSESSIVE"))
return (POSSESSIVE);
else if (!strcmp(attribute, "OUT_OF_REACH"))
return (OUT_OF_REACH);
else if (!strcmp(attribute, "TOUCHED"))
return (TOUCHED);
else if (!strcmp(attribute, "SCORED"))
return (SCORED);
else if (!strcmp(attribute, "SITTING"))
return (SITTING);
else if (!strcmp(attribute, "NPC"))
return (NPC);
else if (!strcmp(attribute, "DONE"))
return (DONE);
else if (!strcmp(attribute, "GAS"))
return (MAPPED);
else if (!strcmp(attribute, "NO_TAB"))
return (NO_TAB);
else if (!strcmp(attribute, "NOT_IMPORTANT"))
return (NOT_IMPORTANT);
else
return (0);
}
long user_attribute_resolve(const char *name) {
struct attribute_type *pointer = attribute_table;
if (pointer == nullptr)
return (0);
do {
if (!strcmp(name, pointer->name)) {
return (pointer->value);
} else
pointer = pointer->next_attribute;
} while (pointer != nullptr);
/* ATTRIBUTE NOT FOUND */
return (0);
}
} // End of namespace JACL
} // End of namespace Glk