diff options
| author | Einar Johan Trøan Sømåen | 2012-07-21 18:19:07 +0200 | 
|---|---|---|
| committer | Einar Johan Trøan Sømåen | 2012-07-21 19:15:33 +0200 | 
| commit | 5683f076331d2831eb4720b65bb53e8d01ca33ee (patch) | |
| tree | 4357d989476643db887d5f5a95f6fd165afd0514 /engines/wintermute/base/base_parser.cpp | |
| parent | 0622b2c5b8260c0f0c01122d6fbc5e10013d1613 (diff) | |
| download | scummvm-rg350-5683f076331d2831eb4720b65bb53e8d01ca33ee.tar.gz scummvm-rg350-5683f076331d2831eb4720b65bb53e8d01ca33ee.tar.bz2 scummvm-rg350-5683f076331d2831eb4720b65bb53e8d01ca33ee.zip | |
WINTERMUTE: Rename CamelCased filenames to prefixed_under_score-filenames
This is mostly a lead-up to namespacing the Ad/Base folders, and then
possibly removing the prefixes from the files, it also has the added
benefit of getting rid of the odd case-typos that makes for issues
on platforms that don't ignore case.
Diffstat (limited to 'engines/wintermute/base/base_parser.cpp')
| -rw-r--r-- | engines/wintermute/base/base_parser.cpp | 436 | 
1 files changed, 436 insertions, 0 deletions
| diff --git a/engines/wintermute/base/base_parser.cpp b/engines/wintermute/base/base_parser.cpp new file mode 100644 index 0000000000..0f185636aa --- /dev/null +++ b/engines/wintermute/base/base_parser.cpp @@ -0,0 +1,436 @@ +/* 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 2
 + * 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, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + */
 +
 +/*
 + * This file is based on WME Lite.
 + * http://dead-code.org/redir.php?target=wmelite
 + * Copyright (c) 2011 Jan Nedoma
 + */
 +
 +#include "engines/wintermute/dcgf.h"
 +#include "engines/wintermute/base/base_parser.h"
 +#include "engines/wintermute/base/base_game.h"
 +#include "engines/wintermute/platform_osystem.h"
 +#include "common/str.h"
 +#include "common/util.h"
 +
 +#define WHITESPACE " \t\n\r"
 +
 +namespace WinterMute {
 +
 +//////////////////////////////////////////////////////////////////////
 +// Construction/Destruction
 +//////////////////////////////////////////////////////////////////////
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +CBParser::CBParser(CBGame *inGame): CBBase(inGame) {
 +	_whiteSpace = new char [strlen(WHITESPACE) + 1];
 +	strcpy(_whiteSpace, WHITESPACE);
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +CBParser::~CBParser() {
 +	if (_whiteSpace != NULL) delete [] _whiteSpace;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +char *CBParser::getLastOffender() {
 +	return _lastOffender;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +int32 CBParser::getObject(char **buf, TokenDesc *tokens, char **name, char **data) {
 +	skipCharacters(buf, _whiteSpace);
 +
 +	// skip comment lines.
 +	while (**buf == ';') {
 +		*buf = strchr(*buf, '\n');
 +		_parserLine++;
 +		skipCharacters(buf, _whiteSpace);
 +	}
 +
 +	if (! **buf)                  // at end of file
 +		return PARSERR_EOF;
 +
 +	// find the token.
 +	// for now just use brute force.  Improve later.
 +	while (tokens->id != 0) {
 +		if (!scumm_strnicmp(tokens->token, *buf, strlen(tokens->token))) {
 +			// here we could be matching PART of a string
 +			// we could detect this here or the token list
 +			// could just have the longer tokens first in the list
 +			break;
 +		}
 +		++tokens;
 +	}
 +	if (tokens->id == 0) {
 +		char *p = strchr(*buf, '\n');
 +		if (p && p > *buf) {
 +			strncpy(_lastOffender, *buf, MIN((uint32)255, (uint32)(p - *buf))); // TODO, clean
 +		} else strcpy(_lastOffender, "");
 +
 +		return PARSERR_TOKENNOTFOUND;
 +	}
 +	// skip the token
 +	*buf += strlen(tokens->token);
 +	skipCharacters(buf, _whiteSpace);
 +
 +	// get optional name
 +	*name = getSubText(buf, '\'', '\'');  // single quotes
 +	skipCharacters(buf, _whiteSpace);
 +
 +	// get optional data
 +	if (**buf == '=') // An assignment rather than a command/object.
 +		*data = getAssignmentText(buf);
 +	else
 +		*data = getSubText(buf, '{', '}');
 +
 +	return tokens->id;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +int32 CBParser::getCommand(char **buf, TokenDesc *tokens, char **params) {
 +	if (!*buf) return PARSERR_TOKENNOTFOUND;
 +	_gameRef->miniUpdate();
 +	char *name;
 +	return getObject(buf, tokens, &name, params);
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +void CBParser::skipCharacters(char **buf, const char *toSkip) {
 +	char ch;
 +	while ((ch = **buf) != 0) {
 +		if (ch == '\n') _parserLine++;
 +		if (strchr(toSkip, ch) == NULL)
 +			return;
 +		++*buf;                     // skip this character
 +	}
 +	// we must be at the end of the buffer if we get here
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +char *CBParser::getSubText(char **buf, char open, char close) {
 +	if (**buf == 0 || **buf != open)
 +		return 0;
 +	++*buf;                       // skip opening delimiter
 +	char *result = *buf;
 +
 +	// now find the closing delimiter
 +	char theChar;
 +	long skip = 1;
 +
 +	if (open == close)            // we cant nest identical delimiters
 +		open = 0;
 +	while ((theChar = **buf) != 0) {
 +		if (theChar == open)
 +			++skip;
 +		if (theChar == close) {
 +			if (--skip == 0) {
 +				**buf = 0;              // null terminate the result string
 +				++*buf;                 // move past the closing delimiter
 +				break;
 +			}
 +		}
 +		++*buf;                     // try next character
 +	}
 +	return result;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +char *CBParser::getAssignmentText(char **buf) {
 +	++*buf;                       // skip the '='
 +	skipCharacters(buf, _whiteSpace);
 +	char *result = *buf;
 +
 +
 +	if (*result == '"') {
 +		result = getSubText(buf, '"', '"');
 +	} else {
 +		// now, we need to find the next whitespace to end the data
 +		char theChar;
 +
 +		while ((theChar = **buf) != 0) {
 +			if (theChar <= 0x20)        // space and control chars
 +				break;
 +			++*buf;
 +		}
 +		**buf = 0;                 // null terminate it
 +		if (theChar)                  // skip the terminator
 +			++*buf;
 +	}
 +
 +	return result;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +//////////////////////////////////////////////////////////////////////
 +char *CBParser::getToken(char **buf) {
 +	static char token[100];
 +	char *b = *buf, * t = token;
 +	while (true) {
 +		while (*b && (*b == ' ' || *b == '\n' || *b == 13 || *b == 10 || *b == '\t')) b++;
 +		if (*b == ';')
 +			while (*b && *b != '\n' && *b != 13 && *b != 10) b++;
 +		else break;
 +	}
 +
 +	if (*b == '\'') {
 +		b++;
 +		while (*b && *b != '\'') {
 +			*t++ = *b++;
 +		}
 +		*t++ = 0;
 +		if (*b == '\'') b++;
 +	} else if (*b == '(' || *b == ')' || *b == '=' || *b == ',' || *b == '[' || *b == ']' ||
 +	           *b == '%' || *b == ':' || *b == '{' || *b == '}') {
 +		*t++ = *b++;
 +		*t++ = 0;
 +	} else if (*b == '.' && (*(b + 1) < '0' || *(b + 1) > '9')) {
 +		*t++ = *b++;
 +		*t++ = 0;
 +	} else if ((*b >= '0' && *b <= '9') || *b == '.' || *b == '-') {
 +		while (*b && ((*b >= '0' && *b <= '9') || *b == '.' || *b == '-')) {
 +			*t++ = *b++;
 +		}
 +		*t++ = 0;
 +	} else if ((*b >= 'A' && *b <= 'Z') || (*b >= 'a' && *b <= 'z') || *b == '_') {
 +		while (*b && ((*b >= 'A' && *b <= 'Z') || (*b >= 'a' && *b <= 'z') || *b == '_')) {
 +			*t++ = *b++;
 +		}
 +		*t++ = 0;
 +	} else if (*b == 0) {
 +		*buf = b;
 +		return NULL;
 +	} else {
 +		// Error.
 +		return NULL;
 +	}
 +
 +	*buf = b;
 +	return token;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +float CBParser::getTokenFloat(char **buf) {
 +	char *t = getToken(buf);
 +	if (!((*t >= '0' && *t <= '9') || *t == '-' || *t == '.')) {
 +		// Error situation. We handle this by return 0.
 +		return 0.;
 +	}
 +	float rc = (float)atof(t);
 +	return rc;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +int CBParser::getTokenInt(char **buf) {
 +	char *t = getToken(buf);
 +	if (!((*t >= '0' && *t <= '9') || *t == '-')) {
 +		// Error situation. We handle this by return 0.
 +		return 0;
 +	}
 +	int rc = atoi(t);
 +	return rc;
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +void CBParser::skipToken(char **buf, char *tok, char * /*msg*/) {
 +	char *t = getToken(buf);
 +	if (strcmp(t, tok)) return;  // Error
 +}
 +
 +
 +//////////////////////////////////////////////////////////////////////
 +int CBParser::scanStr(const char *in, const char *format, ...) {
 +	va_list arg;
 +	va_start(arg, format);
 +
 +	int num = 0;
 +	in += strspn(in, " \t\n\f");
 +
 +	while (*format && *in) {
 +		if (*format == '%') {
 +			format++;
 +			switch (*format) {
 +			case 'd': {
 +				int *a = va_arg(arg, int *);
 +				in += strspn(in, " \t\n\f");
 +				*a = atoi(in);
 +				in += strspn(in, "0123456789+- \t\n\f");
 +				num++;
 +				break;
 +			}
 +			case 'D': {
 +				int i;
 +				int *list = va_arg(arg, int *);
 +				int *nr = va_arg(arg, int *);
 +				in += strspn(in, " \t\n\f");
 +				i = 0;
 +				while ((*in >= '0' && *in <= '9') || *in == '+' || *in == '-') {
 +					list[i++] = atoi(in);
 +					in += strspn(in, "0123456789+-");
 +					in += strspn(in, " \t\n\f");
 +					if (*in != ',') break;
 +					in++;
 +					in += strspn(in, " \t\n\f");
 +				}
 +				*nr = i;
 +				num++;
 +				break;
 +			}
 +			case 'b': {
 +				bool *a = va_arg(arg, bool *);
 +				in += strspn(in, " \t\n\f");
 +				const char *in2 = in + strspn(in, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
 +				int l = (int)(in2 - in);
 +
 +				*a = (bool)(!scumm_strnicmp(in, "yes", l) || !scumm_strnicmp(in, "true", l) || !scumm_strnicmp(in, "on", l) ||
 +				            !scumm_strnicmp(in, "1", l));
 +
 +
 +				in = in2 + strspn(in2, " \t\n\f");
 +				num++;
 +				break;
 +			}
 +			case 'f': {
 +				float *a = va_arg(arg, float *);
 +				in += strspn(in, " \t\n\f");
 +				*a = (float)atof(in);
 +				in += strspn(in, "0123456789.eE+- \t\n\f");
 +				num++;
 +				break;
 +			}
 +			case 'F': {
 +				int i;
 +				float *list = va_arg(arg, float *);
 +				int *nr = va_arg(arg, int *);
 +				in += strspn(in, " \t\n\f");
 +				i = 0;
 +				while ((*in >= '0' && *in <= '9') || *in == '.' || *in == '+' || *in == '-' || *in == 'e' || *in == 'E') {
 +					list[i++] = (float)atof(in);
 +					in += strspn(in, "0123456789.eE+-");
 +					in += strspn(in, " \t\n\f");
 +					if (*in != ',') break;
 +					in++;
 +					in += strspn(in, " \t\n\f");
 +				}
 +				*nr = i;
 +				num++;
 +				break;
 +			}
 +			case 's': {
 +				char *a = va_arg(arg, char *);
 +				in += strspn(in, " \t\n\f");
 +				if (*in == '\'') {
 +					in++;
 +					const char *in2 = strchr(in, '\'');
 +					if (in2) {
 +						strncpy(a, in, (int)(in2 - in));
 +						a[(int)(in2 - in)] = 0;
 +						in = in2 + 1;
 +					} else {
 +						strcpy(a, in);
 +						in = strchr(in, 0);
 +					}
 +				} else {
 +					const char *in2 = in + strspn(in, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789.");
 +					strncpy(a, in, (int)(in2 - in));
 +					a[(int)(in2 - in)] = 0;
 +					in = in2;
 +				}
 +				in += strspn(in, " \t\n\f");
 +				num++;
 +				break;
 +			}
 +			case 'S': {
 +				char *a = va_arg(arg, char *);
 +				in += strspn(in, " \t\n\f");
 +				if (*in == '\"') {
 +					in++;
 +					while (*in != '\"') {
 +						if (*in == '\\') {
 +							in++;
 +							switch (*in) {
 +							case '\\':
 +								*a++ = '\\';
 +								break;
 +							case 'n':
 +								*a++ = '\n';
 +								break;
 +							case 'r':
 +								*a++ = '\r';
 +								break;
 +							case 't':
 +								*a++ = '\t';
 +								break;
 +							case '"':
 +								*a++ = '"';
 +								break;
 +							default:
 +								*a++ = '\\';
 +								*a++ = *in;
 +								break;
 +							} //switch
 +							in++;
 +						} else {
 +							*a++ = *in++;
 +						}
 +					} //while in string
 +					in++;
 +					num++;
 +				} //if string started
 +
 +				//terminate string
 +				*a = '\0';
 +				break;
 +			}
 +			}
 +			if (*format) format++;
 +		} else if (*format == ' ') {
 +			format++;
 +			in += strspn(in, " \t\n\f");
 +		} else if (*in == *format) {
 +			in++;
 +			format++;
 +		} else {
 +			num = -1;
 +			break;
 +		}
 +	}
 +
 +	va_end(arg);
 +
 +	return num;
 +}
 +
 +} // end of namespace WinterMute
 | 
