/* 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 3 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, see .
*
*/
#include "glk/quest/read_file.h"
#include "glk/quest/geas_util.h"
#include "glk/quest/reserved_words.h"
#include "glk/quest/geas_runner.h"
#include "glk/quest/streams.h"
#include "common/util.h"
#include "common/textconsole.h"
namespace Glk {
namespace Quest {
String next_token(String full, uint &tok_start, uint &tok_end, bool cvt_paren) {
tok_start = tok_end;
while (tok_start < full.size() && Common::isSpace(full[tok_start]))
++ tok_start;
if (tok_start >= full.size()) {
tok_start = tok_end = full.size();
//tok_start = tok_end = String::npos;
return "";
}
tok_end = tok_start + 1;
if (full[tok_start] == '{' || full[tok_start] == '}')
/* brace is a token by itself */;
else if (full[tok_start] == '<') {
while (tok_end < full.size() && full [tok_end] != '>')
++ tok_end;
if (full[tok_end] == '>')
++ tok_end;
} else if (cvt_paren && full[tok_start] == '(') {
uint depth = 1;
/*
while (tok_end < full.size() && full [tok_end] != ')')
++ tok_end;
if (full[tok_end] == ')')
++ tok_end;
*/
do {
if (full[tok_end] == '(')
++ depth;
else if (full[tok_end] == ')')
-- depth;
++ tok_end;
} while (tok_end < full.size() && depth > 0);
} else
while (tok_end < full.size() && !Common::isSpace(full[tok_end]))
++ tok_end;
return full.substr(tok_start, tok_end - tok_start);
}
String first_token(String s, uint &t_start, uint &t_end) {
t_end = 0;
return next_token(s, t_start, t_end);
}
String nth_token(String s, int n) {
uint x1, x2 = 0;
String rv;
do
rv = next_token(s, x1, x2);
while (-- n > 0);
return rv;
}
String get_token(String s, bool cvt_paren) {
uint x1, x2 = 0;
return next_token(s, x1, x2, cvt_paren);
}
bool find_token(String s, String tok, int &tok_start, int &tok_end, bool cvt_paren) {
uint copy_start, copy_end;
copy_end = tok_end;
do {
String tmp = next_token(s, copy_start, copy_end, cvt_paren);
if (tmp == tok) {
tok_start = copy_start;
tok_end = copy_end;
return true;
}
} while (copy_end < s.size());
return false;
}
bool is_define(String s) {
return get_token(s) == "define";
}
bool is_define(String s, String t) {
uint t1, t2 = 0;
return next_token(s, t1, t2) == "define" &&
next_token(s, t1, t2) == t;
}
bool is_start_textmode(String s) {
uint start_char, end_char = 0;
if (next_token(s, start_char, end_char) != "define") return false;
String tmp = next_token(s, start_char, end_char);
// SENSITIVE?
return tmp == "text" || tmp == "synonyms";
}
bool is_end_define(String s) {
uint start_char, end_char = 0;
// SENSITIVE?
return (next_token(s, start_char, end_char) == "end" &&
next_token(s, start_char, end_char) == "define");
}
extern Common::Array split_lines(String data);
void GeasFile::read_into(const Common::Array &in_data,
String in_parent, uint cur_line, bool recurse,
const reserved_words &props,
const reserved_words &actions,
const reserved_words &dir_tag_property) {
//cerr << "r_i: Reading in from" << cur_line << ": " << in_data[cur_line] << endl;
//output.push_back (GeasBlock());
//GeasBlock &out_block = output[output.size() - 1];
int blocknum = blocks.size();
blocks.push_back(GeasBlock());
GeasBlock &out_block = blocks[blocknum];
Common::Array &out_data = out_block.data;
out_block.parent = in_parent;
uint t1, t2;
String line = in_data[cur_line];
// SENSITIVE?
assert(first_token(line, t1, t2) == "define");
String blocktype = out_block.blocktype = next_token(line, t1, t2); // "object", or the like
//cerr << "r_i: Pushing back block of type " << blocktype << "\n";
type_indecies[blocktype].push_back(blocknum);
String name = next_token(line, t1, t2); // "", or the like
// SENSITIVE?
if (blocktype == "game") {
out_block.name = "game";
out_data.push_back("game name " + name);
} else if (is_param(name))
out_block.name = param_contents(name);
else if (name != "")
error("Expected parameter; %s found instead.", name.c_str());
//out_block.lname = lcase (out_block.nname);
// apparently not all block types are unique ... TODO which?
// SENSITIVE?
if (blocktype == "room" || blocktype == "object" || blocktype == "game")
register_block(out_block.name, blocktype);
//register_block (out_block.lname, blocktype);
// SENSITIVE?
if (blocktype == "room" && find_by_name("type", "defaultroom"))
out_data.push_back("type ");
// SENSITIVE?
if (blocktype == "object" && find_by_name("type", "default"))
out_data.push_back("type ");
cur_line ++;
uint depth = 1;
while (cur_line < in_data.size() && depth > 0) {
line = in_data[cur_line];
if (recurse && is_define(line))
++ depth;
else if (is_end_define(in_data[cur_line]))
-- depth;
else if (depth == 1) {
//cerr << "r_i: Processing line #" << cur_line << ": " << line << endl;
//String dup_data = "";
String tok = first_token(line, t1, t2);
String rest = next_token(line, t1, t2);
//cerr << "r_i: tok == '" << tok << "', props[tok] == " << props[tok]
// << ", actions[tok] == " << actions[tok] << "\n";
if (props[tok] && dir_tag_property[tok])
out_data.push_back(line);
if (props[tok] && rest == "") {
//cerr << "r_i: Handling as props \n";
line = "properties <" + tok + ">";
} else if (props[tok] && is_param(rest)) {
//cerr << "r_i: Handling as props \n";
line = "properties <" + tok + "=" + param_contents(rest) + ">";
} else if (actions[tok] &&
(tok == "use" || tok == "give" || !is_param(rest))) {
//cerr << "r_i: Handling as action '" << tok << "'\n";
// SENSITIVE?
if (tok == "use") {
//cerr << "r_i: ********** Use line: <" + line + "> ---> ";
String lhs = "action