Changeset - r13903:5fb1706b1ba1
[Not reviewed]
master
0 1 0
rubidium - 14 years ago 2009-12-09 11:41:27
rubidium@openttd.org
(svn r18444) -Feature: allow G and P to 'select' substrings of STRINGn for getting their gender
1 file changed with 21 insertions and 8 deletions:
0 comments (0 inline, 0 general)
src/strgen/strgen.cpp
Show inline comments
 
@@ -236,42 +236,48 @@ static void EmitSingleChar(char *buf, in
 
{
 
	if (*buf != '\0') strgen_warning("Ignoring trailing letters in command");
 
	PutUtf8(value);
 
}
 

	
 

	
 
/* The plural specifier looks like
 
 * {NUM} {PLURAL -1 passenger passengers} then it picks either passenger/passengers depending on the count in NUM */
 

	
 
/* This is encoded like
 
 *  CommandByte <ARG#> <NUM> {Length of each string} {each string} */
 

	
 
bool ParseRelNum(char **buf, int *value)
 
bool ParseRelNum(char **buf, int *value, int *offset)
 
{
 
	const char *s = *buf;
 
	char *end;
 
	bool rel = false;
 

	
 
	while (*s == ' ' || *s == '\t') s++;
 
	if (*s == '+') {
 
		rel = true;
 
		s++;
 
	}
 
	int v = strtol(s, &end, 0);
 
	if (end == s) return false;
 
	if (rel || v < 0) {
 
		*value += v;
 
	} else {
 
		*value = v;
 
	}
 
	if (offset != NULL && *end == ':') {
 
		/* Take the Nth within */
 
		s = end + 1;
 
		*offset = strtol(s, &end, 0);
 
		if (end == s) return false;
 
	}
 
	*buf = end;
 
	return true;
 
}
 

	
 
/* Parse out the next word, or NULL */
 
char *ParseWord(char **buf)
 
{
 
	char *s = *buf, *r;
 

	
 
	while (*s == ' ' || *s == '\t') s++;
 
	if (*s == '\0') return NULL;
 

	
 
@@ -294,44 +300,45 @@ char *ParseWord(char **buf)
 
			if (*s == ' ' || *s == '\t') {
 
				*s++ = '\0';
 
				break;
 
			}
 
			s++;
 
		}
 
	}
 
	*buf = s;
 
	return r;
 
}
 

	
 
/* Forward declaration */
 
static int TranslateArgumentIdx(int arg);
 
static int TranslateArgumentIdx(int arg, int offset = 0);
 

	
 
static void EmitWordList(const char * const *words, uint nw)
 
{
 
	PutByte(nw);
 
	for (uint i = 0; i < nw; i++) PutByte(strlen(words[i]) + 1);
 
	for (uint i = 0; i < nw; i++) {
 
		for (uint j = 0; words[i][j] != '\0'; j++) PutByte(words[i][j]);
 
		PutByte(0);
 
	}
 
}
 

	
 
static void EmitPlural(char *buf, int value)
 
{
 
	int argidx = _cur_argidx;
 
	int offset = 0;
 
	const char *words[5];
 
	int nw = 0;
 

	
 
	/* Parse out the number, if one exists. Otherwise default to prev arg. */
 
	if (!ParseRelNum(&buf, &argidx)) argidx--;
 
	if (!ParseRelNum(&buf, &argidx, &offset)) argidx--;
 

	
 
	/* Parse each string */
 
	for (nw = 0; nw < 5; nw++) {
 
		words[nw] = ParseWord(&buf);
 
		if (words[nw] == NULL) break;
 
	}
 

	
 
	if (nw == 0) {
 
		error("%s: No plural words", _cur_ident);
 
	}
 

	
 
	if (_plural_forms[_lang_pluralform].plural_count != nw) {
 
@@ -342,59 +349,60 @@ static void EmitPlural(char *buf, int va
 
			if ((_show_todo & 2) != 0) strgen_warning("'%s' is untranslated. Tweaking english string to allow compilation for plural forms", _cur_ident);
 
			if (nw > _plural_forms[_lang_pluralform].plural_count) {
 
				nw = _plural_forms[_lang_pluralform].plural_count;
 
			} else {
 
				for (; nw < _plural_forms[_lang_pluralform].plural_count; nw++) {
 
					words[nw] = words[nw - 1];
 
				}
 
			}
 
		}
 
	}
 

	
 
	PutUtf8(SCC_PLURAL_LIST);
 
	PutByte(TranslateArgumentIdx(argidx));
 
	PutByte(TranslateArgumentIdx(argidx, offset));
 
	EmitWordList(words, nw);
 
}
 

	
 

	
 
