//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int ReadValue(source_t *source, float *value) { token_t token; if (!PC_ExpectAnyToken(source, &token)) return qfalse; if (!strcmp(token.string, "-")) { SourceWarning(source, "negative value set to zero"); if(!PC_ExpectAnyToken(source, &token)) { SourceError(source, "Missing return value"); return qfalse; } } if (token.type != TT_NUMBER) { SourceError(source, "invalid return value %s", token.string); return qfalse; } *value = token.floatvalue; return qtrue; } //end of the function ReadValue
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int LoadCfgFile( char *filename ) { source_t *source; token_t token; int settingsdefined; source = LoadSourceFile( filename ); if ( !source ) { Log_Print( "couldn't open cfg file %s\n", filename ); return false; } //end if settingsdefined = false; memset( &cfg, 0, sizeof( cfg_t ) ); while ( PC_ReadToken( source, &token ) ) { if ( !stricmp( token.string, "bbox" ) ) { if ( cfg.numbboxes >= AAS_MAX_BBOXES ) { SourceError( source, "too many bounding box volumes defined" ); } //end if if ( !ReadStructure( source, &bbox_struct, (char *) &cfg.bboxes[cfg.numbboxes] ) ) { FreeSource( source ); return false; } //end if cfg.allpresencetypes |= cfg.bboxes[cfg.numbboxes].presencetype; cfg.numbboxes++; } //end if else if ( !stricmp( token.string, "settings" ) ) { if ( settingsdefined ) { SourceWarning( source, "settings already defined\n" ); } //end if settingsdefined = true; if ( !ReadStructure( source, &cfg_struct, (char *) &cfg ) ) { FreeSource( source ); return false; } //end if } //end else if } //end while if ( VectorLength( cfg.phys_gravitydirection ) < 0.9 || VectorLength( cfg.phys_gravitydirection ) > 1.1 ) { SourceError( source, "invalid gravity direction specified" ); } //end if if ( cfg.numbboxes <= 0 ) { SourceError( source, "no bounding volumes specified" ); } //end if FreeSource( source ); SetCfgLibVars(); Log_Print( "using cfg file %s\n", filename ); return true; } //end of the function LoadCfgFile
/* * ErrorBox - show an error message in a dialog box */ void ErrorBox( char *str, ... ) { va_list al; char tmp[MAX_STR]; if( MessageWindow != NO_WINDOW ) { WindowAuxUpdate( MessageWindow, WIND_INFO_TEXT_COLOR, messagew_info.hilight.foreground ); WindowAuxUpdate( MessageWindow, WIND_INFO_BACKGROUND_COLOR, messagew_info.hilight.background ); va_start( al, str ); MyVSprintf( tmp, str, al ); va_end( al ); SourceError( tmp ); Message1Box( "%s", tmp ); WindowAuxUpdate( MessageWindow, WIND_INFO_TEXT_COLOR, messagew_info.text.foreground ); WindowAuxUpdate( MessageWindow, WIND_INFO_BACKGROUND_COLOR, messagew_info.text.background ); MyBeep(); } else { va_start( al, str ); #ifndef __WIN__ MyVPrintf( str, al ); MyPrintf( "\n" ); #endif va_end( al ); } } /* Error */
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== weightconfig_t *ReadWeightConfig( char *filename ) { int newindent, avail = 0, n; token_t token; source_t *source; fuzzyseperator_t *fs; weightconfig_t *config = NULL; #ifdef DEBUG int starttime; starttime = Sys_MilliSeconds(); #endif //DEBUG if ( !LibVarGetValue( "bot_reloadcharacters" ) ) { avail = -1; for ( n = 0; n < MAX_WEIGHT_FILES; n++ ) { config = weightFileList[n]; if ( !config ) { if ( avail == -1 ) { avail = n; } //end if continue; } //end if if ( strcmp( filename, config->filename ) == 0 ) { //botimport.Print( PRT_MESSAGE, "retained %s\n", filename ); return config; } //end if } //end for if ( avail == -1 ) { botimport.Print( PRT_ERROR, "weightFileList was full trying to load %s\n", filename ); return NULL; } //end if } //end if source = LoadSourceFile( filename ); if ( !source ) { botimport.Print( PRT_ERROR, "counldn't load %s\n", filename ); return NULL; } //end if // config = (weightconfig_t *) GetClearedMemory( sizeof( weightconfig_t ) ); config->numweights = 0; Q_strncpyz( config->filename, filename, sizeof( config->filename ) ); //parse the item config file while ( PC_ReadToken( source, &token ) ) { if ( !strcmp( token.string, "weight" ) ) { if ( config->numweights >= MAX_WEIGHTS ) { SourceWarning( source, "too many fuzzy weights" ); break; } //end if if ( !PC_ExpectTokenType( source, TT_STRING, 0, &token ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if StripDoubleQuotes( token.string ); config->weights[config->numweights].name = (char *) GetClearedMemory( strlen( token.string ) + 1 ); strcpy( config->weights[config->numweights].name, token.string ); if ( !PC_ExpectAnyToken( source, &token ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if newindent = qfalse; if ( !strcmp( token.string, "{" ) ) { newindent = qtrue; if ( !PC_ExpectAnyToken( source, &token ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if } //end if if ( !strcmp( token.string, "switch" ) ) { fs = ReadFuzzySeperators_r( source ); if ( !fs ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if config->weights[config->numweights].firstseperator = fs; } //end if else if ( !strcmp( token.string, "return" ) ) { fs = (fuzzyseperator_t *) GetClearedMemory( sizeof( fuzzyseperator_t ) ); fs->index = 0; fs->value = MAX_INVENTORYVALUE; fs->next = NULL; fs->child = NULL; if ( !ReadFuzzyWeight( source, fs ) ) { FreeMemory( fs ); FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if config->weights[config->numweights].firstseperator = fs; } //end else if else { SourceError( source, "invalid name %s", token.string ); FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end else if ( newindent ) { if ( !PC_ExpectTokenString( source, "}" ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if } //end if config->numweights++; } //end if else { SourceError( source, "invalid name %s", token.string ); FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end else } //end while //free the source at the end of a pass FreeSource( source ); //if the file was located in a pak file botimport.Print( PRT_MESSAGE, "loaded %s\n", filename ); #ifdef DEBUG if ( botDeveloper ) { botimport.Print( PRT_MESSAGE, "weights loaded in %d msec\n", Sys_MilliSeconds() - starttime ); } //end if #endif //DEBUG // if ( !LibVarGetValue( "bot_reloadcharacters" ) ) { weightFileList[avail] = config; } //end if // return config; } //end of the function ReadWeightConfig
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== fuzzyseperator_t *ReadFuzzySeperators_r( source_t *source ) { int newindent, index, def, founddefault; token_t token; fuzzyseperator_t *fs, *lastfs, *firstfs; founddefault = qfalse; firstfs = NULL; lastfs = NULL; if ( !PC_ExpectTokenString( source, "(" ) ) { return NULL; } if ( !PC_ExpectTokenType( source, TT_NUMBER, TT_INTEGER, &token ) ) { return NULL; } index = token.intvalue; if ( !PC_ExpectTokenString( source, ")" ) ) { return NULL; } if ( !PC_ExpectTokenString( source, "{" ) ) { return NULL; } if ( !PC_ExpectAnyToken( source, &token ) ) { return NULL; } do { def = !strcmp( token.string, "default" ); if ( def || !strcmp( token.string, "case" ) ) { fs = (fuzzyseperator_t *) GetClearedMemory( sizeof( fuzzyseperator_t ) ); fs->index = index; if ( lastfs ) { lastfs->next = fs; } else { firstfs = fs;} lastfs = fs; if ( def ) { if ( founddefault ) { SourceError( source, "switch already has a default" ); FreeFuzzySeperators_r( firstfs ); return NULL; } //end if fs->value = MAX_INVENTORYVALUE; founddefault = qtrue; } //end if else { if ( !PC_ExpectTokenType( source, TT_NUMBER, TT_INTEGER, &token ) ) { FreeFuzzySeperators_r( firstfs ); return NULL; } //end if fs->value = token.intvalue; } //end else if ( !PC_ExpectTokenString( source, ":" ) || !PC_ExpectAnyToken( source, &token ) ) { FreeFuzzySeperators_r( firstfs ); return NULL; } //end if newindent = qfalse; if ( !strcmp( token.string, "{" ) ) { newindent = qtrue; if ( !PC_ExpectAnyToken( source, &token ) ) { FreeFuzzySeperators_r( firstfs ); return NULL; } //end if } //end if if ( !strcmp( token.string, "return" ) ) { if ( !ReadFuzzyWeight( source, fs ) ) { FreeFuzzySeperators_r( firstfs ); return NULL; } //end if } //end if else if ( !strcmp( token.string, "switch" ) ) { fs->child = ReadFuzzySeperators_r( source ); if ( !fs->child ) { FreeFuzzySeperators_r( firstfs ); return NULL; } //end if } //end else if else { SourceError( source, "invalid name %s", token.string ); return NULL; } //end else if ( newindent ) { if ( !PC_ExpectTokenString( source, "}" ) ) { FreeFuzzySeperators_r( firstfs ); return NULL; } //end if } //end if } //end if else { FreeFuzzySeperators_r( firstfs ); SourceError( source, "invalid name %s", token.string ); return NULL; } //end else if ( !PC_ExpectAnyToken( source, &token ) ) { FreeFuzzySeperators_r( firstfs ); return NULL; } //end if } while ( strcmp( token.string, "}" ) ); // if ( !founddefault ) { SourceWarning( source, "switch without default" ); fs = (fuzzyseperator_t *) GetClearedMemory( sizeof( fuzzyseperator_t ) ); fs->index = index; fs->value = MAX_INVENTORYVALUE; fs->weight = 0; fs->next = NULL; fs->child = NULL; if ( lastfs ) { lastfs->next = fs; } else { firstfs = fs;} } //end if // return firstfs; } //end of the function ReadFuzzySeperators_r
/* ======================================================================================================================================= ReadNumber ======================================================================================================================================= */ qboolean ReadNumber(source_t *source, fielddef_t *fd, void *p) { token_t token; int negative = qfalse; long int intval, intmin = 0, intmax = 0; double floatval; if (!PC_ExpectAnyToken(source, &token)) { return 0; } // check for minus sign if (token.type == TT_PUNCTUATION) { if (fd->type & FT_UNSIGNED) { SourceError(source, "expected unsigned value, found %s", token.string); return 0; } // if not a minus sign if (strcmp(token.string, "-")) { SourceError(source, "unexpected punctuation %s", token.string); return 0; } negative = qtrue; // read the number if (!PC_ExpectAnyToken(source, &token)) { return 0; } } // check if it is a number if (token.type != TT_NUMBER) { SourceError(source, "expected number, found %s", token.string); return 0; } // check for a float value if (token.subtype & TT_FLOAT) { if ((fd->type & FT_TYPE) != FT_FLOAT) { SourceError(source, "unexpected float"); return 0; } floatval = token.floatvalue; if (negative) { floatval = -floatval; } if (fd->type & FT_BOUNDED) { if (floatval < fd->floatmin || floatval > fd->floatmax) { SourceError(source, "float out of range [%f, %f]", fd->floatmin, fd->floatmax); return 0; } } *(float *)p = (float)floatval; return 1; } intval = token.intvalue; if (negative) { intval = -intval; } // check bounds if ((fd->type & FT_TYPE) == FT_CHAR) { if (fd->type & FT_UNSIGNED) { intmin = 0; intmax = 255; } else { intmin = -128; intmax = 127; } } if ((fd->type & FT_TYPE) == FT_INT) { if (fd->type & FT_UNSIGNED) { intmin = 0; intmax = 65535; } else { intmin = -32768; intmax = 32767; } } if ((fd->type & FT_TYPE) == FT_CHAR || (fd->type & FT_TYPE) == FT_INT) { if (fd->type & FT_BOUNDED) { intmin = Maximum(intmin, fd->floatmin); intmax = Minimum(intmax, fd->floatmax); } if (intval < intmin || intval > intmax) { SourceError(source, "value %ld out of range [%ld, %ld]", intval, intmin, intmax); return 0; } } else if ((fd->type & FT_TYPE) == FT_FLOAT) { if (fd->type & FT_BOUNDED) { if (intval < fd->floatmin || intval > fd->floatmax) { SourceError(source, "value %ld out of range [%f, %f]", intval, fd->floatmin, fd->floatmax); return 0; } } } // store the value if ((fd->type & FT_TYPE) == FT_CHAR) { if (fd->type & FT_UNSIGNED) { *(unsigned char *)p = (unsigned char)intval; } else { *(char *)p = (char)intval; } } else if ((fd->type & FT_TYPE) == FT_INT) { if (fd->type & FT_UNSIGNED) { *(unsigned int *)p = (unsigned int)intval; } else { *(int *)p = (int)intval; } } else if ((fd->type & FT_TYPE) == FT_FLOAT) { *(float *)p = (float)intval; } return 1; }
/* ======================================================================================================================================= ReadStructure ======================================================================================================================================= */ int ReadStructure(source_t *source, structdef_t *def, char *structure) { token_t token; fielddef_t *fd; void *p; int num; if (!PC_ExpectTokenString(source, "{")) { return 0; } while (1) { if (!PC_ExpectAnyToken(source, &token)) { return qfalse; } // if end of structure if (!strcmp(token.string, "}")) { break; } // find the field with the name fd = FindField(def->fields, token.string); if (!fd) { SourceError(source, "unknown structure field %s", token.string); return qfalse; } if (fd->type & FT_ARRAY) { num = fd->maxarray; if (!PC_ExpectTokenString(source, "{")) { return qfalse; } } else { num = 1; } p = (void *)(structure + fd->offset); while (num-- > 0) { if (fd->type & FT_ARRAY) { if (PC_CheckTokenString(source, "}")) { break; } } switch (fd->type & FT_TYPE) { case FT_CHAR: { if (!ReadChar(source, fd, p)) { return qfalse; } p = (char *)p + sizeof(char); break; } case FT_INT: { if (!ReadNumber(source, fd, p)) { return qfalse; } p = (char *)p + sizeof(int); break; } case FT_FLOAT: { if (!ReadNumber(source, fd, p)) { return qfalse; } p = (char *)p + sizeof(float); break; } case FT_STRING: { if (!ReadString(source, fd, p)) { return qfalse; } p = (char *)p + MAX_STRINGFIELD; break; } case FT_STRUCT: { if (!fd->substruct) { SourceError(source, "BUG: no sub structure defined"); return qfalse; } ReadStructure(source, fd->substruct, (char *)p); p = (char *)p + fd->substruct->size; break; } } if (fd->type & FT_ARRAY) { if (!PC_ExpectAnyToken(source, &token)) { return qfalse; } if (!strcmp(token.string, "}")) { break; } if (strcmp(token.string, ",")) { SourceError(source, "expected a comma, found %s", token.string); return qfalse; } } } } return qtrue; }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== bot_character_t *BotLoadCharacterFromFile( char *charfile, int skill ) { int indent, index, foundcharacter; bot_character_t *ch; source_t *source; token_t token; foundcharacter = qfalse; //a bot character is parsed in two phases PS_SetBaseFolder( "botfiles" ); source = LoadSourceFile( charfile ); PS_SetBaseFolder( "" ); if ( !source ) { botimport.Print( PRT_ERROR, "counldn't load %s\n", charfile ); return NULL; } //end if ch = ( bot_character_t * ) GetClearedMemory( sizeof( bot_character_t ) + MAX_CHARACTERISTICS * sizeof( bot_characteristic_t ) ); strcpy( ch->filename, charfile ); while ( PC_ReadToken( source, &token ) ) { if ( !strcmp( token.string, "skill" ) ) { if ( !PC_ExpectTokenType( source, TT_NUMBER, 0, &token ) ) { FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if if ( !PC_ExpectTokenString( source, "{" ) ) { FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if //if it's the correct skill if ( skill < 0 || token.intvalue == skill ) { foundcharacter = qtrue; ch->skill = token.intvalue; while ( PC_ExpectAnyToken( source, &token ) ) { if ( !strcmp( token.string, "}" ) ) { break; } if ( token.type != TT_NUMBER || !( token.subtype & TT_INTEGER ) ) { SourceError( source, "expected integer index, found %s\n", token.string ); FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if index = token.intvalue; if ( index < 0 || index > MAX_CHARACTERISTICS ) { SourceError( source, "characteristic index out of range [0, %d]\n", MAX_CHARACTERISTICS ); FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if if ( ch->c[ index ].type ) { SourceError( source, "characteristic %d already initialized\n", index ); FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if if ( !PC_ExpectAnyToken( source, &token ) ) { FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if if ( token.type == TT_NUMBER ) { if ( token.subtype & TT_FLOAT ) { ch->c[ index ].value._float = token.floatvalue; ch->c[ index ].type = CT_FLOAT; } //end if else { ch->c[ index ].value.integer = token.intvalue; ch->c[ index ].type = CT_INTEGER; } //end else } //end if else if ( token.type == TT_STRING ) { StripDoubleQuotes( token.string ); ch->c[ index ].value.string = GetMemory( strlen( token.string ) + 1 ); strcpy( ch->c[ index ].value.string, token.string ); ch->c[ index ].type = CT_STRING; } //end else if else { SourceError( source, "expected integer, float or string, found %s\n", token.string ); FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end else } //end if break; } //end if else { indent = 1; while ( indent ) { if ( !PC_ExpectAnyToken( source, &token ) ) { FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if if ( !strcmp( token.string, "{" ) ) { indent++; } else if ( !strcmp( token.string, "}" ) ) { indent--; } } //end while } //end else } //end if else { SourceError( source, "unknown definition %s\n", token.string ); FreeSource( source ); BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end else } //end while FreeSource( source ); // if ( !foundcharacter ) { BotFreeCharacterStrings( ch ); FreeMemory( ch ); return NULL; } //end if return ch; } //end of the function BotLoadCharacterFromFile
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== itemconfig_t *LoadItemConfig( char *filename ) { int max_iteminfo; token_t token; char path[MAX_PATH]; source_t *source; itemconfig_t *ic; iteminfo_t *ii; max_iteminfo = (int) LibVarValue( "max_iteminfo", "256" ); if ( max_iteminfo < 0 ) { botimport.Print( PRT_ERROR, "max_iteminfo = %d\n", max_iteminfo ); max_iteminfo = 128; LibVarSet( "max_iteminfo", "128" ); } strncpy( path, filename, MAX_PATH ); source = LoadSourceFile( path ); if ( !source ) { botimport.Print( PRT_ERROR, "counldn't load %s\n", path ); return NULL; } //end if //initialize item config ic = (itemconfig_t *) GetClearedHunkMemory( sizeof( itemconfig_t ) + max_iteminfo * sizeof( iteminfo_t ) ); ic->iteminfo = ( iteminfo_t * )( (char *) ic + sizeof( itemconfig_t ) ); ic->numiteminfo = 0; //parse the item config file while ( PC_ReadToken( source, &token ) ) { if ( !strcmp( token.string, "iteminfo" ) ) { if ( ic->numiteminfo >= max_iteminfo ) { SourceError( source, "more than %d item info defined\n", max_iteminfo ); FreeMemory( ic ); FreeSource( source ); return NULL; } //end if ii = &ic->iteminfo[ic->numiteminfo]; memset( ii, 0, sizeof( iteminfo_t ) ); if ( !PC_ExpectTokenType( source, TT_STRING, 0, &token ) ) { FreeMemory( ic ); FreeMemory( source ); return NULL; } //end if StripDoubleQuotes( token.string ); strncpy( ii->classname, token.string, sizeof( ii->classname ) - 1 ); if ( !ReadStructure( source, &iteminfo_struct, (char *) ii ) ) { FreeMemory( ic ); FreeSource( source ); return NULL; } //end if ii->number = ic->numiteminfo; ic->numiteminfo++; } //end if else { SourceError( source, "unknown definition %s\n", token.string ); FreeMemory( ic ); FreeSource( source ); return NULL; } //end else } //end while FreeSource( source ); // if ( !ic->numiteminfo ) { botimport.Print( PRT_WARNING, "no item info loaded\n" ); } botimport.Print( PRT_MESSAGE, "loaded %s\n", path ); return ic; } //end of the function LoadItemConfig
void desugar (AST::ExpPtr& e) { auto span = e->span; if (auto var = dynamic_cast<AST::VarExp*>(e.get())) { desugarName(var->name); } else if (auto let = dynamic_cast<AST::LetExp*>(e.get())) { desugar(let->pattern); } else if (auto assign = dynamic_cast<AST::AssignExp*>(e.get())) { auto lh = assign->children[0]; auto rh = assign->children[1]; bool okay = false; if (auto mem = dynamic_cast<AST::MemberExp*>(lh.get())) { auto obj = mem->children[0]; auto what = mem->children[1]; auto span = assign->span; if (mem->kind == AST::MemberExp::Get) { // a[b] = c -> a.set(b, c) e = AST::methodCall(span, obj, Names::Set, { what, rh }); okay = true; } } else if (lh->is<AST::VarExp>() || lh->is<AST::PropertyExp>()) okay = true; if (!okay) throw SourceError("invalid left-hand of assignment", lh->span); } else if (auto mem = dynamic_cast<AST::MemberExp*>(e.get())) { auto obj = mem->children[0]; auto args = mem->children; // a[b] -> a.get(b) // a[b,] -> a.sub_from(b) // a[,b] -> a.sub_to(b) // a[b,c] -> a.sub(b, c) switch (mem->kind) { case AST::MemberExp::Slice: e = AST::methodCall(span, obj, Names::Slice, { args[1], args[2] }); break; case AST::MemberExp::SliceFrom: e = AST::methodCall(span, obj, Names::SliceFrom, { args[1] }); break; case AST::MemberExp::SliceTo: e = AST::methodCall(span, obj, Names::SliceTo, { args[1] }); break; case AST::MemberExp::Get: default: e = AST::methodCall(span, obj, Names::Get, { args[1] }); break; } } else if (auto cmp = dynamic_cast<AST::CompareExp*>(e.get())) { AST::ExpPtr res; auto a = cmp->children[0]; auto b = cmp->children[1]; // a == b -> a.equal(b) == true // a != b -> a.equal(b) == false // a > b -> a.cmp(b) > 0 // a < b -> a.cmp(b) < 0 // etc. if (cmp->kind == AST::CompareExp::Eq || cmp->kind == AST::CompareExp::NotEq) res = AST::methodCall(span, a, Names::Equal, { b }); else res = AST::methodCall(span, a, Names::Compare, { b }); e = AST::ExpPtr(new AST::CompareExp(res, cmp->kind)); e->span = span; } else if (auto obj = dynamic_cast<AST::ObjectExp*>(e.get())) { desugar(obj->objType); } else if (auto lam = dynamic_cast<AST::LambdaExp*>(e.get())) { for (auto arg : lam->args) if (arg.type != nullptr) desugar(arg.type); } else if (dynamic_cast<AST::ListExp*>(e.get())) { auto elems = e->children; // build linked list right to left auto res = AST::Exp::nil(span); for (size_t i = 0, len = elems.size(); i < len; i++) { auto elem = elems[len - i - 1]; res = AST::Exp::cons(elem->span, elem, res); } e = res; desugar(e); // again! return; } else if (auto block = dynamic_cast<AST::BlockExp*>(e.get())) { for (auto& c : e->children) { if (c == block->last) { desugar(block->last); c = block->last; } else desugar(c); } return; } else if (auto match = dynamic_cast<AST::MatchExp*>(e.get())) { for (auto& pat : match->patterns) desugar(pat); } for (auto& c : e->children) desugar(c); }
static itemconfig_t* LoadItemConfig( const char* filename ) { int max_iteminfo = ( int )LibVarValue( "max_iteminfo", "256" ); if ( max_iteminfo < 0 ) { BotImport_Print( PRT_ERROR, "max_iteminfo = %d\n", max_iteminfo ); max_iteminfo = 256; LibVarSet( "max_iteminfo", "256" ); } if ( GGameType & GAME_Quake3 ) { PC_SetBaseFolder( BOTFILESBASEFOLDER ); } char path[ MAX_QPATH ]; String::NCpyZ( path, filename, MAX_QPATH ); source_t* source = LoadSourceFile( path ); if ( !source ) { BotImport_Print( PRT_ERROR, "counldn't load %s\n", path ); return NULL; } //initialize item config itemconfig_t* ic = ( itemconfig_t* )Mem_ClearedAlloc( sizeof ( itemconfig_t ) + max_iteminfo * sizeof ( iteminfo_t ) ); ic->iteminfo = ( iteminfo_t* )( ( char* )ic + sizeof ( itemconfig_t ) ); ic->numiteminfo = 0; //parse the item config file token_t token; while ( PC_ReadToken( source, &token ) ) { if ( !String::Cmp( token.string, "iteminfo" ) ) { if ( ic->numiteminfo >= max_iteminfo ) { SourceError( source, "more than %d item info defined\n", max_iteminfo ); Mem_Free( ic ); FreeSource( source ); return NULL; } iteminfo_t* ii = &ic->iteminfo[ ic->numiteminfo ]; Com_Memset( ii, 0, sizeof ( iteminfo_t ) ); if ( !PC_ExpectTokenType( source, TT_STRING, 0, &token ) ) { Mem_Free( ic ); FreeSource( source ); return NULL; } StripDoubleQuotes( token.string ); String::NCpy( ii->classname, token.string, sizeof ( ii->classname ) - 1 ); if ( !ReadStructure( source, &iteminfo_struct, ( char* )ii ) ) { Mem_Free( ic ); FreeSource( source ); return NULL; } ii->number = ic->numiteminfo; ic->numiteminfo++; } else { SourceError( source, "unknown definition %s\n", token.string ); Mem_Free( ic ); FreeSource( source ); return NULL; } } FreeSource( source ); if ( !ic->numiteminfo ) { BotImport_Print( PRT_WARNING, "no item info loaded\n" ); } BotImport_Print( PRT_MESSAGE, "loaded %s\n", path ); return ic; }