void VInvocation::CheckDecorateParams(VEmitContext& ec) { guard(VInvocation::CheckDecorateParams); int max_params; int num_needed_params = Func->NumParams; if (Func->Flags & FUNC_VarArgs) { max_params = VMethod::MAX_PARAMS - 1; } else { max_params = Func->NumParams; } if (NumArgs > max_params) { ParseError(Loc, "Incorrect number of arguments, need %d, got %d.", max_params, NumArgs); } for (int i = 0; i < NumArgs; i++) { if (i >= num_needed_params) { continue; } if (!Args[i]) { continue; } switch (Func->ParamTypes[i].Type) { case TYPE_Name: if (Args[i]->IsDecorateSingleName()) { VDecorateSingleName* E = (VDecorateSingleName*)Args[i]; Args[i] = new VNameLiteral(*E->Name, E->Loc); delete E; E = NULL; } else if (Args[i]->IsStrConst()) { VStr Val = Args[i]->GetStrConst(ec.Package); TLocation ALoc = Args[i]->Loc; delete Args[i]; Args[i] = NULL; Args[i] = new VNameLiteral(*Val, ALoc); } break; case TYPE_String: if (Args[i]->IsDecorateSingleName()) { VDecorateSingleName* E = (VDecorateSingleName*)Args[i]; Args[i] = new VStringLiteral(ec.Package->FindString(*E->Name), E->Loc); delete E; E = NULL; } break; case TYPE_Class: if (Args[i]->IsDecorateSingleName()) { VDecorateSingleName* E = (VDecorateSingleName*)Args[i]; Args[i] = new VStringLiteral(ec.Package->FindString(*E->Name), E->Loc); delete E; E = NULL; } if (Args[i]->IsStrConst()) { VStr CName = Args[i]->GetStrConst(ec.Package); TLocation ALoc = Args[i]->Loc; VClass* Cls = VClass::FindClassNoCase(*CName); if (!Cls) { ParseWarning(ALoc, "No such class %s", *CName); delete Args[i]; Args[i] = NULL; Args[i] = new VNoneLiteral(ALoc); } else if (Func->ParamTypes[i].Class && !Cls->IsChildOf(Func->ParamTypes[i].Class)) { ParseWarning(ALoc, "Class %s is not a descendant of %s", *CName, Func->ParamTypes[i].Class->GetName()); delete Args[i]; Args[i] = NULL; Args[i] = new VNoneLiteral(ALoc); } else { delete Args[i]; Args[i] = NULL; Args[i] = new VClassConstant(Cls, ALoc); } } break; case TYPE_State: if (Args[i]->IsIntConst()) { int Offs = Args[i]->GetIntConst(); TLocation ALoc = Args[i]->Loc; if (Offs < 0) { ParseError(ALoc, "Negative state jumps are not allowed"); } else if (Offs == 0) { // 0 means no state delete Args[i]; Args[i] = NULL; Args[i] = new VNoneLiteral(ALoc); } else { check(CallerState); VState* S = CallerState->GetPlus(Offs, true); if (!S) { ParseError(ALoc, "Bad state jump offset"); } else { delete Args[i]; Args[i] = NULL; Args[i] = new VStateConstant(S, ALoc); } } } else if (Args[i]->IsStrConst()) { VStr Lbl = Args[i]->GetStrConst(ec.Package); TLocation ALoc = Args[i]->Loc; int DCol = Lbl.IndexOf("::"); if (DCol >= 0) { // Jump to a specific parent class state, resolve it and // pass value directly. VStr ClassName(Lbl, 0, DCol); VClass* CheckClass; if (ClassName.ICmp("Super")) { CheckClass = ec.SelfClass->ParentClass; } else { CheckClass = VClass::FindClassNoCase(*ClassName); if (!CheckClass) { ParseError(ALoc, "No such class %s", *ClassName); } else if (!ec.SelfClass->IsChildOf(CheckClass)) { ParseError(ALoc, "%s is not a subclass of %s", ec.SelfClass->GetName(), CheckClass->GetName()); CheckClass = NULL; } } if (CheckClass) { VStr LblName(Lbl, DCol + 2, Lbl.Length() - DCol - 2); TArray<VName> Names; VMemberBase::StaticSplitStateLabel(LblName, Names); VStateLabel* StLbl = CheckClass->FindStateLabel(Names, true); if (!StLbl) { ParseError(ALoc, "No such state %s", *Lbl); } else { delete Args[i]; Args[i] = NULL; Args[i] = new VStateConstant(StLbl->State, ALoc); } } } else { // It's a virtual state jump VExpression* TmpArgs[1]; TmpArgs[0] = Args[i]; Args[i] = new VInvocation(NULL, ec.SelfClass->FindMethodChecked("FindJumpState"), NULL, false, false, Args[i]->Loc, 1, TmpArgs); } } break; } } unguard; }
SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) { /* See if we are ignoring a phrase */ if (m_CurPhrase == -1) { return SMCResult_Continue; } phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase); /* Duplicate format keys get silently ignored. */ if (key[0] == '#' && strcmp(key, "#format") == 0 && pPhrase->fmt_list == -1) { if (pPhrase->translations > 0) { ParseWarning("#format property should come before translations on line %d, ignoring", states->line); return SMCResult_Continue; } /* Do an initial browsing for error checking and what not */ enum ParseStates { Parse_None, Parse_Index, Parse_Format, }; ParseStates state = Parse_None; const char *old_value = value; const char *last_value = value; while (*value != '\0') { if (state == Parse_None) { if (*value == '{') { pPhrase->fmt_count++; state = Parse_Index; } else if (*value == ',') { /* Do nothing */ } else { unsigned int bytes = textparsers->GetUTF8CharBytes(value); if (bytes != 1 || !isalpha(*value)) { ParseWarning("Invalid token '%c' in #format property on line %d.", *value, states->line); } } } else if (state == Parse_Index) { if (*value == ':') { state = Parse_Format; if (value - last_value >= 15) { ParseWarning("Too many digits in format index on line %d, phrase will be ignored.", states->line); m_CurPhrase = -1; return SMCResult_Continue; } } else { unsigned int bytes = textparsers->GetUTF8CharBytes(value); if (bytes != 1 || !isdigit(*value)) { ParseWarning("Token '%c' in #format property on line %d is not a digit, phrase will be ignored.", *value, states->line); m_CurPhrase = -1; return SMCResult_Continue; } } } else if (state == Parse_Format) { if (*value == '}') { state = Parse_None; last_value = value + 1; } } value++; } if (state != Parse_None) { /* Moose clam cow. */ ParseWarning("Unterminated format string on line %d, phrase will be ignored.", states->line); m_CurPhrase = -1; return SMCResult_Continue; } value = old_value; /* Allocate the format table */ char fmt_buf[16]; int *fmt_list; int tmp = m_pMemory->CreateMem(sizeof(int) * pPhrase->fmt_count, (void **)&fmt_list); /* Update the phrase pointer in case it changed */ pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase); pPhrase->fmt_list = tmp; /* Initialize */ for (size_t i=0; i<pPhrase->fmt_count; i++) { fmt_list[i] = -1; } /* Now we need to read again... this time into the format buffer */ const char *in_ptr = value; const char *idx_ptr = NULL; char *out_ptr = NULL; unsigned int cur_idx = 0; state = Parse_None; while (*in_ptr != '\0') { if (state == Parse_None) { if (*in_ptr == '{') { state = Parse_Index; idx_ptr = NULL; } } else if (state == Parse_Index) { if (*in_ptr == ':') { /* Check the number! */ if (!idx_ptr) { ParseWarning("Format property contains unindexed format string on line %d, phrase will be ignored.", states->line); m_CurPhrase = -1; return SMCResult_Continue; } long idx = strtol(idx_ptr, NULL, 10); if (idx < 1 || idx > (long)pPhrase->fmt_count) { ParseWarning("Format property contains invalid index '%d' on line %d, phrase will be ignored.", idx, states->line); m_CurPhrase = -1; return SMCResult_Continue; } else if (fmt_list[idx - 1] != -1) { ParseWarning("Format property contains duplicated index '%d' on line %d, phrase will be ignored.", idx, states->line); m_CurPhrase = -1; return SMCResult_Continue; } cur_idx = (unsigned int)idx; state = Parse_Format; out_ptr = NULL; } else if (!idx_ptr) { idx_ptr = in_ptr; } } else if (state == Parse_Format) { if (*in_ptr == '}') { if (!out_ptr) { ParseWarning("Format property contains empty format string on line %d, phrase will be ignored.", states->line); m_CurPhrase = -1; return SMCResult_Continue; } *out_ptr = '\0'; state = Parse_None; /* Now, add this to our table */ int tmp_idx = m_pStringTab->AddString(fmt_buf); /* Update pointers and update necessary variables */ pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase); pPhrase->fmt_bytes += strlen(fmt_buf); fmt_list = (int *)m_pMemory->GetAddress(pPhrase->fmt_list); fmt_list[cur_idx - 1] = tmp_idx; } else { if (!out_ptr) { out_ptr = fmt_buf; *out_ptr++ = '%'; } /* Check length ... */ if ((unsigned)(out_ptr - fmt_buf) >= sizeof(fmt_buf) - 1) { ParseWarning("Format property contains format string that exceeds maximum length on line %d, phrase will be ignored.", states->line); m_CurPhrase = -1; return SMCResult_Continue; } *out_ptr++ = *in_ptr; } } in_ptr++; } /* If we've gotten here, we only accepted unique indexes in a range. * Therefore, the list has to be completely filled. Double check anyway. */ for (size_t i=0; i<pPhrase->fmt_count; i++) { if (fmt_list[i] == -1) { ParseWarning("Format property contains no string for index %d on line %d, phrase will be ignored.", i + 1, states->line); m_CurPhrase = -1; return SMCResult_Continue; } } } else { size_t len = strlen(key); if (len < 2 || len > 3) { ParseWarning("Ignoring translation to invalid language \"%s\" on line %d.", key, states->line); return SMCResult_Continue; } unsigned int lang; if (!m_pTranslator->GetLanguageByCode(key, &lang)) { /* Ignore if we don't have a language. * :IDEA: issue a one-time alert? */ return SMCResult_Continue; } /* See how many bytes we need for this string, then allocate. * NOTE: THIS SHOULD GUARANTEE THAT WE DO NOT NEED TO NEED TO SIZE CHECK */ len = strlen(value) + pPhrase->fmt_bytes + 1; char *out_buf; int out_idx; out_idx = m_pMemory->CreateMem(len, (void **)&out_buf); /* Update pointer */ pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase); int *fmt_order; int *fmt_list = (int *)m_pMemory->GetAddress(pPhrase->fmt_list); trans_t *pTrans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl); pTrans = &pTrans[lang]; pTrans->stridx = out_idx; bool params[MAX_TRANSLATE_PARAMS]; /* Build the format order list, if necessary */ if (fmt_list) { int tmp = m_pMemory->CreateMem(pPhrase->fmt_count * sizeof(int), (void **)&fmt_order); /* Update pointers */ pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase); pTrans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl); fmt_list = (int *)m_pMemory->GetAddress(pPhrase->fmt_list); out_buf = (char *)m_pMemory->GetAddress(out_idx); pTrans = &pTrans[lang]; /* Now it's safe to save the index */ pTrans->fmt_order = tmp; for (unsigned int i=0; i<pPhrase->fmt_count; i++) { fmt_order[i] = -1; } memset(¶ms[0], 0, sizeof(params)); } const char *in_ptr = value; char *out_ptr = out_buf; unsigned int order_idx = 0; while (*in_ptr != '\0') { if (*in_ptr == '\\') { switch (*(in_ptr + 1)) { case '\n': *out_ptr++ = '\n'; break; case '\t': *out_ptr++ = '\t'; break; case '\r': *out_ptr++ = '\r'; break; case '{': *out_ptr++ = '{'; break; default: /* Copy both bytes since we don't know what's going on */ *out_ptr++ = *in_ptr++; *out_ptr++ = *in_ptr; break; } /* Skip past the last byte read */ in_ptr++; } else if (*in_ptr == '{' && fmt_list != NULL) { /* Search for parameters if this is a formatted string */ const char *scrap_in_point = in_ptr; const char *digit_start = ++in_ptr; unsigned int bytes; while (*in_ptr != '\0') { bytes = textparsers->GetUTF8CharBytes(in_ptr); if (bytes != 1) { goto scrap_point; } if (*in_ptr == '}') { /* Did we get an index? */ if (in_ptr == digit_start) { goto scrap_point; } /* Is it valid? */ long idx = strtol(digit_start, NULL, 10); if (idx < 1 || idx > (int)pPhrase->fmt_count) { goto scrap_point; } if (params[idx-1]) { goto scrap_point; } /* We're safe to insert the string. First mark order. */ fmt_order[order_idx++] = (int)idx - 1; /* Now concatenate */ out_ptr += sprintf(out_ptr, "%s", m_pStringTab->GetString(fmt_list[idx-1])); /* Mark as used */ params[idx-1] = true; goto cont_loop; } in_ptr++; } scrap_point: /* Pretend none of this ever happened. Move along now! */ in_ptr = scrap_in_point; *out_ptr++ = *in_ptr; } else { *out_ptr++ = *in_ptr; } cont_loop: in_ptr++; } *out_ptr = '\0'; pPhrase->translations++; } return SMCResult_Continue; }
void Read_extension (P_WBXML_INFO buffer) { if (Is_switchPage(buffer)) { Read_switchPage(buffer); } if (IsTag(buffer, TAG_EXT_I_0)) { char* str = NULL; ReadFixedTag(buffer, TAG_EXT_I_0); Read_termstr_rtn(buffer, &str); AddVariableStringNode(buffer, str, VAR_ESCAPED); } else if (IsTag(buffer, TAG_EXT_I_1)) { char* str = NULL; ReadFixedTag(buffer, TAG_EXT_I_1); Read_termstr_rtn(buffer, &str); AddVariableStringNode(buffer, str, VAR_UNESCAPED); } else if (IsTag(buffer, TAG_EXT_I_2)) { char* str = NULL; ReadFixedTag(buffer, TAG_EXT_I_2); Read_termstr_rtn(buffer, &str); AddVariableStringNode(buffer, str, VAR_UNCHANGED); } else if (IsTag(buffer, TAG_EXT_T_0)) { WBXML_MB_U_INT32 index; ReadFixedTag(buffer, TAG_EXT_T_0); Read_index(buffer, &index); AddVariableIndexNode(buffer, index, VAR_ESCAPED); } else if (IsTag(buffer, TAG_EXT_T_1)) { WBXML_MB_U_INT32 index; ReadFixedTag(buffer, TAG_EXT_T_1); Read_index(buffer, &index); AddVariableIndexNode(buffer, index, VAR_UNESCAPED); } else if (IsTag(buffer, TAG_EXT_T_2)) { WBXML_MB_U_INT32 index; ReadFixedTag(buffer, TAG_EXT_T_2); Read_index(buffer, &index); AddVariableIndexNode(buffer, index, VAR_UNCHANGED); } else if (IsTag(buffer, TAG_EXT_0)) { ReadFixedTag(buffer, TAG_EXT_0); ParseWarning(WARN_FUTURE_EXPANSION_EXT_0); } else if (IsTag(buffer, TAG_EXT_1)) { ReadFixedTag(buffer, TAG_EXT_1); ParseWarning(WARN_FUTURE_EXPANSION_EXT_1); } else if (IsTag(buffer, TAG_EXT_2)) { ReadFixedTag(buffer, TAG_EXT_2); ParseWarning(WARN_FUTURE_EXPANSION_EXT_2); } else { ParseError(ERR_TAG_NOT_FOUND); } }
SMCResult CPhraseFile::ReadSMC_NewSection(const SMCStates *states, const char *name) { bool recognized = false; if (m_ParseState == PPS_None) { if (strcmp(name, "Phrases") == 0) { m_ParseState = PPS_Phrases; recognized = true; } } else if (m_ParseState == PPS_Phrases) { m_ParseState = PPS_InPhrase; recognized = true; void *value; if (sm_trie_retrieve(m_pPhraseLookup, name, &value)) { m_CurPhrase = reinterpret_cast<int>(value); } else { phrase_t *pPhrase; m_CurPhrase = m_pMemory->CreateMem(sizeof(phrase_t), (void **)&pPhrase); sm_trie_insert(m_pPhraseLookup, name, reinterpret_cast<void *>(m_CurPhrase)); /* Initialize new phrase */ trans_t *pTrans; pPhrase->fmt_count = 0; pPhrase->fmt_list = -1; int trans_tbl = m_pMemory->CreateMem(sizeof(trans_t) * m_LangCount, (void **)&pTrans); pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase); pPhrase->trans_tbl = trans_tbl; pPhrase->translations = 0; pPhrase->fmt_bytes = 0; for (unsigned int i=0; i<m_LangCount; i++) { pTrans[i].stridx = -1; } } m_LastPhraseString.assign(name); } else if (m_ParseState == PPS_InPhrase) { ParseError("Phrase sections may not have sub-sections"); return SMCResult_HaltFail; } if (!recognized) { ParseWarning("Ignoring invalid section \"%s\" on line %d.", name, states->line); } return SMCResult_Continue; }