static void EmitGender(char *buf, int value)
 
{
 
	int argidx = _cur_argidx;
 
	int offset = 0;
 
	uint nw;
 

	
 
	if (buf[0] == '=') {
 
		buf++;
 

	
 
		/* This is a {G=DER} command */
 
		for (nw = 0; ; nw++) {
 
			if (nw >= MAX_NUM_GENDER) error("G argument '%s' invalid", buf);
 
			if (strcmp(buf, _genders[nw]) == 0) break;
 
		}
 
		/* now nw contains the gender index */
 
		PutUtf8(SCC_GENDER_INDEX);
 
		PutByte(nw);
 
	} else {
 
		const char *words[MAX_NUM_GENDER];
 

	
 
		/* This is a {G 0 foo bar two} command.
 
		 * If no relative number exists, default to +0 */
 
		if (!ParseRelNum(&buf, &argidx)) {}
 
		if (!ParseRelNum(&buf, &argidx, &offset)) {}
 

	
 
		for (nw = 0; nw < MAX_NUM_GENDER; nw++) {
 
			words[nw] = ParseWord(&buf);
 
			if (words[nw] == NULL) break;
 
		}
 
		if (nw != _numgenders) error("Bad # of arguments for gender command");
 
		PutUtf8(SCC_GENDER_LIST);
 
		PutByte(TranslateArgumentIdx(argidx));
 
		PutByte(TranslateArgumentIdx(argidx, offset));
 
		EmitWordList(words, nw);
 
	}
 
}
 

	
 
static const CmdStruct *FindCmd(const char *s, int len)
 
{
 
	for (const CmdStruct *cs = _cmd_structs; cs != endof(_cmd_structs); cs++) {
 
		if (strncmp(cs->cmd, s, len) == 0 && cs->cmd[len] == '\0') return cs;
 
	}
 
	return NULL;
 
}
 

	
 
@@ -939,38 +947,43 @@ static void WriteStringsH(const char *fi
 
	if (CompareFiles("tmp.xxx", filename)) {
 
		/* files are equal. tmp.xxx is not needed */
 
		unlink("tmp.xxx");
 
	} else {
 
		/* else rename tmp.xxx into filename */
 
#if defined(WIN32) || defined(WIN64)
 
		unlink(filename);
 
#endif
 
		if (rename("tmp.xxx", filename) == -1) error("rename() failed");
 
	}
 
}
 

	
 
static int TranslateArgumentIdx(int argidx)
 
static int TranslateArgumentIdx(int argidx, int offset)
 
{
 
	int sum;
 

	
 
	if (argidx < 0 || (uint)argidx >= lengthof(_cur_pcs.cmd)) {
 
		error("invalid argidx %d", argidx);
 
	}
 
	const CmdStruct *cs = _cur_pcs.cmd[argidx];
 
	if (cs != NULL && cs->consumes <= offset) {
 
		error("invalid argidx offset %d:%d\n", argidx, offset);
 
	}
 

	
 
	for (int i = sum = 0; i < argidx; i++) {
 
		const CmdStruct *cs = _cur_pcs.cmd[i];
 

	
 
		sum += (cs != NULL) ? cs->consumes : 1;
 
	}
 

	
 
	return sum;
 
	return sum + offset;
 
}
 

	
 
static void PutArgidxCommand()
 
{
 
	PutUtf8(SCC_ARG_INDEX);
 
	PutByte(TranslateArgumentIdx(_cur_argidx));
 
}
 

	
 

	
 
static void PutCommandString(const char *str)
 
{
 
	_cur_argidx = 0;
0 comments (0 inline, 0 general)