//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ReadNumber( script_t *script, token_t *token ) { int len = 0, i; int octal, dot; char c; // unsigned long int intvalue = 0; // long double floatvalue = 0; token->type = TT_NUMBER; //check for a hexadecimal number if ( *script->script_p == '0' && ( *( script->script_p + 1 ) == 'x' || *( script->script_p + 1 ) == 'X' ) ) { token->string[len++] = *script->script_p++; token->string[len++] = *script->script_p++; c = *script->script_p; //hexadecimal while ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'A' ) ) { token->string[len++] = *script->script_p++; if ( len >= MAX_TOKEN ) { ScriptError( script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN ); return 0; } //end if c = *script->script_p; } //end while token->subtype |= TT_HEX; } //end if #ifdef BINARYNUMBERS //check for a binary number else if ( *script->script_p == '0' && ( *( script->script_p + 1 ) == 'b' || *( script->script_p + 1 ) == 'B' ) ) { token->string[len++] = *script->script_p++; token->string[len++] = *script->script_p++; c = *script->script_p; //hexadecimal while ( c == '0' || c == '1' ) { token->string[len++] = *script->script_p++; if ( len >= MAX_TOKEN ) { ScriptError( script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN ); return 0; } //end if c = *script->script_p; } //end while token->subtype |= TT_BINARY; } //end if #endif //BINARYNUMBERS else //decimal or octal integer or floating point number { octal = qfalse; dot = qfalse; if ( *script->script_p == '0' ) { octal = qtrue; } while ( 1 ) { token->string[len++] = *script->script_p++; if ( len >= MAX_TOKEN ) { ScriptError( script, "number longer than MAX_TOKEN = %d", MAX_TOKEN ); return 0; } //end if c = *script->script_p; if ( c == '.' ) { dot = qtrue; } else if ( c == '8' || c == '9' ) { octal = qfalse; } else if ( c < '0' || c > '9' ) { break; } } //end while if ( octal ) { token->subtype |= TT_OCTAL; } else { token->subtype |= TT_DECIMAL;} if ( dot ) { token->subtype |= TT_FLOAT; } } //end else for ( i = 0; i < 2; i++ ) { c = *script->script_p; //check for a LONG number if ( c == 'l' || c == 'L' && !( token->subtype & TT_LONG ) ) { script->script_p++; token->subtype |= TT_LONG; } //end if //check for an UNSIGNED number else if ( c == 'u' || c == 'U' && !( token->subtype & ( TT_UNSIGNED | TT_FLOAT ) ) ) { script->script_p++; token->subtype |= TT_UNSIGNED; } //end if } //end for token->string[len] = '\0'; #ifdef NUMBERVALUE NumberValue( token->string, token->subtype, &token->intvalue, &token->floatvalue ); #endif //NUMBERVALUE if ( !( token->subtype & TT_FLOAT ) ) { token->subtype |= TT_INTEGER; } return 1; } //end of the function PS_ReadNumber
//============================================================================ // Reads an escape character. // // Parameter: script : script to read from // ch : place to store the read escape character // Returns: - // Changes Globals: - //============================================================================ int PS_ReadEscapeCharacter( script_t *script, char *ch ) { int c, val, i; //step over the leading '\\' script->script_p++; //determine the escape character switch ( *script->script_p ) { case '\\': c = '\\'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'a': c = '\a'; break; case '\'': c = '\''; break; case '\"': c = '\"'; break; case '\?': c = '\?'; break; case 'x': { script->script_p++; for ( i = 0, val = 0; ; i++, script->script_p++ ) { c = *script->script_p; if ( c >= '0' && c <= '9' ) { c = c - '0'; } else if ( c >= 'A' && c <= 'Z' ) { c = c - 'A' + 10; } else if ( c >= 'a' && c <= 'z' ) { c = c - 'a' + 10; } else { break;} val = ( val << 4 ) + c; } //end for script->script_p--; if ( val > 0xFF ) { ScriptWarning( script, "too large value in escape character" ); val = 0xFF; } //end if c = val; break; } //end case default: //NOTE: decimal ASCII code, NOT octal { if ( *script->script_p < '0' || *script->script_p > '9' ) { ScriptError( script, "unknown escape char" ); } for ( i = 0, val = 0; ; i++, script->script_p++ ) { c = *script->script_p; if ( c >= '0' && c <= '9' ) { c = c - '0'; } else { break;} val = val * 10 + c; } //end for script->script_p--; if ( val > 0xFF ) { ScriptWarning( script, "too large value in escape character" ); val = 0xFF; } //end if c = val; break; } //end default } //end switch //step over the escape character or the last digit of the number script->script_p++; //store the escape character *ch = c; //succesfully read escape character return 1; } //end of the function PS_ReadEscapeCharacter
//============================================================================ // Reads C-like string. Escape characters are interpretted. // Quotes are included with the string. // Reads two strings with a white space between them as one string. // // Parameter: script : script to read from // token : buffer to store the string // Returns: qtrue when a string was read succesfully // Changes Globals: - //============================================================================ int PS_ReadString( script_t *script, token_t *token, int quote ) { int len, tmpline; char *tmpscript_p; if ( quote == '\"' ) { token->type = TT_STRING; } else { token->type = TT_LITERAL;} len = 0; //leading quote token->string[len++] = *script->script_p++; // while ( 1 ) { //minus 2 because trailing double quote and zero have to be appended if ( len >= MAX_TOKEN - 2 ) { ScriptError( script, "string longer than MAX_TOKEN = %d", MAX_TOKEN ); return 0; } //end if //if there is an escape character and //if escape characters inside a string are allowed if ( *script->script_p == '\\' && !( script->flags & SCFL_NOSTRINGESCAPECHARS ) ) { if ( !PS_ReadEscapeCharacter( script, &token->string[len] ) ) { token->string[len] = 0; return 0; } //end if len++; } //end if //if a trailing quote else if ( *script->script_p == quote ) { //step over the double quote script->script_p++; //if white spaces in a string are not allowed if ( script->flags & SCFL_NOSTRINGWHITESPACES ) { break; } // tmpscript_p = script->script_p; tmpline = script->line; //read unusefull stuff between possible two following strings if ( !PS_ReadWhiteSpace( script ) ) { script->script_p = tmpscript_p; script->line = tmpline; break; } //end if //if there's no leading double qoute if ( *script->script_p != quote ) { script->script_p = tmpscript_p; script->line = tmpline; break; } //end if //step over the new leading double quote script->script_p++; } //end if else { if ( *script->script_p == '\0' ) { token->string[len] = 0; ScriptError( script, "missing trailing quote" ); return 0; } //end if if ( *script->script_p == '\n' ) { token->string[len] = 0; ScriptError( script, "newline inside string %s", token->string ); return 0; } //end if token->string[len++] = *script->script_p++; } //end else } //end while //trailing quote token->string[len++] = quote; //end string with a zero token->string[len] = '\0'; //the sub type is the length of the string token->subtype = len; return 1; } //end of the function PS_ReadString
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ReadPunctuation(script_t *script, token_t *token) { int len; char *p; punctuation_t *punc; #ifdef PUNCTABLE for (punc = script->punctuationtable[(unsigned int)*script->script_p]; punc; punc = punc->next) { #else int i; for (i = 0; script->punctuations[i].p; i++) { punc = &script->punctuations[i]; #endif //PUNCTABLE p = punc->p; len = strlen(p); //if the script contains at least as much characters as the punctuation if (script->script_p + len <= script->end_p) { //if the script contains the punctuation if (!strncmp(script->script_p, p, len)) { strncpy(token->string, p, MAX_TOKEN); script->script_p += len; token->type = TT_PUNCTUATION; //sub type is the number of the punctuation token->subtype = punc->n; return 1; } //end if } //end if } //end for return 0; } //end of the function PS_ReadPunctuation //============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ReadPrimitive(script_t *script, token_t *token) { int len; len = 0; while(*script->script_p > ' ' && *script->script_p != ';') { if (len >= MAX_TOKEN) { ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN); return 0; } //end if token->string[len++] = *script->script_p++; } //end while token->string[len] = 0; //copy the token into the script structure Com_Memcpy(&script->token, token, sizeof(token_t)); //primitive reading successfull return 1; } //end of the function PS_ReadPrimitive
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ReadToken(script_t *script, token_t *token) { //if there is a token available (from UnreadToken) if (script->tokenavailable) { script->tokenavailable = 0; Com_Memcpy(token, &script->token, sizeof(token_t)); return 1; } //end if //save script pointer script->lastscript_p = script->script_p; //save line counter script->lastline = script->line; //clear the token stuff Com_Memset(token, 0, sizeof(token_t)); //start of the white space script->whitespace_p = script->script_p; token->whitespace_p = script->script_p; //read unusefull stuff if (!PS_ReadWhiteSpace(script)) return 0; //end of the white space script->endwhitespace_p = script->script_p; token->endwhitespace_p = script->script_p; //line the token is on token->line = script->line; //number of lines crossed before token token->linescrossed = script->line - script->lastline; //if there is a leading double quote if (*script->script_p == '\"') { if (!PS_ReadString(script, token, '\"')) return 0; } //end if //if an literal else if (*script->script_p == '\'') { //if (!PS_ReadLiteral(script, token)) return 0; if (!PS_ReadString(script, token, '\'')) return 0; } //end if //if there is a number else if ((*script->script_p >= '0' && *script->script_p <= '9') || (*script->script_p == '.' && (*(script->script_p + 1) >= '0' && *(script->script_p + 1) <= '9'))) { if (!PS_ReadNumber(script, token)) return 0; } //end if //if this is a primitive script else if (script->flags & SCFL_PRIMITIVE) { return PS_ReadPrimitive(script, token); } //end else if //if there is a name else if ((*script->script_p >= 'a' && *script->script_p <= 'z') || (*script->script_p >= 'A' && *script->script_p <= 'Z') || *script->script_p == '_') { if (!PS_ReadName(script, token)) return 0; } //end if //check for punctuations else if (!PS_ReadPunctuation(script, token)) { ScriptError(script, "can't read token"); return 0; } //end if //copy the token into the script structure Com_Memcpy(&script->token, token, sizeof(token_t)); //succesfully read a token return 1; } //end of the function PS_ReadToken
void Interpreter::execute(const DirectoryName & root, ScriptType type, const ScriptName & name) { std::string scriptDir = root + "/scripts/"; std::string scriptDir2 = root + "/"; switch (type) { case rule: scriptDir += "rules/"; scriptDir2 += "rules/"; break; case transformation: scriptDir += "transformations/"; scriptDir2 += "transformations/"; break; } // first look at tcl rules std::string tclName = name; if (boost::algorithm::ends_with(tclName, ".tcl") == false) { tclName += ".tcl"; } if (boost::filesystem::exists(scriptDir + tclName)) { TclInterpreter::execute(root, type, scriptDir + tclName); return; } else if (boost::filesystem::exists(scriptDir2 + tclName)) { TclInterpreter::execute(root, type, scriptDir2 + tclName); return; } #ifdef VERA_PYTHON // then python std::string pyName = name; if (boost::algorithm::ends_with(pyName, ".py") == false) { pyName += ".py"; } if (boost::filesystem::exists(scriptDir + pyName)) { PythonInterpreter::execute(root, type, scriptDir + pyName); return; } else if (boost::filesystem::exists(scriptDir2 + pyName)) { PythonInterpreter::execute(root, type, scriptDir2 + pyName); return; } #endif #ifdef VERA_LUA // then lua std::string luaName = name; if (boost::algorithm::ends_with(luaName, ".lua") == false) { luaName += ".lua"; } if (boost::filesystem::exists(scriptDir + luaName)) { LuaInterpreter::execute(root, type, scriptDir + luaName); return; } else if (boost::filesystem::exists(scriptDir2 + luaName)) { LuaInterpreter::execute(root, type, scriptDir2 + luaName); return; } #endif std::ostringstream ss; ss << "cannot open script " << name; throw ScriptError(ss.str()); }
//============================================================================ // // Parameter: - // Returns: - // Changes Globals: - //============================================================================ int PS_ExpectTokenType( script_t *script, int type, int subtype, token_t *token ) { char str[MAX_TOKEN]; if ( !PS_ReadToken( script, token ) ) { ScriptError( script, "couldn't read expected token" ); return 0; } //end if if ( token->type != type ) { strcpy(str, ""); if ( type == TT_STRING ) { strcpy( str, "string" ); } if ( type == TT_LITERAL ) { strcpy( str, "literal" ); } if ( type == TT_NUMBER ) { strcpy( str, "number" ); } if ( type == TT_NAME ) { strcpy( str, "name" ); } if ( type == TT_PUNCTUATION ) { strcpy( str, "punctuation" ); } ScriptError( script, "expected a %s, found %s", str, token->string ); return 0; } //end if if ( token->type == TT_NUMBER ) { if ( ( token->subtype & subtype ) != subtype ) { strcpy(str, ""); if ( subtype & TT_DECIMAL ) { strcpy( str, "decimal" ); } if ( subtype & TT_HEX ) { strcpy( str, "hex" ); } if ( subtype & TT_OCTAL ) { strcpy( str, "octal" ); } if ( subtype & TT_BINARY ) { strcpy( str, "binary" ); } if ( subtype & TT_LONG ) { strcat( str, " long" ); } if ( subtype & TT_UNSIGNED ) { strcat( str, " unsigned" ); } if ( subtype & TT_FLOAT ) { strcat( str, " float" ); } if ( subtype & TT_INTEGER ) { strcat( str, " integer" ); } ScriptError( script, "expected %s, found %s", str, token->string ); return 0; } //end if } //end if else if ( token->type == TT_PUNCTUATION ) { if ( subtype < 0 ) { ScriptError( script, "BUG: wrong punctuation subtype" ); return 0; } //end if if ( token->subtype != subtype ) { ScriptError( script, "expected %s, found %s", script->punctuations[subtype].p, token->string); return 0; } //end if } //end else if return 1; } //end of the function PS_ExpectTokenType
void FScanner::MustGetValue(bool allowfloat) { if (!ScanValue(allowfloat)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected"); }
void FScanner::MustGetBoolToken() { if (!CheckBoolToken()) ScriptError("Expected true or false"); }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_ParseBSPEntities(void) { script_t *script; token_t token; bsp_entity_t *ent; bsp_epair_t *epair; script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata"); SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS);//SCFL_PRIMITIVE); bspworld.numentities = 1; while(PS_ReadToken(script, &token)) { if (strcmp(token.string, "{")) { ScriptError(script, "invalid %s\n", token.string); AAS_FreeBSPEntities(); FreeScript(script); return; } //end if if (bspworld.numentities >= MAX_BSPENTITIES) { botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n"); break; } //end if ent = &bspworld.entities[bspworld.numentities]; bspworld.numentities++; ent->epairs = NULL; while(PS_ReadToken(script, &token)) { if (!strcmp(token.string, "}")) break; epair = (bsp_epair_t *) GetClearedHunkMemory(sizeof(bsp_epair_t)); epair->next = ent->epairs; ent->epairs = epair; if (token.type != TT_STRING) { ScriptError(script, "invalid %s\n", token.string); AAS_FreeBSPEntities(); FreeScript(script); return; } //end if StripDoubleQuotes(token.string); epair->key = (char *) GetHunkMemory(strlen(token.string) + 1); strcpy(epair->key, token.string); if (!PS_ExpectTokenType(script, TT_STRING, 0, &token)) { AAS_FreeBSPEntities(); FreeScript(script); return; } //end if StripDoubleQuotes(token.string); epair->value = (char *) GetHunkMemory(strlen(token.string) + 1); strcpy(epair->value, token.string); } //end while if (strcmp(token.string, "}")) { ScriptError(script, "missing }\n"); AAS_FreeBSPEntities(); FreeScript(script); return; } //end if } //end while FreeScript(script); } //end of the function AAS_ParseBSPEntities
static bool PS_ReadNumber( script_t* script, token_t* token ) { int len = 0; token->type = TT_NUMBER; //check for a hexadecimal number if ( *script->script_p == '0' && ( *( script->script_p + 1 ) == 'x' || *( script->script_p + 1 ) == 'X' ) ) { token->string[ len++ ] = *script->script_p++; token->string[ len++ ] = *script->script_p++; char c = *script->script_p; //hexadecimal while ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'A' ) ) { token->string[ len++ ] = *script->script_p++; if ( len >= MAX_TOKEN ) { ScriptError( script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN ); return false; } c = *script->script_p; } token->subtype |= TT_HEX; } //check for a binary number else if ( *script->script_p == '0' && ( *( script->script_p + 1 ) == 'b' || *( script->script_p + 1 ) == 'B' ) ) { token->string[ len++ ] = *script->script_p++; token->string[ len++ ] = *script->script_p++; char c = *script->script_p; //binary while ( c == '0' || c == '1' ) { token->string[ len++ ] = *script->script_p++; if ( len >= MAX_TOKEN ) { ScriptError( script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN ); return 0; } c = *script->script_p; } token->subtype |= TT_BINARY; } else { //decimal or octal integer or floating point number bool octal = false; int dot = false; if ( *script->script_p == '0' ) { octal = true; } while ( 1 ) { char c = *script->script_p; if ( c == '.' ) { dot = true; } else if ( c == '8' || c == '9' ) { octal = false; } else if ( c < '0' || c > '9' ) { break; } token->string[ len++ ] = *script->script_p++; if ( len >= MAX_TOKEN - 1 ) { ScriptError( script, "number longer than MAX_TOKEN = %d", MAX_TOKEN ); return false; } } if ( octal ) { token->subtype |= TT_OCTAL; } else { token->subtype |= TT_DECIMAL; } if ( dot ) { token->subtype |= TT_FLOAT; } } for ( int i = 0; i < 2; i++ ) { char c = *script->script_p; //check for a LONG number if ( ( c == 'l' || c == 'L' ) && !( token->subtype & TT_LONG ) ) { script->script_p++; token->subtype |= TT_LONG; } //check for an UNSIGNED number else if ( ( c == 'u' || c == 'U' ) && !( token->subtype & ( TT_UNSIGNED | TT_FLOAT ) ) ) { script->script_p++; token->subtype |= TT_UNSIGNED; } } token->string[ len ] = '\0'; NumberValue( token->string, token->subtype, &token->intvalue, &token->floatvalue ); if ( !( token->subtype & TT_FLOAT ) ) { token->subtype |= TT_INTEGER; } return true; }
/* ======================================================================================================================================= AAS_ParseBSPEntities ======================================================================================================================================= */ void AAS_ParseBSPEntities(void) { script_t *script; token_t token; bsp_entity_t *ent; bsp_epair_t *epair; byte *buffer, *buftrav; int bufsize; // modified this, so that it first gathers up memory requirements, then allocates a single chunk, and places the strings all in there bspworld.ebuffer = NULL; script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata"); SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS); // SCFL_PRIMITIVE bufsize = 0; while (PS_ReadToken(script, &token)) { if (strcmp(token.string, "{")) { ScriptError(script, "invalid %s", token.string); AAS_FreeBSPEntities(); FreeScript(script); return; } if (bspworld.numentities >= MAX_BSPENTITIES) { botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n"); break; } while (PS_ReadToken(script, &token)) { if (!strcmp(token.string, "}")) { break; } bufsize += sizeof(bsp_epair_t); if (token.type != TT_STRING) { ScriptError(script, "invalid %s", token.string); AAS_FreeBSPEntities(); FreeScript(script); return; } StripDoubleQuotes(token.string); bufsize += strlen(token.string) + 1; if (!PS_ExpectTokenType(script, TT_STRING, 0, &token)) { AAS_FreeBSPEntities(); FreeScript(script); return; } StripDoubleQuotes(token.string); bufsize += strlen(token.string) + 1; } if (strcmp(token.string, "}")) { ScriptError(script, "missing}"); AAS_FreeBSPEntities(); FreeScript(script); return; } } FreeScript(script); buffer = (byte *)GetClearedHunkMemory(bufsize); buftrav = buffer; bspworld.ebuffer = buffer; // now parse the entities into memory // NOTE: removed error checks for speed, no need to do them twice script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata"); SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS); // SCFL_PRIMITIVE bspworld.numentities = 1; while (PS_ReadToken(script, &token)) { ent = &bspworld.entities[bspworld.numentities]; bspworld.numentities++; ent->epairs = NULL; while (PS_ReadToken(script, &token)) { if (!strcmp(token.string, "}")) { break; } epair = (bsp_epair_t *)buftrav; buftrav += sizeof(bsp_epair_t); epair->next = ent->epairs; ent->epairs = epair; StripDoubleQuotes(token.string); epair->key = (char *)buftrav; buftrav += (strlen(token.string) + 1); strcpy(epair->key, token.string); if (!PS_ExpectTokenType(script, TT_STRING, 0, &token)) { AAS_FreeBSPEntities(); FreeScript(script); return; } StripDoubleQuotes(token.string); epair->value = (char *)buftrav; buftrav += (strlen(token.string) + 1); strcpy(epair->value, token.string); } } FreeScript(script); }