[Scummvm-cvs-logs] SF.net SVN: scummvm: [32697] scummvm/branches/gsoc2008-gui/gui

Tanoku at users.sourceforge.net Tanoku at users.sourceforge.net
Sat Jun 14 00:05:22 CEST 2008


Revision: 32697
          http://scummvm.svn.sourceforge.net/scummvm/?rev=32697&view=rev
Author:   Tanoku
Date:     2008-06-13 15:05:21 -0700 (Fri, 13 Jun 2008)

Log Message:
-----------
Parser redesign. Fixed most possible overflows.

Modified Paths:
--------------
    scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp
    scummvm/branches/gsoc2008-gui/gui/ThemeParser.h

Modified: scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp
===================================================================
--- scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp	2008-06-13 17:47:56 UTC (rev 32696)
+++ scummvm/branches/gsoc2008-gui/gui/ThemeParser.cpp	2008-06-13 22:05:21 UTC (rev 32697)
@@ -42,15 +42,11 @@
 
 namespace GUI {
 
-inline bool isValidNameChar(char c) {
-	return isalnum(c) || c == '_';
-}
-
 void ThemeParser::debug_testEval() {
 	static const char *debug_config_text =
 		"<drawdata id = \"background_default\" cache = true>"
 		"<draw func = \"roundedsq\" /*/fill = \"gradient\" gradient_start = \"255, 255, 128\" gradient_end = \"128, 128, 128\" size = \"auto\"/>"
-		"<draw func = \"roundedsq\" fill = \"none\" color = \"0, 0, 0\" size = \"auto\"/>"
+		"<draw func = \"roundedsq\" fill = \"none\" color = /*\"0, 0, 0\"*/\"0, 1, 2\" size = \"auto\"/>"
 		"</drawdata>/* lol this is just a simple test*/";
 
 	_text = strdup(debug_config_text);
@@ -91,37 +87,38 @@
 	}
 }
 
