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 #include "glk/jacl/version.h"
28 
29 namespace Glk {
30 namespace JACL {
31 
32 /* INDICATES THAT THE CURRENT '.j2' FILE BEING WORKED
33  * WITH IS ENCRYPTED */
34 int                 encrypted = FALSE;
35 
36 extern char         text_buffer[];
37 extern char         temp_buffer[];
38 extern char         prefix[];
39 extern char         error_buffer[];
40 extern const char   *word[];
41 extern int          quoted[];
42 extern int          punctuated[];
43 extern int          wp;
44 
45 extern schanid_t                sound_channel[];
46 
47 extern struct object_type       *object[];
48 extern struct integer_type      *integer_table;
49 extern struct integer_type      *integer[];
50 extern struct cinteger_type     *cinteger_table;
51 extern struct string_type       *string_table;
52 extern struct string_type       *cstring_table;
53 extern struct attribute_type    *attribute_table;
54 extern struct function_type     *function_table;
55 extern struct function_type     *executing_function;
56 extern struct command_type      *completion_list;
57 extern struct word_type         *grammar_table;
58 extern struct synonym_type      *synonym_table;
59 extern struct filter_type       *filter_table;
60 
61 
62 struct string_type *current_string = NULL;
63 struct integer_type *current_integer = NULL;
64 struct integer_type *last_system_integer = NULL;
65 
66 extern struct string_type *current_cstring;
67 extern struct cinteger_type *current_cinteger;
68 
69 extern strid_t                  game_stream;
70 
71 extern int                      objects;
72 extern int                      integers;
73 extern int                      functions;
74 extern int                      strings;
75 extern int                      player;
76 
77 extern int                      it;
78 extern int                      them[];
79 extern int                      her;
80 extern int                      him;
81 extern int                      parent;
82 
83 extern int                      noun[];
84 
85 int                             value_resolved;
86 
read_gamefile()87 void read_gamefile() {
88 	int             index,
89 	                counter,
90 	                errors;
91 	int             result;
92 	int             location_count = 0;
93 	int             object_count = 0;
94 	int             line = 0;
95 	int             self_parent = 0;
96 
97 	long            start_of_file = 0;
98 	long            bit_mask;
99 
100 	filter_type *current_filter = NULL;
101 	filter_type *new_filter = NULL;
102 	attribute_type *current_attribute = NULL;
103 	attribute_type *new_attribute = NULL;
104 	cinteger_type *resolved_cinteger = NULL;
105 	synonym_type *current_synonym = NULL;
106 	synonym_type *new_synonym = NULL;
107 	function_type *current_function = NULL;
108 	name_type *current_name = NULL;
109 
110 	char            function_name[81];
111 
112 	// CREATE SOME SYSTEM VARIABLES
113 
114 	// THIS IS USED BY JACL FUNCTIONS TO PASS STRING VALUES BACK
115 	// TO THE INTERPRETER AS JACL FUNCTION CAN ONLY RETURN
116 	// AN INTEGER
117 	create_string("return_value", "");
118 
119 	create_cstring("function_name", "JACL*Internal");
120 
121 	// THESE ARE THE FIELDS FOR THE CSV PARSER
122 	create_cstring("field", "field0");
123 	create_cstring("field", "field1");
124 	create_cstring("field", "field2");
125 	create_cstring("field", "field3");
126 	create_cstring("field", "field4");
127 	create_cstring("field", "field5");
128 	create_cstring("field", "field6");
129 	create_cstring("field", "field7");
130 	create_cstring("field", "field8");
131 	create_cstring("field", "field9");
132 	create_cstring("field", "field10");
133 	create_cstring("field", "field11");
134 	create_cstring("field", "field12");
135 	create_cstring("field", "field13");
136 	create_cstring("field", "field14");
137 	create_cstring("field", "field15");
138 	create_cstring("field", "field16");
139 	create_cstring("field", "field17");
140 	create_cstring("field", "field18");
141 	create_cstring("field", "field19");
142 
143 	create_cinteger("field_count", 0);
144 
145 	create_integer("compass", 0);
146 	// START AT -1 AS TIME PASSES BEFORE THE FIRST PROMPT
147 	create_integer("total_moves", -1);
148 	create_integer("time", TRUE);
149 	create_integer("score", 0);
150 	create_integer("display_mode", 0);
151 	create_integer("internal_version", J_VERSION);
152 	create_integer("max_rand", 100);
153 	create_integer("destination", 0);
154 	create_integer("interrupted", 0);
155 	create_integer("debug", 0);
156 	create_integer("graphics_enabled", 0);
157 	create_integer("sound_enabled", 0);
158 	create_integer("timer_enabled", 0);
159 	create_integer("multi_prefix", 0);
160 	create_integer("notify", 1);
161 	create_integer("debug", 0);
162 	create_integer("linebreaks", 1);
163 
164 	/* STORE THIS SO THE SECOND PASS KNOWS WHERE TO START
165 	 * SETTING VALUES FROM (EVERYTHING BEFORE THIS IN THE
166 	 * VARIABLE TABLE IS A SYSTEM VARIABLE */
167 	last_system_integer = current_integer;
168 
169 	/* CREATE SOME SYSTEM CONSTANTS */
170 	create_cinteger("graphics_supported", 0);
171 	create_cinteger("sound_supported", 0);
172 	create_cinteger("timer_supported", 0);
173 	create_cinteger("GLK", 0);
174 	create_cinteger("CGI", 1);
175 	create_cinteger("NDS", 2);
176 
177 	create_cinteger("interpreter", 0);
178 
179 	/* TEST FOR AVAILABLE FUNCTIONALITY BEFORE EXECUTING ANY JACL CODE */
180 
181 	GRAPHICS_SUPPORTED->value = (int)g_vm->glk_gestalt(gestalt_Graphics, 0);
182 	GRAPHICS_ENABLED->value = (int)g_vm->glk_gestalt(gestalt_Graphics, 0);
183 	SOUND_SUPPORTED->value = (int)g_vm->glk_gestalt(gestalt_Sound, 0);
184 	SOUND_ENABLED->value = (int)g_vm->glk_gestalt(gestalt_Sound, 0);
185 	TIMER_SUPPORTED->value = (int)g_vm->glk_gestalt(gestalt_Timer, 0);
186 	TIMER_ENABLED->value = (int)g_vm->glk_gestalt(gestalt_Timer, 0);
187 
188 	create_cinteger("true", 1);
189 	create_cinteger("false", 0);
190 	create_cinteger("null", 0);
191 	create_cinteger("nowhere", 0);
192 	create_cinteger("heavy", HEAVY);
193 	create_cinteger("scenery", SCENERY);
194 	create_cinteger("north", NORTH_DIR);
195 	create_cinteger("south", SOUTH_DIR);
196 	create_cinteger("east", EAST_DIR);
197 	create_cinteger("west", WEST_DIR);
198 	create_cinteger("northeast", NORTHEAST_DIR);
199 	create_cinteger("northwest", NORTHWEST_DIR);
200 	create_cinteger("southeast", SOUTHEAST_DIR);
201 	create_cinteger("southwest", SOUTHWEST_DIR);
202 	create_cinteger("up", UP_DIR);
203 	create_cinteger("down", DOWN_DIR);
204 	create_cinteger("in", IN_DIR);
205 	create_cinteger("out", OUT_DIR);
206 	create_cinteger("parent", 0);
207 	create_cinteger("quantity", 1);
208 	create_cinteger("capacity", 1);
209 	create_cinteger("mass", 2);
210 	create_cinteger("bearing", 3);
211 	create_cinteger("velocity", 4);
212 	create_cinteger("next", 5);
213 	create_cinteger("previous", 6);
214 	create_cinteger("child", 7);
215 	create_cinteger("index", 8);
216 	create_cinteger("status", 9);
217 	create_cinteger("state", 10);
218 	create_cinteger("counter", 11);
219 	create_cinteger("points", 12);
220 	create_cinteger("class", 13);
221 	create_cinteger("x", 14);
222 	create_cinteger("y", 15);
223 	create_cinteger("volume", 100);
224 	create_cinteger("volume", 100);
225 	create_cinteger("volume", 100);
226 	create_cinteger("volume", 100);
227 	create_cinteger("volume", 100);
228 	create_cinteger("volume", 100);
229 	create_cinteger("volume", 100);
230 	create_cinteger("volume", 100);
231 	create_cinteger("timer", 500);
232 
233 	set_defaults();
234 
235 	/* CREATE A DUMMY FUNCTION TO BE USED WHEN AN ERROR MESSAGE
236 	   IS PRINTED AS A RESULT OF CODE CALLED BY THE INTERPRETER */
237 	if ((function_table = (struct function_type *)
238 	                      malloc(sizeof(struct function_type))) == NULL)
239 		outofmem();
240 	else {
241 		current_function = function_table;
242 		strcpy(current_function->name, "JACL*Internal");
243 		current_function->position = 0;
244 		current_function->self = 0;
245 		current_function->call_count = 0;
246 		current_function->call_count_backup = 0;
247 		current_function->next_function = NULL;
248 	}
249 
250 	executing_function = function_table;
251 
252 	errors = 0;
253 	objects = 0;
254 	integers = 0;
255 	functions = 0;
256 	strings = 0;
257 
258 	g_vm->glk_stream_set_position(game_stream, start_of_file, seekmode_Start);
259 	result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
260 
261 	line++;
262 
263 	if (!encrypted && strstr(text_buffer, "#encrypted")) {
264 		encrypted = TRUE;
265 
266 		result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
267 		line++;
268 	}
269 
270 	if (encrypted) jacl_decrypt(text_buffer);
271 
272 	while (result) {
273 		encapsulate();
274 		if (word[0] == NULL);
275 		else if (text_buffer[0] == '{') {
276 			while (result) {
277 				result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
278 				line++;
279 
280 				if (!encrypted && strstr(text_buffer, "#encrypted")) {
281 					encrypted = TRUE;
282 					result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
283 					line++;
284 				}
285 				if (encrypted) jacl_decrypt(text_buffer);
286 				if (text_buffer[0] == '}')
287 					break;
288 			}
289 		} else {
290 			if (!strcmp(word[0], "grammar")) {
291 				if (word[++wp] == NULL) {
292 					noproperr(line);
293 					errors++;
294 				} else {
295 					if (grammar_table == NULL) {
296 						if ((grammar_table = (struct word_type *)
297 						                     malloc(sizeof(struct word_type))) == NULL)
298 							outofmem();
299 						else {
300 							strncpy(grammar_table->word, word[wp], 40);
301 							grammar_table->word[40] = 0;
302 							grammar_table->next_sibling = NULL;
303 							grammar_table->first_child = NULL;
304 							build_grammar_table(grammar_table);
305 						}
306 					} else
307 						build_grammar_table(grammar_table);
308 				}
309 			} else if (!strcmp(word[0], "object")
310 			           || !strcmp(word[0], "location")) {
311 				if (word[1] == NULL) {
312 					noproperr(line);
313 					errors++;
314 				} else if (legal_label_check(word[1], line, OBJ_TYPE)) {
315 					errors++;
316 				} else {
317 					objects++;
318 
319 					if (objects == MAX_OBJECTS) {
320 						log_error(MAXIMUM_EXCEEDED, PLUS_STDERR);
321 						terminate(47);
322 						return;
323 					} else {
324 						if ((object[objects] = (struct object_type *)
325 						                       malloc(sizeof(struct object_type))) == NULL)
326 							outofmem();
327 
328 						strncpy(object[objects]->label, word[1], 40);
329 
330 						object[objects]->label[40] = 0;
331 						object[objects]->first_plural = NULL;
332 
333 						strcpy(object[objects]->described, object[objects]->label);
334 						strcpy(object[objects]->inventory, object[objects]->label);
335 						strcpy(object[objects]->article, "the");
336 						strcpy(object[objects]->definite, "the");
337 						object[objects]->attributes = FALSE;
338 						object[objects]->user_attributes = FALSE;
339 
340 						for (counter = 0; counter < 16; counter++)
341 							object[objects]->integer[counter] = 0;
342 					}
343 					object[objects]->nosave = FALSE;
344 				}
345 			} else if (!strcmp(word[0], "synonym")) {
346 				if (word[++wp] == NULL) {
347 					noproperr(line);
348 					errors++;
349 				} else {
350 					if ((new_synonym = (struct synonym_type *)
351 					                   malloc(sizeof(struct synonym_type))) == NULL)
352 						outofmem();
353 					else {
354 						if (synonym_table == NULL) {
355 							synonym_table = new_synonym;
356 						} else {
357 							current_synonym->next_synonym = new_synonym;
358 						}
359 					}
360 					current_synonym = new_synonym;
361 					strncpy(current_synonym->original, word[wp], 40);
362 					current_synonym->original[40] = 0;
363 					if (word[++wp] == NULL) {
364 						noproperr(line);
365 						errors++;
366 					} else {
367 						strncpy(current_synonym->standard, word[wp], 40);
368 						current_synonym->standard[40] = 0;
369 					}
370 					current_synonym->next_synonym = NULL;
371 				}
372 			} else if (!strcmp(word[0], "parameter")) {
373 #ifdef UNUSED
374 				if (word[2] == NULL) {
375 					noproperr(line);
376 					errors++;
377 				} else {
378 					if ((new_parameter = (struct parameter_type *)
379 					                     malloc(sizeof(struct parameter_type))) == NULL)
380 						outofmem();
381 					else {
382 						if (parameter_table == NULL) {
383 							parameter_table = new_parameter;
384 						} else {
385 							current_parameter->next_parameter =
386 							    new_parameter;
387 						}
388 						current_parameter = new_parameter;
389 						strncpy(current_parameter->name, word[1], 40);
390 						current_parameter->name[40] = 0;
391 						strncpy(current_parameter->container, word[2], 40);
392 						current_parameter->container[40] = 0;
393 						current_parameter->next_parameter = NULL;
394 					}
395 
396 					if (word[4] != NULL) {
397 						if (validate(word[3]))
398 							current_parameter->low = atoi(word[3]);
399 						else
400 							current_parameter->low = -65535;
401 
402 						if (validate(word[4]))
403 							current_parameter->high = atoi(word[4]);
404 						else
405 							current_parameter->high = 65535;
406 					} else {
407 						current_parameter->low = -65535;
408 						current_parameter->high = 65535;
409 					}
410 
411 				}
412 #else
413 				warning("parameter");
414 #endif
415 			} else if (!strcmp(word[0], "constant")) {
416 				if (word[2] == NULL) {
417 					noproperr(line);
418 					errors++;
419 				} else {
420 					/* CHECK IF MORE THAN ONE VALUE IS SUPPLIED AND CREATE
421 					   ADDITIONAL CONSTANTS IF REQUIRED */
422 					index = 2;
423 
424 					while (word[index] != NULL && index < MAX_WORDS) {
425 						if (quoted[index] == TRUE || !validate(word[index])) {
426 							if (legal_label_check(word[1], line, CSTR_TYPE)) {
427 								errors++;
428 							} else {
429 								create_cstring(word[1], word[index]);
430 							}
431 						} else {
432 							if (legal_label_check(word[1], line, CINT_TYPE)) {
433 								errors++;
434 							} else {
435 								create_cinteger(word[1], value_of(word[index])/*, FALSE */);
436 								if (!value_resolved) {
437 									unkvalerr(line, index);
438 									errors++;
439 								}
440 							}
441 						}
442 						index++;
443 					}
444 				}
445 			} else if (!strcmp(word[0], "attribute")) {
446 				if (word[1] == NULL) {
447 					noproperr(line);
448 					errors++;
449 				} else if (legal_label_check(word[1], line, ATT_TYPE)) {
450 					errors++;
451 				} else if (current_attribute != NULL && current_attribute->value == 1073741824) {
452 					maxatterr(line, 1);
453 					errors++;
454 				} else {
455 					if ((new_attribute = (struct attribute_type *)
456 					                     malloc(sizeof(struct attribute_type))) == NULL)
457 						outofmem();
458 					else {
459 						if (attribute_table == NULL) {
460 							attribute_table = new_attribute;
461 							new_attribute->value = 1;
462 						} else {
463 							current_attribute->next_attribute = new_attribute;
464 							new_attribute->value = current_attribute->value * 2;
465 						}
466 						current_attribute = new_attribute;
467 						strncpy(current_attribute->name, word[1], 40);
468 						current_attribute->name[40] = 0;
469 						current_attribute->next_attribute = NULL;
470 					}
471 
472 					/* CHECK IF MORE THAN ONE VALUE IS SUPPLIED AND CREATE
473 					   ADDITIONAL CONSTANTS IF REQUIRED */
474 					index = 2;
475 					while (word[index] != NULL && index < MAX_WORDS) {
476 						if (legal_label_check(word[index], line, ATT_TYPE)) {
477 							errors++;
478 						} else if (current_attribute != NULL && current_attribute->value == 1073741824) {
479 							maxatterr(line, index);
480 							errors++;
481 						} else {
482 							if ((new_attribute = (struct attribute_type *)
483 							                     malloc(sizeof(struct attribute_type))) == NULL)
484 								outofmem();
485 							else {
486 								current_attribute->next_attribute = new_attribute;
487 								new_attribute->value = current_attribute->value * 2;
488 								current_attribute = new_attribute;
489 								strncpy(current_attribute->name, word[index], 40);
490 								current_attribute->name[40] = 0;
491 								current_attribute->next_attribute = NULL;
492 							}
493 						}
494 						index++;
495 					}
496 				}
497 			} else if (!strcmp(word[0], "string")) {
498 				if (word[1] == NULL) {
499 					noproperr(line);
500 					errors++;
501 				} else if (legal_label_check(word[1], line, STR_TYPE)) {
502 					errors++;
503 				} else {
504 					if (word[2] == NULL) {
505 						create_string(word[1], "");
506 					} else {
507 						create_string(word[1], word[2]);
508 						index = 3;
509 						while (word[index] != NULL && index < MAX_WORDS) {
510 							create_string(word[1], word[index]);
511 							index++;
512 						}
513 					}
514 				}
515 			} else if (!strcmp(word[0], "filter")) {
516 				if (word[++wp] == NULL) {
517 					noproperr(line);
518 					errors++;
519 				} else {
520 					if ((new_filter = (struct filter_type *)
521 					                  malloc(sizeof(struct filter_type))) == NULL)
522 						outofmem();
523 					else {
524 						if (filter_table == NULL) {
525 							filter_table = new_filter;
526 						} else {
527 							current_filter->next_filter = new_filter;
528 						}
529 						current_filter = new_filter;
530 						strncpy(current_filter->word, word[wp], 40);
531 						current_filter->word[40] = 0;
532 						current_filter->next_filter = NULL;
533 					}
534 				}
535 			} else if (!strcmp(word[0], "string_array")) {
536 				if (word[2] == NULL) {
537 					noproperr(line);
538 					errors++;
539 				} else if (legal_label_check(word[1], line, STR_TYPE)) {
540 					errors++;
541 				} else {
542 					int x;
543 
544 					index = value_of(word[2], FALSE);
545 					if (!value_resolved) {
546 						unkvalerr(line, 2);
547 						errors++;
548 					}
549 
550 					for (x = 0; x < index; x++) {
551 						create_string(word[1], word[3]);
552 					}
553 				}
554 			} else if (!strcmp(word[0], "integer_array")) {
555 				if (word[2] == NULL) {
556 					noproperr(line);
557 					errors++;
558 				} else if (legal_label_check(word[1], line, INT_TYPE)) {
559 					errors++;
560 				} else {
561 					int default_value, x;
562 
563 					if (word[3] != NULL) {
564 						default_value = value_of(word[3], FALSE);
565 						if (!value_resolved) {
566 							unkvalerr(line, 3);
567 							errors++;
568 						}
569 					} else {
570 						default_value = 0;
571 					}
572 
573 					/* THIS IS THE NUMBER OF ARRAY ELEMENTS TO MAKE */
574 					index = value_of(word[2], FALSE);
575 					if (!value_resolved) {
576 						unkvalerr(line, 2);
577 						errors++;
578 					}
579 
580 					for (x = 0; x < index; x++) {
581 						create_integer(word[1], default_value);
582 					}
583 				}
584 			} else if (!strcmp(word[0], "integer")) {
585 				if (word[1] == NULL) {
586 					noproperr(line);
587 					errors++;
588 				} else if (legal_label_check(word[1], line, INT_TYPE)) {
589 					errors++;
590 				} else {
591 					create_integer(word[1], 0);
592 
593 					/* CHECK IF MORE THAN ONE VALUE IS SUPPLIED AND CREATE
594 					   ADDITIONAL VARIABLES IF REQUIRED */
595 					index = 3;
596 					while (word[index] != NULL && index < MAX_WORDS) {
597 						create_integer(word[1], 0);
598 						index++;
599 					}
600 				}
601 			}
602 		}
603 
604 		result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
605 		line++;
606 
607 		if (!encrypted && strstr(text_buffer, "#encrypted")) {
608 			encrypted = TRUE;
609 			result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
610 			line++;
611 		}
612 		if (encrypted) jacl_decrypt(text_buffer);
613 	}
614 
615 	if (errors) {
616 		totalerrs(errors);
617 		terminate(48);
618 		return;
619 	}
620 
621 	/*************************************************************************
622 	 * START OF SECOND PASS                                                  *
623 	 *************************************************************************/
624 
625 	/* IF NO SIZE IS SPECIFIED FOR THE STATUS WINDOW, SET IT TO 1 */
626 	if (integer_resolve("status_window") == NULL) {
627 		create_integer("status_window", 1);
628 	}
629 
630 	/* IF NO STRING IS SPECIFIED FOR THE COMMAND PROMPT, SET IT TO "^> " */
631 	if (string_resolve("command_prompt") == NULL) {
632 		create_string("command_prompt", "^> ");
633 	}
634 
635 	/* IF NO STRING IS SPECIFIED FOR THE GAME_TITLE, SET IT TO THE FILENAME */
636 	if (cstring_resolve("game_title") == NULL) {
637 		create_cstring("game_title", prefix);
638 	}
639 
640 	create_language_constants();
641 
642 	/* MUST RE-DETERMINE THE POINT IN THE GAME FILE THAT ENCRYPTION STARTS */
643 	encrypted = FALSE;
644 
645 	/* SET CURRENT VARIABLE TO POINT TO THE FIRST USER VARIABLE THAT WAS
646 	 * CREATED AFTER THE SYSTEM VARIABLES */
647 	current_integer = last_system_integer;
648 
649 	line = 0;
650 	g_vm->glk_stream_set_position(game_stream, start_of_file, seekmode_Start);
651 	result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
652 
653 	line++;
654 
655 	if (!encrypted && strstr(text_buffer, "#encrypted")) {
656 		encrypted = TRUE;
657 		result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
658 		line++;
659 	}
660 	if (encrypted) jacl_decrypt(text_buffer);
661 
662 	while (result) {
663 		encapsulate();
664 		if (word[0] == NULL);
665 		else if (text_buffer[0] == '{') {
666 			word[wp]++;         /* MOVE THE START OF THE FIRST WORD ONLY
667 								 * TO PAST THE '{'. */
668 			if (word[wp][0] == 0) {
669 				nofnamerr(line);
670 				errors++;
671 			} else {
672 				while (word[wp] != NULL && wp < MAX_WORDS) {
673 					if (word[wp][0] == '+') {
674 						strncpy(function_name, word[wp], 80);
675 						function_name[80] = 0;
676 						self_parent = 0;
677 					} else if (word[wp][0] == '*') {
678 						const char *last_underscore = (char *)NULL;
679 
680 						/* ALLOW MANUAL NAMING OF ASSOCIATED FUNCTIONS */
681 						/* TO GIVE CLASS-LIKE BEHAVIOR */
682 						strncpy(function_name, word[wp] + 1, 80);
683 						function_name[80] = 0;
684 
685 						/* LOOK FOR THE FINAL UNDERSCORE AND SEE IF */
686 						/* IT IS FOLLOWED BY AN OBJECT LABEL */
687 						last_underscore = strrchr(word[wp], '_');
688 						if (last_underscore != NULL) {
689 							self_parent = object_resolve(last_underscore + 1);
690 						} else {
691 							self_parent = 0;
692 						}
693 					} else if (object_count == 0) {
694 						nongloberr(line);
695 						errors++;
696 					} else {
697 						strncpy(function_name, word[wp], 59);
698 						strcat(function_name, "_");
699 						strcat(function_name, object[object_count]->label);
700 						self_parent = object_count;
701 					}
702 					if (function_table == NULL) {
703 						if ((function_table = (struct function_type *)
704 						                      malloc(sizeof(struct function_type))) == NULL)
705 							outofmem();
706 						else {
707 							// STORE THE NUMBER OF FUNCTION DEFINED TO
708 							// HELP VALIDATE SAVED GAME FILES
709 							functions++;
710 
711 							current_function = function_table;
712 							strcpy(current_function->name, function_name);
713 
714 							current_function->position = g_vm->glk_stream_get_position(game_stream);
715 							current_function->call_count = 0;
716 							current_function->call_count_backup = 0;
717 							current_function->self = self_parent;
718 							current_function->next_function = NULL;
719 						}
720 					} else {
721 						if ((current_function->next_function =
722 						            (struct function_type *)
723 						            malloc(sizeof(struct function_type))) == NULL)
724 							outofmem();
725 						else {
726 							// STORE THE NUMBER OF FUNCTION DEFINED TO
727 							// HELP VALIDATE SAVED GAME FILES
728 							functions++;
729 
730 							current_function = current_function->next_function;
731 							strcpy(current_function->name, function_name);
732 
733 							current_function->position = g_vm->glk_stream_get_position(game_stream);
734 							current_function->call_count = 0;
735 							current_function->call_count_backup = 0;
736 							current_function->self = self_parent;
737 							current_function->next_function = NULL;
738 						}
739 					}
740 					wp++;
741 				}
742 			}
743 
744 			while (result) {
745 				result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
746 				line++;
747 
748 				if (!encrypted && strstr(text_buffer, "#encrypted")) {
749 					encrypted = TRUE;
750 					result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
751 					line++;
752 				}
753 				if (encrypted) jacl_decrypt(text_buffer);
754 				if (text_buffer[0] == '}')
755 					break;
756 			}
757 		}
758 		else if (!strcmp(word[0], "string_array")) {
759 		} else if (!strcmp(word[0], "integer_array")) {
760 			if (word[2] == NULL) {
761 				noproperr(line);
762 				errors++;
763 			} else {
764 				int x;
765 
766 				/* THIS IS THE NUMBER OF ARRAY ELEMENTS TO MAKE */
767 				index = value_of(word[2], FALSE);
768 				if (!value_resolved) {
769 					unkvalerr(line, 2);
770 					errors++;
771 				}
772 
773 				for (x = 0; x < index; x++) {
774 					current_integer = current_integer->next_integer;
775 				}
776 			}
777 		} else if (!strcmp(word[0], "integer")) {
778 			if (word[2] != NULL) {
779 				current_integer = current_integer->next_integer;
780 				current_integer->value = value_of(word[2], FALSE);
781 				if (!value_resolved) {
782 					unkvalerr(line, 2);
783 					errors++;
784 				}
785 				index = 3;
786 				while (word[index] != NULL && index < MAX_WORDS) {
787 					current_integer = current_integer->next_integer;
788 					current_integer->value = value_of(word[index], FALSE);
789 					if (!value_resolved) {
790 						unkvalerr(line, index);
791 						errors++;
792 					}
793 					index++;
794 				}
795 			} else {
796 				current_integer = current_integer->next_integer;
797 				current_integer->value = FALSE;
798 			}
799 
800 			/* CONSUME ALL THESE KEYWORDS TO AVOID AN UNKNOWN KEYWORD */
801 			/* ERROR DURING THE SECOND PASS (ALL WORK DONE IN FIRST PASS) */
802 		} else if (!strcmp(word[0], "constant"));
803 		else if (!strcmp(word[0], "string"));
804 		else if (!strcmp(word[0], "attribute"));
805 		else if (!strcmp(word[0], "parameter"));
806 		else if (!strcmp(word[0], "synonym"));
807 		else if (!strcmp(word[0], "grammar"));
808 		else if (!strcmp(word[0], "filter"));
809 		else if (!strcmp(word[0], "has")) {
810 			if (word[1] == NULL) {
811 				noproperr(line);
812 				errors++;
813 			} else if (object_count == 0) {
814 				noobjerr(line);
815 				errors++;
816 			} else {
817 				for (index = 1; word[index] != NULL && index < MAX_WORDS; index++) {
818 					if ((bit_mask = attribute_resolve(word[index]))) {
819 						object[object_count]->attributes = object[object_count]->attributes | bit_mask;
820 					} else if ((bit_mask = user_attribute_resolve(word[index]))) {
821 						object[object_count]->user_attributes = object[object_count]->user_attributes | bit_mask;
822 					} else {
823 						unkatterr(line, index);
824 						errors++;
825 					}
826 				}
827 			}
828 		} else if (!strcmp(word[0], "object")
829 		           || !strcmp(word[0], "location")) {
830 			object_count++;
831 
832 			if (!strcmp(word[0], "object")) {
833 				object[object_count]->MASS = SCENERY;
834 				if (location_count == 0)
835 					object[object_count]->PARENT = 0;
836 				else
837 					object[object_count]->PARENT = location_count;
838 			} else {
839 				location_count = object_count;
840 				object[object_count]->PARENT = 0;
841 				object[object_count]->attributes =
842 				    object[object_count]->attributes | LOCATION;
843 			}
844 
845 
846 			if ((object[object_count]->first_name =
847 			            (struct name_type *) malloc(sizeof(struct name_type)))
848 			        == NULL)
849 				outofmem();
850 			else {
851 				current_name = object[object_count]->first_name;
852 				if (word[2] != NULL) {
853 					strncpy(current_name->name, word[2], 40);
854 				} else {
855 					strncpy(current_name->name, object[object_count]->label, 40);
856 				}
857 				current_name->name[40] = 0;
858 				current_name->next_name = NULL;
859 			}
860 
861 			wp = 3;
862 
863 			while (word[wp] != NULL && wp < MAX_WORDS) {
864 				if ((current_name->next_name = (struct name_type *)
865 				                               malloc(sizeof(struct name_type))) == NULL)
866 					outofmem();
867 				else {
868 					current_name = current_name->next_name;
869 					strncpy(current_name->name, word[wp], 40);
870 					current_name->name[40] = 0;
871 					current_name->next_name = NULL;
872 				}
873 				wp++;
874 			}
875 		} else if (!strcmp(word[0], "plural")) {
876 			if (word[1] == NULL) {
877 				noproperr(line);
878 				errors++;
879 			} else {
880 				if ((object[object_count]->first_plural =
881 				            (struct name_type *) malloc(sizeof(struct name_type)))
882 				        == NULL)
883 					outofmem();
884 				else {
885 					current_name = object[object_count]->first_plural;
886 					strncpy(current_name->name, word[1], 40);
887 					current_name->name[40] = 0;
888 					current_name->next_name = NULL;
889 				}
890 
891 				wp = 2;
892 
893 				while (word[wp] != NULL && wp < MAX_WORDS) {
894 					if ((current_name->next_name = (struct name_type *)
895 					                               malloc(sizeof(struct name_type))) == NULL)
896 						outofmem();
897 					else {
898 						current_name = current_name->next_name;
899 						strncpy(current_name->name, word[wp], 40);
900 						current_name->name[40] = 0;
901 						current_name->next_name = NULL;
902 					}
903 					wp++;
904 				}
905 			}
906 		} else if (!strcmp(word[0], "static")) {
907 			if (object_count == 0) {
908 				noobjerr(line);
909 				errors++;
910 			} else
911 				object[object_count]->nosave = TRUE;
912 		} else if (!strcmp(word[0], "player")) {
913 			if (object_count == 0) {
914 				noobjerr(line);
915 				errors++;
916 			} else
917 				player = object_count;
918 		} else if (!strcmp(word[0], "short")) {
919 			if (word[2] == NULL) {
920 				noproperr(line);
921 				errors++;
922 			} else if (object_count == 0) {
923 				noobjerr(line);
924 				errors++;
925 			} else {
926 				strncpy(object[object_count]->article, word[1], 10);
927 				object[object_count]->article[10] = 0;
928 				strncpy(object[object_count]->inventory, word[2], 40);
929 				object[object_count]->inventory[40] = 0;
930 			}
931 		} else if (!strcmp(word[0], "definite")) {
932 			if (word[1] == NULL) {
933 				noproperr(line);
934 				errors++;
935 			} else if (object_count == 0) {
936 				noobjerr(line);
937 				errors++;
938 			} else {
939 				strncpy(object[object_count]->definite, word[1], 10);
940 				object[object_count]->definite[10] = 0;
941 			}
942 		} else if (!strcmp(word[0], "long")) {
943 			if (word[1] == NULL) {
944 				noproperr(line);
945 				errors++;
946 			} else if (object_count == 0) {
947 				noobjerr(line);
948 				errors++;
949 			} else {
950 				strncpy(object[object_count]->described, word[1], 80);
951 				object[object_count]->described[80] = 0;
952 			}
953 		} else if ((resolved_cinteger = cinteger_resolve(word[0])) != NULL) {
954 			index = resolved_cinteger->value;
955 			if (word[1] == NULL) {
956 				noproperr(line);
957 				errors++;
958 			} else if (object_count == 0) {
959 				noobjerr(line);
960 				errors++;
961 			} else if (!strcmp(word[1], "here")) {
962 				object[object_count]->integer[index] = location_count;
963 			} else {
964 				object[object_count]->integer[index] = value_of(word[1], FALSE);
965 				if (!value_resolved) {
966 					unkvalerr(line, 1);
967 					errors++;
968 				}
969 			}
970 		} else {
971 			unkkeyerr(line, 0);
972 			errors++;
973 		}
974 
975 		result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
976 		line++;
977 
978 		if (!encrypted && strstr(text_buffer, "#encrypted")) {
979 			encrypted = TRUE;
980 			result = glk_get_bin_line_stream(game_stream, text_buffer, (glui32) 1024);
981 			line++;
982 		}
983 		if (encrypted) jacl_decrypt(text_buffer);
984 	}
985 
986 	/* CREATE THE CONSTANT THE RECORDS THE TOTAL NUMBER OF OBJECTS */
987 	create_cinteger("objects", objects);
988 
989 	/* LOOP THROUGH ALL THE OBJECTS AND CALL THEIR CONSTRUCTORS
990 	for (index = 1; index <= objects; index++) {
991 	    strcpy (function_name, "constructor_");
992 	    strcat (function_name, object[index]->label);
993 	    execute (function_name);
994 	}
995 	*/
996 
997 	if (errors) {
998 		totalerrs(errors);
999 		terminate(48);
1000 		return;
1001 	}
1002 }
1003 
build_grammar_table(struct word_type * pointer)1004 void build_grammar_table(struct word_type *pointer) {
1005 	do {
1006 		if (!strcmp(word[wp], pointer->word)) {
1007 			if (pointer->first_child == NULL && word[wp + 1] != NULL) {
1008 				if ((pointer->first_child = (struct word_type *)
1009 				                            malloc(sizeof(struct word_type)))
1010 				        == NULL)
1011 					outofmem();
1012 				else {
1013 					pointer = pointer->first_child;
1014 					strncpy(pointer->word, word[++wp], 40);
1015 					pointer->word[40] = 0;
1016 					pointer->next_sibling = NULL;
1017 					pointer->first_child = NULL;
1018 				}
1019 			} else {
1020 				pointer = pointer->first_child;
1021 				wp++;
1022 			}
1023 		} else {
1024 			if (pointer->next_sibling == NULL) {
1025 				if ((pointer->next_sibling = (struct word_type *)
1026 				                             malloc(sizeof(struct word_type)))
1027 				        == NULL)
1028 					outofmem();
1029 				else {
1030 					pointer = pointer->next_sibling;
1031 					strncpy(pointer->word, word[wp], 40);
1032 					pointer->word[40] = 0;
1033 					pointer->next_sibling = NULL;
1034 					pointer->first_child = NULL;
1035 				}
1036 			} else
1037 				pointer = pointer->next_sibling;
1038 		}
1039 	} while (word[wp] != NULL && wp < MAX_WORDS);
1040 }
1041 
legal_label_check(const char * label_word,int line,int type)1042 int legal_label_check(const char *label_word, int line, int type) {
1043 	struct integer_type *integer_pointer = integer_table;
1044 	struct cinteger_type *cinteger_pointer = cinteger_table;
1045 	struct string_type *string_pointer = string_table;
1046 	struct string_type *cstring_pointer = cstring_table;
1047 	struct attribute_type *attribute_pointer = attribute_table;
1048 
1049 	int index;
1050 
1051 	if (!strcmp(label_word, "here") ||
1052 	        !strcmp(label_word, "player") ||
1053 	        !strcmp(label_word, "integer") ||
1054 	        !strcmp(label_word, "arg") ||
1055 	        !strcmp(label_word, "string_arg") ||
1056 	        !strcmp(label_word, "arg") ||
1057 	        !strcmp(label_word, "$label_word") ||
1058 	        !strcmp(label_word, "self") ||
1059 	        !strcmp(label_word, "this") ||
1060 	        !strcmp(label_word, "noun1") ||
1061 	        !strcmp(label_word, "noun2") ||
1062 	        !strcmp(label_word, "noun3") ||
1063 	        !strcmp(label_word, "noun4") ||
1064 	        !strcmp(label_word, "objects") ||
1065 	        validate(label_word)) {
1066 		sprintf(error_buffer, ILLEGAL_LABEL, line, label_word);
1067 		log_error(error_buffer, PLUS_STDERR);
1068 
1069 		return (TRUE);
1070 	}
1071 
1072 	if (type == CSTR_TYPE) {
1073 		if (!strcmp(label_word, "command_prompt")) {
1074 			sprintf(error_buffer, USED_LABEL_STR, line, label_word);
1075 			log_error(error_buffer, PLUS_STDERR);
1076 
1077 			return (TRUE);
1078 		}
1079 	}
1080 
1081 	while (integer_pointer != NULL && type != INT_TYPE) {
1082 		if (!strcmp(label_word, integer_pointer->name)) {
1083 			sprintf(error_buffer, USED_LABEL_INT, line, label_word);
1084 			log_error(error_buffer, PLUS_STDERR);
1085 
1086 			return (TRUE);
1087 		} else
1088 			integer_pointer = integer_pointer->next_integer;
1089 	}
1090 
1091 
1092 	while (cinteger_pointer != NULL && type != CINT_TYPE) {
1093 		if (!strcmp(label_word, cinteger_pointer->name)) {
1094 			sprintf(error_buffer, USED_LABEL_CINT, line, label_word);
1095 			log_error(error_buffer, PLUS_STDERR);
1096 
1097 			return (TRUE);
1098 		} else
1099 			cinteger_pointer = cinteger_pointer->next_cinteger;
1100 	}
1101 
1102 	while (string_pointer != NULL && type != STR_TYPE) {
1103 		if (!strcmp(label_word, string_pointer->name)) {
1104 			sprintf(error_buffer, USED_LABEL_STR, line, label_word);
1105 			log_error(error_buffer, PLUS_STDERR);
1106 
1107 			return (TRUE);
1108 		} else
1109 			string_pointer = string_pointer->next_string;
1110 	}
1111 
1112 	while (cstring_pointer != NULL && type != CSTR_TYPE) {
1113 		if (!strcmp(label_word, cstring_pointer->name)) {
1114 			sprintf(error_buffer, USED_LABEL_CSTR, line, label_word);
1115 			log_error(error_buffer, PLUS_STDERR);
1116 
1117 			return (TRUE);
1118 		} else
1119 			cstring_pointer = cstring_pointer->next_string;
1120 	}
1121 
1122 	/* DON'T CHECK FOR ATT_TYPE AS YOU CAN'T HAVE ATTRIBUTE ARRAYS. */
1123 	while (attribute_pointer != NULL) {
1124 		if (!strcmp(label_word, attribute_pointer->name)) {
1125 			sprintf(error_buffer, USED_LABEL_ATT, line, label_word);
1126 			write_text(error_buffer);
1127 
1128 			return (TRUE);
1129 		} else
1130 			attribute_pointer = attribute_pointer->next_attribute;
1131 	}
1132 
1133 	for (index = 1; index <= objects; index++) {
1134 		if (!strcmp(label_word, object[index]->label)) {
1135 			sprintf(error_buffer, USED_LABEL_OBJ,
1136 			        line, label_word);
1137 			log_error(error_buffer, PLUS_STDERR);
1138 
1139 			return (TRUE);
1140 		}
1141 	}
1142 
1143 	return (FALSE);
1144 }
1145 
restart_game()1146 void restart_game() {
1147 	int             index;
1148 
1149 	integer_type *curr_integer;
1150 	integer_type *previous_integer;
1151 	synonym_type *current_synonym;
1152 	synonym_type *previous_synonym;
1153 	name_type *current_name;
1154 	name_type *next_name;
1155 	function_type *current_function;
1156 	function_type *previous_function;
1157 	string_type *curr_string;
1158 	string_type *previous_string;
1159 	attribute_type *current_attribute;
1160 	attribute_type *previous_attribute;
1161 	cinteger_type *previous_cinteger;
1162 	filter_type *current_filter;
1163 	filter_type *previous_filter;
1164 
1165 	if (SOUND_SUPPORTED->value) {
1166 		/* STOP ALL SOUNDS AND SET VOLUMES BACK TO 100% */
1167 		for (index = 0; index < 4; index++) {
1168 			g_vm->glk_schannel_stop(sound_channel[index]);
1169 			g_vm->glk_schannel_set_volume(sound_channel[index], 65535);
1170 
1171 			/* STORE A COPY OF THE CURRENT VOLUME FOR ACCESS
1172 			 * FROM JACL CODE */
1173 			sprintf(temp_buffer, "volume[%d]", index);
1174 			cinteger_resolve(temp_buffer)->value = 100;
1175 		}
1176 	}
1177 
1178 	/* FREE ALL OBJECTS */
1179 	for (index = 1; index <= objects; index++) {
1180 		current_name = object[index]->first_name;
1181 		while (current_name->next_name != NULL) {
1182 			next_name = current_name->next_name;
1183 			free(current_name);
1184 			current_name = next_name;
1185 		}
1186 		free(current_name);
1187 		free(object[index]);
1188 	}
1189 
1190 	/* FREE ALL VARIABLES */
1191 
1192 	if (integer_table != NULL) {
1193 		if (integer_table->next_integer != NULL) {
1194 			do {
1195 				curr_integer = integer_table;
1196 				previous_integer = integer_table;
1197 				while (curr_integer->next_integer != NULL) {
1198 					previous_integer = curr_integer;
1199 					curr_integer = curr_integer->next_integer;
1200 				}
1201 				free(curr_integer);
1202 				previous_integer->next_integer = NULL;
1203 			} while (previous_integer != integer_table);
1204 		}
1205 
1206 		free(integer_table);
1207 		integer_table = NULL;
1208 	}
1209 
1210 	/* FREE ALL FUNCTIONS */
1211 	if (function_table != NULL) {
1212 		if (function_table->next_function != NULL) {
1213 			do {
1214 				current_function = function_table;
1215 				previous_function = function_table;
1216 				while (current_function->next_function != NULL) {
1217 					previous_function = current_function;
1218 					current_function = current_function->next_function;
1219 				}
1220 				free(current_function);
1221 				previous_function->next_function = NULL;
1222 			} while (previous_function != function_table);
1223 		}
1224 
1225 		free(function_table);
1226 		function_table = NULL;
1227 	}
1228 
1229 	/* FREE ALL FILTERS */
1230 	if (filter_table != NULL) {
1231 		if (filter_table->next_filter != NULL) {
1232 			do {
1233 				current_filter = filter_table;
1234 				previous_filter = filter_table;
1235 				while (current_filter->next_filter != NULL) {
1236 					previous_filter = current_filter;
1237 					current_filter = current_filter->next_filter;
1238 				}
1239 				free(current_filter);
1240 				previous_filter->next_filter = NULL;
1241 			} while (previous_filter != filter_table);
1242 		}
1243 
1244 		free(filter_table);
1245 		filter_table = NULL;
1246 	}
1247 
1248 	/* FREE ALL STRINGS */
1249 	if (string_table != NULL) {
1250 		if (string_table->next_string != NULL) {
1251 			do {
1252 				curr_string = string_table;
1253 				previous_string = string_table;
1254 				while (curr_string->next_string != NULL) {
1255 					previous_string = curr_string;
1256 					curr_string = curr_string->next_string;
1257 				}
1258 				free(curr_string);
1259 				previous_string->next_string = NULL;
1260 			} while (previous_string != string_table);
1261 		}
1262 
1263 		free(string_table);
1264 		string_table = NULL;
1265 	}
1266 
1267 	/* FREE ALL ATTRIBUTES */
1268 	if (attribute_table != NULL) {
1269 		if (attribute_table->next_attribute != NULL) {
1270 			do {
1271 				current_attribute = attribute_table;
1272 				previous_attribute = attribute_table;
1273 				while (current_attribute->next_attribute != NULL) {
1274 					previous_attribute = current_attribute;
1275 					current_attribute = current_attribute->next_attribute;
1276 				}
1277 				free(current_attribute);
1278 				previous_attribute->next_attribute = NULL;
1279 			} while (previous_attribute != attribute_table);
1280 		}
1281 
1282 		free(attribute_table);
1283 		attribute_table = NULL;
1284 	}
1285 
1286 	/* FREE ALL CONSTANTS */
1287 	if (cinteger_table != NULL) {
1288 		if (cinteger_table->next_cinteger != NULL) {
1289 			do {
1290 				current_cinteger = cinteger_table;
1291 				previous_cinteger = cinteger_table;
1292 				while (current_cinteger->next_cinteger != NULL) {
1293 					previous_cinteger = current_cinteger;
1294 					current_cinteger = current_cinteger->next_cinteger;
1295 				}
1296 				free(current_cinteger);
1297 				previous_cinteger->next_cinteger = NULL;
1298 			} while (previous_cinteger != cinteger_table);
1299 		}
1300 
1301 		free(cinteger_table);
1302 		cinteger_table = NULL;
1303 	}
1304 
1305 	if (cstring_table != NULL) {
1306 		if (cstring_table->next_string != NULL) {
1307 			do {
1308 				curr_string = cstring_table;
1309 				previous_string = cstring_table;
1310 				while (curr_string->next_string != NULL) {
1311 					previous_string = curr_string;
1312 					curr_string = curr_string->next_string;
1313 				}
1314 				free(curr_string);
1315 				previous_string->next_string = NULL;
1316 			} while (previous_string != cstring_table);
1317 		}
1318 
1319 		free(cstring_table);
1320 		cstring_table = NULL;
1321 	}
1322 
1323 	/* FREE ALL SYNONYMS */
1324 	if (synonym_table != NULL) {
1325 		if (synonym_table->next_synonym != NULL) {
1326 			do {
1327 				current_synonym = synonym_table;
1328 				previous_synonym = synonym_table;
1329 				while (current_synonym->next_synonym != NULL) {
1330 					previous_synonym = current_synonym;
1331 					current_synonym = current_synonym->next_synonym;
1332 				}
1333 				free(current_synonym);
1334 				previous_synonym->next_synonym = NULL;
1335 			} while (previous_synonym != synonym_table);
1336 		}
1337 		free(synonym_table);
1338 		synonym_table = NULL;
1339 	}
1340 
1341 	free_from(grammar_table);
1342 	grammar_table = NULL;
1343 
1344 	read_gamefile();
1345 }
1346 
free_from(struct word_type * x)1347 void free_from(struct word_type *x) {
1348 	if (x) {
1349 		free_from(x->first_child);
1350 		free_from(x->next_sibling);
1351 		free(x);
1352 	}
1353 }
1354 
set_defaults()1355 void set_defaults() {
1356 	/* RESET THE BACK-REFERENCE VARIABLES */
1357 	them[0] = 0;
1358 	it = 0;
1359 	her = 0;
1360 	him = 0;
1361 }
1362 
create_cinteger(const char * name,int value)1363 void create_cinteger(const char *name, int value) {
1364 	struct cinteger_type *new_cinteger = NULL;
1365 
1366 	if ((new_cinteger = (struct cinteger_type *)
1367 	                    malloc(sizeof(struct cinteger_type))) == NULL) {
1368 		outofmem();
1369 	} else {
1370 		if (cinteger_table == NULL) {
1371 			cinteger_table = new_cinteger;
1372 		} else {
1373 			current_cinteger->next_cinteger = new_cinteger;
1374 		}
1375 
1376 		current_cinteger = new_cinteger;
1377 		strncpy(current_cinteger->name, name, 40);
1378 		current_cinteger->name[40] = 0;
1379 		current_cinteger->value = value;
1380 		current_cinteger->next_cinteger = NULL;
1381 	}
1382 }
1383 
create_integer(const char * name,int value)1384 void create_integer(const char *name, int value) {
1385 	struct integer_type *new_integer = NULL;
1386 
1387 	if ((new_integer = (struct integer_type *)
1388 	                   malloc(sizeof(struct integer_type))) == NULL) {
1389 		outofmem();
1390 	} else {
1391 		/* KEEP A COUNT OF HOW MANY INTEGERS ARE DEFINED TO
1392 		 * VALIDATE SAVED GAMES */
1393 		integers++;
1394 
1395 		if (integer_table == NULL) {
1396 			integer_table = new_integer;
1397 		} else {
1398 			current_integer->next_integer = new_integer;
1399 		}
1400 		current_integer = new_integer;
1401 		strncpy(current_integer->name, name, 40);
1402 		current_integer->name[40] = 0;
1403 		current_integer->value = value;
1404 		current_integer->next_integer = NULL;
1405 	}
1406 }
1407 
create_string(const char * name,const char * value)1408 void create_string(const char *name, const char *value) {
1409 	struct string_type *new_string = NULL;
1410 
1411 	if ((new_string = (struct string_type *)
1412 	                  malloc(sizeof(struct string_type))) == NULL) {
1413 		outofmem();
1414 	} else {
1415 		/* KEEP A COUNT OF HOW MANY STRINGS ARE DEFINED TO
1416 		 * VALIDATE SAVED GAMES */
1417 		strings++;
1418 
1419 		if (string_table == NULL) {
1420 			string_table = new_string;
1421 		} else {
1422 			current_string->next_string = new_string;
1423 		}
1424 		current_string = new_string;
1425 		strncpy(current_string->name, name, 40);
1426 		current_string->name[40] = 0;
1427 
1428 		if (value != NULL) {
1429 			strncpy(current_string->value, value, 255);
1430 		} else {
1431 			/* IF NO VALUE IS SUPPLIED, JUST NULL-TERMINATE
1432 			 * THE STRING */
1433 			current_string->value[0] = 0;
1434 		}
1435 
1436 		current_string->value[255] = 0;
1437 		current_string->next_string = NULL;
1438 	}
1439 }
1440 
create_cstring(const char * name,const char * value)1441 void create_cstring(const char *name, const char *value) {
1442 	struct string_type *new_string = NULL;
1443 
1444 	if ((new_string = (struct string_type *)
1445 	                  malloc(sizeof(struct string_type))) == NULL) {
1446 		outofmem();
1447 	} else {
1448 		if (cstring_table == NULL) {
1449 			cstring_table = new_string;
1450 		} else {
1451 			current_cstring->next_string = new_string;
1452 		}
1453 		current_cstring = new_string;
1454 		strncpy(current_cstring->name, name, 40);
1455 		current_cstring->name[40] = 0;
1456 
1457 		if (value != NULL) {
1458 			strncpy(current_cstring->value, value, 255);
1459 		} else {
1460 			/* IF NO VALUE IS SUPPLIED, JUST NULL-TERMINATE
1461 			 * THE STRING */
1462 			current_cstring->value[0] = 0;
1463 		}
1464 
1465 		current_cstring->value[255] = 0;
1466 		current_cstring->next_string = NULL;
1467 	}
1468 }
1469 
create_language_constants()1470 void create_language_constants() {
1471 	/* SET THE DEFAULT LANGUAGE CONSTANTS IF ANY OR ALL OF THEM
1472 	 * ARE MISSING FROM THE GAME THAT IS BEING LOADED. DEFAULT
1473 	 * TO THE NATIVE_LANGUAGE SETTING IN language.h */
1474 
1475 	if (cstring_resolve("COMMENT_IGNORED") == NULL)
1476 		create_cstring("COMMENT_IGNORED", COMMENT_IGNORED);
1477 	if (cstring_resolve("COMMENT_RECORDED") == NULL)
1478 		create_cstring("COMMENT_RECORDED", COMMENT_RECORDED);
1479 	if (cstring_resolve("YES_WORD") == NULL)
1480 		create_cstring("YES_WORD", YES_WORD);
1481 	if (cstring_resolve("NO_WORD") == NULL)
1482 		create_cstring("NO_WORD", NO_WORD);
1483 	if (cstring_resolve("YES_OR_NO") == NULL)
1484 		create_cstring("YES_OR_NO", YES_OR_NO);
1485 	if (cstring_resolve("INVALID_SELECTION") == NULL)
1486 		create_cstring("INVALID_SELECTION", INVALID_SELECTION);
1487 	if (cstring_resolve("RESTARTING") == NULL)
1488 		create_cstring("RESTARTING", RESTARTING);
1489 	if (cstring_resolve("RETURN_GAME") == NULL)
1490 		create_cstring("RETURN_GAME", RETURN_GAME);
1491 	if (cstring_resolve("SCRIPTING_ON") == NULL)
1492 		create_cstring("SCRIPTING_ON", SCRIPTING_ON);
1493 	if (cstring_resolve("SCRIPTING_OFF") == NULL)
1494 		create_cstring("SCRIPTING_OFF", SCRIPTING_OFF);
1495 	if (cstring_resolve("SCRIPTING_ALREADY_OFF") == NULL)
1496 		create_cstring("SCRIPTING_ALREADY_OFF", SCRIPTING_ALREADY_OFF);
1497 	if (cstring_resolve("SCRIPTING_ALREADY_ON") == NULL)
1498 		create_cstring("SCRIPTING_ALREADY_ON", SCRIPTING_ALREADY_ON);
1499 	if (cstring_resolve("CANT_WRITE_SCRIPT") == NULL)
1500 		create_cstring("CANT_WRITE_SCRIPT", CANT_WRITE_SCRIPT);
1501 	if (cstring_resolve("ERROR_READING_WALKTHRU") == NULL)
1502 		create_cstring("ERROR_READING_WALKTHRU", ERROR_READING_WALKTHRU);
1503 	if (cstring_resolve("BAD_OOPS") == NULL)
1504 		create_cstring("BAD_OOPS", BAD_OOPS);
1505 	if (cstring_resolve("CANT_CORRECT") == NULL)
1506 		create_cstring("CANT_CORRECT", CANT_CORRECT);
1507 	if (cstring_resolve("SURE_QUIT") == NULL)
1508 		create_cstring("SURE_QUIT", SURE_QUIT);
1509 	if (cstring_resolve("SURE_RESTART") == NULL)
1510 		create_cstring("SURE_RESTART", SURE_RESTART);
1511 	if (cstring_resolve("NOT_CLEVER") == NULL)
1512 		create_cstring("NOT_CLEVER", NOT_CLEVER);
1513 	if (cstring_resolve("NO_MOVES") == NULL)
1514 		create_cstring("NO_MOVES", NO_MOVES);
1515 	if (cstring_resolve("TYPE_NUMBER") == NULL)
1516 		create_cstring("TYPE_NUMBER", TYPE_NUMBER);
1517 	if (cstring_resolve("BY") == NULL)
1518 		create_cstring("BY", BY);
1519 	if (cstring_resolve("REFERRING_TO") == NULL)
1520 		create_cstring("REFERRING_TO", REFERRING_TO);
1521 	if (cstring_resolve("WALKTHRU_WORD") == NULL)
1522 		create_cstring("WALKTHRU_WORD", WALKTHRU_WORD);
1523 	if (cstring_resolve("INFO_WORD") == NULL)
1524 		create_cstring("INFO_WORD", INFO_WORD);
1525 	if (cstring_resolve("RESTART_WORD") == NULL)
1526 		create_cstring("RESTART_WORD", RESTART_WORD);
1527 	if (cstring_resolve("AGAIN_WORD") == NULL)
1528 		create_cstring("AGAIN_WORD", AGAIN_WORD);
1529 	if (cstring_resolve("SCRIPT_WORD") == NULL)
1530 		create_cstring("SCRIPT_WORD", SCRIPT_WORD);
1531 	if (cstring_resolve("UNSCRIPT_WORD") == NULL)
1532 		create_cstring("UNSCRIPT_WORD", UNSCRIPT_WORD);
1533 	if (cstring_resolve("QUIT_WORD") == NULL)
1534 		create_cstring("QUIT_WORD", QUIT_WORD);
1535 	if (cstring_resolve("UNDO_WORD") == NULL)
1536 		create_cstring("UNDO_WORD", UNDO_WORD);
1537 	if (cstring_resolve("OOPS_WORD") == NULL)
1538 		create_cstring("OOPS_WORD", OOPS_WORD);
1539 	if (cstring_resolve("FROM_WORD") == NULL)
1540 		create_cstring("FROM_WORD", FROM_WORD);
1541 	if (cstring_resolve("EXCEPT_WORD") == NULL)
1542 		create_cstring("EXCEPT_WORD", EXCEPT_WORD);
1543 	if (cstring_resolve("FOR_WORD") == NULL)
1544 		create_cstring("FOR_WORD", FOR_WORD);
1545 	if (cstring_resolve("BUT_WORD") == NULL)
1546 		create_cstring("BUT_WORD", BUT_WORD);
1547 	if (cstring_resolve("AND_WORD") == NULL)
1548 		create_cstring("AND_WORD", AND_WORD);
1549 	if (cstring_resolve("THEN_WORD") == NULL)
1550 		create_cstring("THEN_WORD", THEN_WORD);
1551 	if (cstring_resolve("OF_WORD") == NULL)
1552 		create_cstring("OF_WORD", OF_WORD);
1553 	if (cstring_resolve("SHE_WORD") == NULL)
1554 		create_cstring("SHE_WORD", SHE_WORD);
1555 	if (cstring_resolve("HE_WORD") == NULL)
1556 		create_cstring("HE_WORD", HE_WORD);
1557 	if (cstring_resolve("THAT_WORD") == NULL)
1558 		create_cstring("THAT_WORD", THAT_WORD);
1559 	if (cstring_resolve("THEM_WORD") == NULL)
1560 		create_cstring("THEM_WORD", THEM_WORD);
1561 	if (cstring_resolve("THOSE_WORD") == NULL)
1562 		create_cstring("THOSE_WORD", THOSE_WORD);
1563 	if (cstring_resolve("THEY_WORD") == NULL)
1564 		create_cstring("THEY_WORD", THEY_WORD);
1565 	if (cstring_resolve("IT_WORD") == NULL)
1566 		create_cstring("IT_WORD", IT_WORD);
1567 	if (cstring_resolve("ITSELF_WORD") == NULL)
1568 		create_cstring("ITSELF_WORD", ITSELF_WORD);
1569 	if (cstring_resolve("HIM_WORD") == NULL)
1570 		create_cstring("HIM_WORD", HIM_WORD);
1571 	if (cstring_resolve("HIMSELF_WORD") == NULL)
1572 		create_cstring("HIMSELF_WORD", HIMSELF_WORD);
1573 	if (cstring_resolve("HER_WORD") == NULL)
1574 		create_cstring("HER_WORD", HER_WORD);
1575 	if (cstring_resolve("HERSELF_WORD") == NULL)
1576 		create_cstring("HERSELF_WORD", HERSELF_WORD);
1577 	if (cstring_resolve("THEMSELVES_WORD") == NULL)
1578 		create_cstring("THEMSELVES_WORD", THEMSELVES_WORD);
1579 	if (cstring_resolve("YOU_WORD") == NULL)
1580 		create_cstring("YOU_WORD", YOU_WORD);
1581 	if (cstring_resolve("YOURSELF_WORD") == NULL)
1582 		create_cstring("YOURSELF_WORD", YOURSELF_WORD);
1583 	if (cstring_resolve("ONES_WORD") == NULL)
1584 		create_cstring("ONES_WORD", ONES_WORD);
1585 	if (cstring_resolve("NO_MULTI_VERB") == NULL)
1586 		create_cstring("NO_MULTI_VERB", NO_MULTI_VERB);
1587 	if (cstring_resolve("NO_MULTI_START") == NULL)
1588 		create_cstring("NO_MULTI_START", NO_MULTI_START);
1589 	if (cstring_resolve("PERSON_CONCEALING") == NULL)
1590 		create_cstring("PERSON_CONCEALING", PERSON_CONCEALING);
1591 	if (cstring_resolve("PERSON_POSSESSIVE") == NULL)
1592 		create_cstring("PERSON_POSSESSIVE", PERSON_POSSESSIVE);
1593 	if (cstring_resolve("CONTAINER_CLOSED") == NULL)
1594 		create_cstring("CONTAINER_CLOSED", CONTAINER_CLOSED);
1595 	if (cstring_resolve("CONTAINER_CLOSED_FEM") == NULL)
1596 		create_cstring("CONTAINER_CLOSED_FEM", CONTAINER_CLOSED_FEM);
1597 	if (cstring_resolve("FROM_NON_CONTAINER") == NULL)
1598 		create_cstring("FROM_NON_CONTAINER", FROM_NON_CONTAINER);
1599 	if (cstring_resolve("DOUBLE_EXCEPT") == NULL)
1600 		create_cstring("DOUBLE_EXCEPT", DOUBLE_EXCEPT);
1601 	if (cstring_resolve("NONE_HELD") == NULL)
1602 		create_cstring("NONE_HELD", NONE_HELD);
1603 	if (cstring_resolve("NO_OBJECTS") == NULL)
1604 		create_cstring("NO_OBJECTS", NO_OBJECTS);
1605 	if (cstring_resolve("NO_FILENAME") == NULL)
1606 		create_cstring("NO_FILENAME", NO_FILENAME);
1607 	if (cstring_resolve("MOVE_UNDONE") == NULL)
1608 		create_cstring("MOVE_UNDONE", MOVE_UNDONE);
1609 	if (cstring_resolve("NO_UNDO") == NULL)
1610 		create_cstring("NO_UNDO", NO_UNDO);
1611 	if (cstring_resolve("CANT_SAVE") == NULL)
1612 		create_cstring("CANT_SAVE", CANT_SAVE);
1613 	if (cstring_resolve("CANT_RESTORE") == NULL)
1614 		create_cstring("CANT_RESTORE", CANT_RESTORE);
1615 	if (cstring_resolve("GAME_SAVED") == NULL)
1616 		create_cstring("GAME_SAVED", GAME_SAVED);
1617 	if (cstring_resolve("INCOMPLETE_SENTENCE") == NULL)
1618 		create_cstring("INCOMPLETE_SENTENCE", INCOMPLETE_SENTENCE);
1619 	if (cstring_resolve("UNKNOWN_OBJECT") == NULL)
1620 		create_cstring("UNKNOWN_OBJECT", UNKNOWN_OBJECT);
1621 	if (cstring_resolve("UNKNOWN_OBJECT_END") == NULL)
1622 		create_cstring("UNKNOWN_OBJECT_END", UNKNOWN_OBJECT_END);
1623 	if (cstring_resolve("CANT_USE_WORD") == NULL)
1624 		create_cstring("CANT_USE_WORD", CANT_USE_WORD);
1625 	if (cstring_resolve("IN_CONTEXT") == NULL)
1626 		create_cstring("IN_CONTEXT", IN_CONTEXT);
1627 	if (cstring_resolve("DONT_SEE") == NULL)
1628 		create_cstring("DONT_SEE", DONT_SEE);
1629 	if (cstring_resolve("HERE_WORD") == NULL)
1630 		create_cstring("HERE_WORD", HERE_WORD);
1631 	if (cstring_resolve("BAD_SAVED_GAME") == NULL)
1632 		create_cstring("BAD_SAVED_GAME", BAD_SAVED_GAME);
1633 	if (cstring_resolve("ARENT") == NULL)
1634 		create_cstring("ARENT", ARENT);
1635 	if (cstring_resolve("ISNT") == NULL)
1636 		create_cstring("ISNT", ISNT);
1637 	if (cstring_resolve("ARE") == NULL)
1638 		create_cstring("ARE", ARE);
1639 	if (cstring_resolve("IS") == NULL)
1640 		create_cstring("IS", IS);
1641 	if (cstring_resolve("DONT") == NULL)
1642 		create_cstring("DONT", DONT);
1643 	if (cstring_resolve("DOESNT") == NULL)
1644 		create_cstring("DOESNT", DOESNT);
1645 	if (cstring_resolve("DO") == NULL)
1646 		create_cstring("DO", DO);
1647 	if (cstring_resolve("DOES") == NULL)
1648 		create_cstring("DOES", DOES);
1649 	if (cstring_resolve("SCORE_UP") == NULL)
1650 		create_cstring("SCORE_UP", SCORE_UP);
1651 	if (cstring_resolve("POINT") == NULL)
1652 		create_cstring("POINT", POINT);
1653 	if (cstring_resolve("POINTS") == NULL)
1654 		create_cstring("POINTS", POINTS);
1655 	if (cstring_resolve("STARTING") == NULL)
1656 		create_cstring("STARTING", STARTING);
1657 	if (cstring_resolve("NO_IT") == NULL)
1658 		create_cstring("NO_IT", NO_IT);
1659 	if (cstring_resolve("NO_IT_END") == NULL)
1660 		create_cstring("NO_IT_END", NO_IT_END);
1661 	if (cstring_resolve("BACK_REFERENCE") == NULL)
1662 		create_cstring("BACK_REFERENCE", BACK_REFERENCE);
1663 	if (cstring_resolve("BACK_REFERENCE_END") == NULL)
1664 		create_cstring("BACK_REFERENCE_END", BACK_REFERENCE_END);
1665 	if (cstring_resolve("WHEN_YOU_SAY") == NULL)
1666 		create_cstring("WHEN_YOU_SAY", WHEN_YOU_SAY);
1667 	if (cstring_resolve("MUST_SPECIFY") == NULL)
1668 		create_cstring("MUST_SPECIFY", MUST_SPECIFY);
1669 	if (cstring_resolve("OR_WORD") == NULL)
1670 		create_cstring("OR_WORD", OR_WORD);
1671 }
1672 
1673 } // End of namespace JACL
1674 } // End of namespace Glk
1675