diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -245,7 +245,7 @@ static void EmitSingleChar(char *buf, in /* This is encoded like * CommandByte {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; @@ -263,6 +263,12 @@ bool ParseRelNum(char **buf, int *value) } 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; } @@ -303,7 +309,7 @@ char *ParseWord(char **buf) } /* Forward declaration */ -static int TranslateArgumentIdx(int arg); +static int TranslateArgumentIdx(int arg, int offset = 0); static void EmitWordList(const char * const *words, uint nw) { @@ -318,11 +324,12 @@ static void EmitWordList(const char * co 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++) { @@ -351,7 +358,7 @@ static void EmitPlural(char *buf, int va } PutUtf8(SCC_PLURAL_LIST); - PutByte(TranslateArgumentIdx(argidx)); + PutByte(TranslateArgumentIdx(argidx, offset)); EmitWordList(words, nw); } @@ -359,6 +366,7 @@ static void EmitPlural(char *buf, int va static void EmitGender(char *buf, int value) { int argidx = _cur_argidx; + int offset = 0; uint nw; if (buf[0] == '=') { @@ -377,7 +385,7 @@ static void EmitGender(char *buf, int va /* 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); @@ -385,7 +393,7 @@ static void EmitGender(char *buf, int va } if (nw != _numgenders) error("Bad # of arguments for gender command"); PutUtf8(SCC_GENDER_LIST); - PutByte(TranslateArgumentIdx(argidx)); + PutByte(TranslateArgumentIdx(argidx, offset)); EmitWordList(words, nw); } } @@ -948,20 +956,25 @@ static void WriteStringsH(const char *fi } } -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()