-void ThemeParser::parseKeyValue(Common::String &key_name) {
-	assert(_text[_pos++] == '=');
+bool ThemeParser::parseKeyValue(Common::String &key_name) {
 	assert(_keyValues.empty() == false);
 
-	if (_keyValues.top().contains(key_name)) {
-		parserError("Repeated value inside key.");
-		return;
-	}
+	if (_keyValues.top().contains(key_name))
+		return false;
 
-	skipSpaces();
-
-	Common::String data;
+	Common::String name = key_name;
+	_token.clear();
 	char string_start;
 
 	if (_text[_pos] == '"' || _text[_pos] == '\'') {
 		string_start = _text[_pos++];
 
-		while (_text[_pos] != string_start)
-			data += _text[_pos++];
+		while (_text[_pos] && _text[_pos] != string_start)
+			_token += _text[_pos++];
 
-		_pos++;
-	} else {
-		while (isValidNameChar(_text[_pos]))
-			data += _text[_pos++];
+		if (_text[_pos++] == 0)
+			return false;
+
+	} else if (!parseToken()) {
+		return false;
 	}
 
-	_keyValues.top()[key_name] = data;
+	_keyValues.top()[name] = _token;
+	return true;
 }
 
 bool ThemeParser::parse() {
 
+	bool active_closure = false;
+	bool self_closure = false;
+
 	_state = kParserNeedKey;
 	_pos = 0;
 	_keyValues.clear();
@@ -131,79 +128,74 @@
 		if (_state == kParserError)
 			break;
 
-		skipSpaces();
+		if (skipSpaces())
+			continue;
 
 		if (skipComments())
 			continue;
 
 		switch (_state) {
 			case kParserNeedKey:
-				if (_text[_pos++] != '<') {
-					parserError("Expecting key start.");
-					break;
-				}
+				if (_text[_pos++] != '<') parserError("Expecting key start.");
+				else _state = kParserNeedKeyName;
+				break;
 
+			case kParserNeedKeyName:
 				if (_text[_pos] == '/') {
 					_pos++;
-					_token.clear();
-					while (isValidNameChar(_text[_pos]))
-						_token += _text[_pos++];
+					active_closure = true;
+				}
+				
+				if (!parseToken()) {
+					parserError("Unexpected end of file while parsing token.");
+					break;
+				}
 
+				if (active_closure) {
 					if (_activeKey.empty() || _token != _activeKey.top())
 						parserError("Unexpected closure.");
-					else {
-						_activeKey.pop();
-						_keyValues.pop();
-
-						skipSpaces();
-
-						if (_text[_pos++] != '>')
-							parserError("Malformed tag closure.");
-					}
-	
-					break;
+				} else {
+					_keyValues.push(Common::StringMap());
+					_activeKey.push(_token);
 				}
 
-				_keyValues.push(Common::StringMap());
-				_state = kParserNeedKeyName;
+				_state = kParserNeedPropertyName;
 				break;
 
-			case kParserNeedKeyName:
-				_token.clear();
-				while (isValidNameChar(_text[_pos]))
-					_token += _text[_pos++];
+			case kParserNeedPropertyName:
+				if (active_closure) {
+					active_closure = false;
+					_activeKey.pop();
+					_keyValues.pop();
 
-				if (!isspace(_text[_pos]) && _text[_pos] != '>') {
-					parserError("Invalid character in token name.");
+					if (_text[_pos++] != '>')
+						parserError("Invalid syntax in key closure.");
+					
+					_state = kParserNeedKey;
 					break;
 				}
 
-				_state = kParserNeedKeyValues;
-				_activeKey.push(_token);
-				break;
+				self_closure = (_text[_pos] == '/');
 
-			case kParserNeedKeyValues:
-				_token.clear();
-
-				if ((_text[_pos] == '/' && _text[_pos + 1] == '>') || _text[_pos] == '>') {
-					bool closed = _text[_pos] == '/';
-					parseActiveKey(closed);
-					_pos += closed ? 2 : 1;
+				if ((self_closure && _text[_pos + 1] == '>') || _text[_pos] == '>') {
+					parseActiveKey(self_closure);
+					_pos += self_closure ? 2 : 1;
 					_state = kParserNeedKey;
 					break;
 				}
 
-				while (isValidNameChar(_text[_pos]))
-					_token += _text[_pos++];
+				if (!parseToken()) parserError("Error when parsing key value.");
+				else _state = kParserNeedPropertyOperator;
+				break;
 
-				skipSpaces();
+			case kParserNeedPropertyOperator:
+				if (_text[_pos++] != '=') parserError("Unexpected character after key name.");
+				else  _state = kParserNeedPropertyValue;
+				break;
 
-				if (_text[_pos] != '=') {
-					parserError("Unexpected character after key name.");
-					break;
-				}
-
-				parseKeyValue(_token);
+			case kParserNeedPropertyValue:
+				if (!parseKeyValue(_token)) parserError("Unable to parse key value.");
+				else _state = kParserNeedPropertyName;
 				break;
 
 			default:
@@ -217,6 +209,7 @@
 
 	if (_state != kParserNeedKey || !_activeKey.empty()) {
 		parserError("Unexpected end of file.");
+		return false;
 	}
 
 	return true;

Modified: scummvm/branches/gsoc2008-gui/gui/ThemeParser.h
===================================================================
--- scummvm/branches/gsoc2008-gui/gui/ThemeParser.h	2008-06-13 17:47:56 UTC (rev 32696)
+++ scummvm/branches/gsoc2008-gui/gui/ThemeParser.h	2008-06-13 22:05:21 UTC (rev 32697)
@@ -52,25 +52,33 @@
 	enum ParserState {
 		kParserNeedKey,
 		kParserNeedKeyName,
-		kParserNeedKeyValues,
+
+		kParserNeedPropertyName,
+		kParserNeedPropertyOperator,
+		kParserNeedPropertyValue,
+
 		kParserError
 	};
 
 	bool parse();
-	void parseKeyValue(Common::String &key_name);
-	void parseActiveKey(bool closed);
-
-	void parserError(const char *error_string);
-
 	void debug_testEval();
 	
 protected:
 	void parserCallback_DRAW();
 	void parserCallback_DRAWDATA();
 
-	inline void skipSpaces() {
-		while (isspace(_text[_pos]))
+	bool parseKeyValue(Common::String &key_name);
+	void parseActiveKey(bool closed);
+	void parserError(const char *error_string);
+
+	inline bool skipSpaces() {
+		if (!isspace(_text[_pos]))
+			return false;
+
+		while (_text[_pos] && isspace(_text[_pos]))
 			_pos++;
+
+		return true;
 	}
 
 	inline bool skipComments() {
@@ -85,6 +93,18 @@
 		return false;
 	}
 
+	inline bool isValidNameChar(char c) {
+		return isalnum(c) || c == '_';
+	}
+
+	inline bool parseToken() {
+		_token.clear();
+		while (isValidNameChar(_text[_pos]))
+			_token += _text[_pos++];
+
+		return (_text[_pos] != 0);
+	}
+
 	int _pos;
 	char *_text;
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list