aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction
diff options
context:
space:
mode:
authorNicola Mettifogo2008-11-13 15:15:54 +0000
committerNicola Mettifogo2008-11-13 15:15:54 +0000
commit618644ba0c3e410ba7df320fe33ba4f469476295 (patch)
treeef6cae961bc365273ea052168b5a498344d7cde6 /engines/parallaction
parentf7bdf6b40f883ceeac2034763bc0bebc174a13df (diff)
downloadscummvm-rg350-618644ba0c3e410ba7df320fe33ba4f469476295.tar.gz
scummvm-rg350-618644ba0c3e410ba7df320fe33ba4f469476295.tar.bz2
scummvm-rg350-618644ba0c3e410ba7df320fe33ba4f469476295.zip
Update to the low level parser:
* made it detect buffer overflows * removed unused code paths * general simplification svn-id: r35047
Diffstat (limited to 'engines/parallaction')
-rw-r--r--engines/parallaction/parser.cpp189
-rw-r--r--engines/parallaction/parser.h4
-rw-r--r--engines/parallaction/parser_ns.cpp55
3 files changed, 112 insertions, 136 deletions
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index c15d1111d3..3dc586dd8c 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -40,46 +40,85 @@ Script::~Script() {
delete _input;
}
-char *Script::readLine(char *buf, size_t bufSize) {
-
+char *Script::readLineIntern(char *buf, size_t bufSize) {
uint16 i;
for (i = 0; i < bufSize; i++) {
-
char c = _input->readSByte();
-
if (_input->eos())
break;
-
- if (c == 0xA || c == 0xD)
+ if (c == '\n' || c == '\r')
break;
+ if (c == '\t')
+ c = ' ';
- if (i < bufSize)
- buf[i] = c;
+ buf[i] = c;
}
-
_line++;
-
- if (i == 0 && _input->eos())
+ if (i == bufSize) {
+ warning("overflow in readLineIntern (line %i)", _line);
+ }
+ if (i == 0 && _input->eos()) {
return 0;
+ }
+ buf[i] = '\0';
+ return buf;
+}
- buf[i] = 0xA;
- buf[i+1] = '\0';
+bool isCommentLine(char *text) {
+ return text[0] == '#';
+}
- return buf;
+bool isStartOfCommentBlock(char *text) {
+ return (text[0] == '[');
+}
+bool isEndOfCommentBlock(char *text) {
+ return (text[0] == ']');
}
+char *Script::readLine(char *buf, size_t bufSize) {
+ bool inBlockComment = false;
+ bool ignoreLine = true;
+ char *line = 0;
+ do {
+ line = readLineIntern(buf, bufSize);
+ if (line == 0) {
+ return 0;
+ }
-void Script::clearTokens() {
+ if (line[0] == '\0')
+ continue;
- for (uint16 i = 0; i < MAX_TOKENS; i++)
- _tokens[i][0] = '\0';
+ ignoreLine = false;
- _numTokens = 0;
+ line = Common::ltrim(line);
+ if (isCommentLine(line)) {
+ // ignore this line
+ ignoreLine = true;
+ } else
+ if (isStartOfCommentBlock(line)) {
+ // mark this and the following lines as comment
+ inBlockComment = true;
+ } else
+ if (isEndOfCommentBlock(line)) {
+ // comment is finished, so stop ignoring
+ inBlockComment = false;
+ // the current line must be skipped, though,
+ // as it contains the end-of-comment marker
+ ignoreLine = true;
+ }
- return;
+ } while (inBlockComment || ignoreLine);
+ return line;
+}
+
+
+
+void Script::clearTokens() {
+ memset(_tokens, 0, sizeof(_tokens));
+ _numTokens = 0;
}
void Script::skip(const char* endToken) {
@@ -111,21 +150,14 @@ char *Script::parseNextToken(char *s, char *tok, uint16 count, const char *brk,
if (*s == '\0') {
*tok = '\0';
return s;
- }
-
+ } else
if (strchr(brk, *s)) {
*tok = '\0';
return ++s;
- }
-
+ } else
if (*s == '"') {
- if (ignoreQuotes) {
- *tok++ = *s++;
- count--;
- } else {
- state = QUOTED;
- s++;
- }
+ state = QUOTED;
+ s++;
} else {
*tok++ = *s++;
count--;
@@ -136,14 +168,14 @@ char *Script::parseNextToken(char *s, char *tok, uint16 count, const char *brk,
if (*s == '\0') {
*tok = '\0';
return s;
- }
- if (*s == '"' || *s == '\n' || *s == '\t') {
+ } else
+ if (*s == '"') {
*tok = '\0';
return ++s;
+ } else {
+ *tok++ = *s++;
+ count--;
}
-
- *tok++ = *s++;
- count--;
break;
}
@@ -158,71 +190,23 @@ char *Script::parseNextToken(char *s, char *tok, uint16 count, const char *brk,
}
-uint16 Script::fillTokens(char* line) {
-
- uint16 i = 0;
- while (strlen(line) > 0 && i < MAX_TOKENS) {
- line = parseNextToken(line, _tokens[i], MAX_TOKEN_LEN, " \t\n");
- line = Common::ltrim(line);
- i++;
- }
-
- _numTokens = i;
-
- return i;
-}
-
-bool isCommentLine(char *text) {
- return text[0] == '#';
-}
-
-bool isStartOfCommentBlock(char *text) {
- return (text[0] == '[');
-}
-
-bool isEndOfCommentBlock(char *text) {
- return (text[0] == ']');
-}
-
uint16 Script::readLineToken(bool errorOnEOF) {
-
- clearTokens();
-
- bool inBlockComment = false;
-
char buf[200];
- char *line = NULL;
- char *start;
- do {
- line = readLine(buf, 200);
-
- if (line == NULL) {
- if (errorOnEOF)
- error("unexpected end of file while parsing");
- else
- return 0;
- }
- start = Common::ltrim(line);
-
- if (isCommentLine(start)) {
- // ignore this line
- start[0] = '\0';
- } else
- if (isStartOfCommentBlock(start)) {
- // mark this and the following lines as comment
- inBlockComment = true;
- } else
- if (isEndOfCommentBlock(start)) {
- // comment is finished, so stop ignoring
- inBlockComment = false;
- // the current line must be skipped, though,
- // as it contains the end-of-comment marker
- start[0] = '\0';
- }
-
- } while (inBlockComment || strlen(start) == 0);
+ char *line = readLine(buf, 200);
+ if (!line) {
+ if (errorOnEOF)
+ error("unexpected end of file while parsing");
+ else
+ return 0;
+ }
- return fillTokens(start);
+ clearTokens();
+ while (strlen(line) > 0 && _numTokens < MAX_TOKENS) {
+ line = parseNextToken(line, _tokens[_numTokens], MAX_TOKEN_LEN, " ");
+ line = Common::ltrim(line);
+ _numTokens++;
+ }
+ return _numTokens;
}
@@ -328,13 +312,11 @@ class CommentStatementDef : public StatementDef {
Common::String parseComment(Script &script) {
Common::String result;
char buf[401];
-
do {
- script.readLine(buf, 400);
- buf[strlen(buf)-1] = '\0';
- if (!scumm_stricmp(buf, "endtext"))
+ char *line = script.readLine(buf, 400);
+ if (!scumm_stricmp(line, "endtext"))
break;
- result += Common::String(buf) + "\n";
+ result += Common::String(line) + "\n";
} while (true);
result += "endtext\n";
return result;
@@ -408,8 +390,7 @@ void PreProcessor::preprocessScript(Script &script, StatementList &list) {
_numZones = 0;
Common::String text;
do {
- script.readLineToken(false);
- if (_numTokens == 0)
+ if (script.readLineToken(false) == 0)
break;
StatementDef *def = findDef(_tokens[0]);
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index f184dcbc58..cbeecbb438 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -44,8 +44,8 @@ class Script {
uint _line; // for debug messages
void clearTokens();
- uint16 fillTokens(char* line);
- char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
+ char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
+ char *readLineIntern(char *buf, size_t bufSize);
public:
Script(Common::ReadStream *, bool _disposeSource = false);
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index 7864df917d..d6405a4dfd 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -943,21 +943,12 @@ void LocationParser_ns::resolveDialogueForwards(Dialogue *dialogue, uint numQues
}
char *LocationParser_ns::parseDialogueString() {
-
- char vC8[200];
- char *vD0 = NULL;
- do {
-
- vD0 = _script->readLine(vC8, 200);
- if (vD0 == 0) return NULL;
-
- vD0 = Common::ltrim(vD0);
-
- } while (strlen(vD0) == 0);
-
- vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA'
- // this is critical for Gfx::displayWrappedString to work properly
- return strdup(vD0);
+ char buf[200];
+ char *line = _script->readLine(buf, 200);
+ if (line == 0) {
+ return 0;
+ }
+ return strdup(line);
}
@@ -1275,26 +1266,30 @@ void ProgramParser_ns::init() {
// comments are displayed into rectangles on the screen
//
char *LocationParser_ns::parseComment() {
-
- char _tmp_comment[1000] = "\0";
- char *v194;
-
+ const int tempSize = 1000;
+ char temp[tempSize] = "\0";
+ int len = 0;
+ char buf[400];
do {
- char v190[400];
- v194 = _script->readLine(v190, 400);
-
- v194[strlen(v194)-1] = '\0';
- if (!scumm_stricmp(v194, "endtext"))
+ char *line = _script->readLine(buf, 400);
+ if (!scumm_stricmp(line, "endtext"))
break;
- strcat(_tmp_comment, v194);
- strcat(_tmp_comment, " ");
- } while (true);
+ strncat(temp, line, tempSize - len - 1);
+ strcat(temp, " ");
+ len = len + strlen(line) + 1;
+ } while (len < tempSize);
- v194 = strdup(_tmp_comment);
- _tmp_comment[0] = '\0';
+ if (len == 0) {
+ return 0;
+ }
+
+ if (len == tempSize) {
+ warning("overflow in LocationParser_ns::parseComment (line %i)", _script->getLine());
+ }
- return v194;
+ temp[len-1] = '\0'; // removes the last space pasted in the string
+ return strdup(temp);
}
DECLARE_ZONE_PARSER(null) {