[Scummvm-cvs-logs] SF.net SVN: scummvm:[44545] scummvm/trunk/engines/sci/console.cpp

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Fri Oct 2 22:20:45 CEST 2009


Revision: 44545
          http://scummvm.svn.sourceforge.net/scummvm/?rev=44545&view=rev
Author:   fingolfin
Date:     2009-10-02 20:20:45 +0000 (Fri, 02 Oct 2009)

Log Message:
-----------
SCI: Fix parse_reg_t, it no longer modified the const string passed to it

Modified Paths:
--------------
    scummvm/trunk/engines/sci/console.cpp

Modified: scummvm/trunk/engines/sci/console.cpp
===================================================================
--- scummvm/trunk/engines/sci/console.cpp	2009-10-02 18:48:00 UTC (rev 44544)
+++ scummvm/trunk/engines/sci/console.cpp	2009-10-02 20:20:45 UTC (rev 44545)
@@ -2721,95 +2721,99 @@
 
 // Returns 0 on success
 int parse_reg_t(EngineState *s, const char *str, reg_t *dest) {
-	// FIXME: Stop this function from changing str.
-	int rel_offsetting = 0;
-	const char *offsetting = NULL;
+	// Pointer to the part of str which contains a numeric offset (if any)
+	const char *offsetStr = NULL;
+
+	// Flag that tells whether the value stored in offsetStr is an absolute offset,
+	// or a relative offset against dest->offset.
+	bool relativeOffset = false;
+
 	// Non-NULL: Parse end of string for relative offsets
 	char *endptr;
 
-	if (*str == '$') { // Register
-		rel_offsetting = 1;
+	if (*str == '$') { // Register: "$FOO" or "$FOO+NUM" or "$FOO-NUM
+		relativeOffset = true;
 
 		if (!scumm_strnicmp(str + 1, "PC", 2)) {
 			*dest = s->_executionStack.back().addr.pc;
-			offsetting = str + 3;
+			offsetStr = str + 3;
 		} else if (!scumm_strnicmp(str + 1, "P", 1)) {
 			*dest = s->_executionStack.back().addr.pc;
-			offsetting = str + 2;
+			offsetStr = str + 2;
 		} else if (!scumm_strnicmp(str + 1, "PREV", 4)) {
 			*dest = s->r_prev;
-			offsetting = str + 5;
+			offsetStr = str + 5;
 		} else if (!scumm_strnicmp(str + 1, "ACC", 3)) {
 			*dest = s->r_acc;
-			offsetting = str + 4;
+			offsetStr = str + 4;
 		} else if (!scumm_strnicmp(str + 1, "A", 1)) {
 			*dest = s->r_acc;
-			offsetting = str + 2;
+			offsetStr = str + 2;
 		} else if (!scumm_strnicmp(str + 1, "OBJ", 3)) {
 			*dest = s->_executionStack.back().objp;
-			offsetting = str + 4;
+			offsetStr = str + 4;
 		} else if (!scumm_strnicmp(str + 1, "O", 1)) {
 			*dest = s->_executionStack.back().objp;
-			offsetting = str + 2;
+			offsetStr = str + 2;
 		} else
 			return 1; // No matching register
 
-		if (!*offsetting)
-			offsetting = NULL;
-		else if (*offsetting != '+' && *offsetting != '-')
+		if (!*offsetStr)
+			offsetStr = NULL;
+		else if (*offsetStr != '+' && *offsetStr != '-')
 			return 1;
-	} else if (*str == '&') {
-		int script_nr;
-		// Look up by script ID
-		char *colon = (char *)strchr(str, ':');
-
+	} else if (*str == '&') { // Script relative: "&SCRIPT-ID:OFFSET"
+		// Look up by script ID. The text from start till just before the colon
+		// (resp. end of string, if there is no colon) contains the script ID.
+		const char *colon = strchr(str, ':');
 		if (!colon)
 			return 1;
-		*colon = 0;
-		offsetting = colon + 1;
 
-		script_nr = strtol(str + 1, &endptr, 10);
-
+		// Extract the script id and parse it
+		Common::String scriptStr(str, colon);
+		int script_nr = strtol(scriptStr.c_str() + 1, &endptr, 10);
 		if (*endptr)
 			return 1;
 
+		// Now lookup the script's segment
 		dest->segment = s->segMan->getScriptSegment(script_nr);
-
 		if (!dest->segment) {
 			return 1;
 		}
-	} else if (*str == '?') {
+
+		// Finally, after the colon comes the offset
+		offsetStr = colon + 1;
+	} else if (*str == '?') {	// Object by name: "?OBJ" or "?OBJ.INDEX" or "?OBJ.INDEX+OFFSET" or "?OBJ.INDEX-OFFSET"
+		// The (optional) index can be used to distinguish multiple object with the same name.
 		int index = -1;
-		int times_found = 0;
-		char *tmp;
-		const char *str_objname;
-		char *str_suffix;
-		char suffchar = 0;
-		uint i;
-		// Parse obj by name
 
-		tmp = (char *)strchr(str, '+');
-		str_suffix = (char *)strchr(str, '-');
-		if (tmp < str_suffix)
-			str_suffix = tmp;
-		if (str_suffix) {
-			suffchar = (*str_suffix);
-			*str_suffix = 0;
-		}
+		// Look for an offset. It starts with + or -
+		relativeOffset = true;
+		offsetStr = strchr(str, '+');
+		if (!offsetStr)	// No + found, look for -
+			offsetStr = strchr(str, '-');
 
-		tmp = (char *)strchr(str, '.');
+		// Strip away the offset and the leading '?'
+		Common::String str_objname;
+		if (offsetStr) {
+			str_objname = Common::String(str + 1, offsetStr);
+		} else
+			str_objname = str + 1;
 
+
+		// Scan for a period, after which (if present) we'll find an index
+		const char *tmp = Common::find(str_objname.begin(), str_objname.end(), '.');
 		if (tmp) {
-			*tmp = 0;
 			index = strtol(tmp + 1, &endptr, 16);
 			if (*endptr)
 				return -1;
+			// Chop of the index
+			str_objname = Common::String(str_objname.c_str(), tmp);
 		}
 
-		str_objname = str + 1;
-
 		// Now all values are available; iterate over all objects.
-		for (i = 0; i < s->segMan->_heap.size(); i++) {
+		int times_found = 0;
+		for (uint i = 0; i < s->segMan->_heap.size(); i++) {
 			SegmentObj *mobj = s->segMan->_heap[i];
 			int idx = 0;
 			int max_index = 0;
@@ -2828,6 +2832,7 @@
 				}
 			}
 
+			// It's a script or a clone table, scan all objects in it
 			for (; idx < max_index; ++idx) {
 				Object *obj = NULL;
 				reg_t objpos;
@@ -2846,15 +2851,15 @@
 				}
 
 				const char *objname = s->segMan->getObjectName(objpos);
-				if (!strcmp(objname, str_objname)) {
+				if (str_objname == objname) {
 					// Found a match!
 					if ((index < 0) && (times_found > 0)) {
 						if (times_found == 1) {
 							// First time we realized the ambiguity
 							printf("Ambiguous:\n");
-							printf("  %3x: [%04x:%04x] %s\n", 0, PRINT_REG(*dest), str_objname);
+							printf("  %3x: [%04x:%04x] %s\n", 0, PRINT_REG(*dest), str_objname.c_str());
 						}
-						printf("  %3x: [%04x:%04x] %s\n", times_found, PRINT_REG(objpos), str_objname);
+						printf("  %3x: [%04x:%04x] %s\n", times_found, PRINT_REG(objpos), str_objname.c_str());
 					}
 					if (index < 0 || times_found == index)
 						*dest = objpos;
@@ -2875,29 +2880,26 @@
 		if (times_found <= index)
 			return 1; // Not found
 
-		offsetting = str_suffix;
-		if (offsetting)
-			*str_suffix = suffchar;
-		rel_offsetting = 1;
-	} else {
-		char *colon = (char *)strchr(str, ':');
+	} else {	// Finally, check for "SEGMENT:OFFSET" or just "OFFSET"
+		const char *colon = strchr(str, ':');
 
 		if (!colon) {
-			offsetting = str;
+			// No segment specified
+			offsetStr = str;
 			dest->segment = 0;
 		} else {
-			*colon = 0;
-			offsetting = colon + 1;
+			offsetStr = colon + 1;
 
-			dest->segment = strtol(str, &endptr, 16);
+			Common::String segmentStr(str, colon);
+			dest->segment = strtol(segmentStr.c_str(), &endptr, 16);
 			if (*endptr)
 				return 1;
 		}
 	}
-	if (offsetting) {
-		int val = strtol(offsetting, &endptr, 16);
+	if (offsetStr) {
+		int val = strtol(offsetStr, &endptr, 16);
 
-		if (rel_offsetting)
+		if (relativeOffset)
 			dest->offset += val;
 		else
 			dest->offset = val;


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