/* =========================================================================== Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). Doom 3 Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 Source Code. If not, see . In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #include "sys/platform.h" #include "idlib/Lexer.h" #include "idlib/Lib.h" #include "framework/CVarSystem.h" #include "idlib/CmdArgs.h" /* ============ idCmdArgs::operator= ============ */ void idCmdArgs::operator=( const idCmdArgs &args ) { int i; argc = args.argc; memcpy( tokenized, args.tokenized, MAX_COMMAND_STRING ); for ( i = 0; i < argc; i++ ) { argv[ i ] = tokenized + ( args.argv[ i ] - args.tokenized ); } } /* ============ idCmdArgs::Args ============ */ const char *idCmdArgs::Args( int start, int end, bool escapeArgs ) const { static char cmd_args[MAX_COMMAND_STRING]; int i; if ( end < 0 ) { end = argc - 1; } else if ( end >= argc ) { end = argc - 1; } cmd_args[0] = '\0'; if ( escapeArgs ) { strcat( cmd_args, "\"" ); } for ( i = start; i <= end; i++ ) { if ( i > start ) { if ( escapeArgs ) { strcat( cmd_args, "\" \"" ); } else { strcat( cmd_args, " " ); } } if ( escapeArgs && strchr( argv[i], '\\' ) ) { char *p = argv[i]; while ( *p != '\0' ) { if ( *p == '\\' ) { strcat( cmd_args, "\\\\" ); } else { int l = strlen( cmd_args ); cmd_args[ l ] = *p; cmd_args[ l+1 ] = '\0'; } p++; } } else { strcat( cmd_args, argv[i] ); } } if ( escapeArgs ) { strcat( cmd_args, "\"" ); } return cmd_args; } /* ============ idCmdArgs::TokenizeString Parses the given string into command line tokens. The text is copied to a separate buffer and 0 characters are inserted in the appropriate place. The argv array will point into this temporary buffer. ============ */ void idCmdArgs::TokenizeString( const char *text, bool keepAsStrings ) { idLexer lex; idToken token, number; int len, totalLen; // clear previous args argc = 0; if ( !text ) { return; } lex.LoadMemory( text, strlen( text ), "idCmdSystemLocal::TokenizeString" ); lex.SetFlags( LEXFL_NOERRORS | LEXFL_NOWARNINGS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWIPADDRESSES | ( keepAsStrings ? LEXFL_ONLYSTRINGS : 0 ) ); totalLen = 0; while ( 1 ) { if ( argc == MAX_COMMAND_ARGS ) { return; // this is usually something malicious } if ( !lex.ReadToken( &token ) ) { return; } // check for negative numbers if ( !keepAsStrings && ( token == "-" ) ) { if ( lex.CheckTokenType( TT_NUMBER, 0, &number ) ) { token = "-" + number; } } // check for cvar expansion if ( token == "$" ) { if ( !lex.ReadToken( &token ) ) { return; } if ( idLib::cvarSystem ) { token = idLib::cvarSystem->GetCVarString( token.c_str() ); } else { token = ""; } } len = token.Length(); if ( totalLen + len + 1 > sizeof( tokenized ) ) { return; // this is usually something malicious } // regular token argv[argc] = tokenized + totalLen; argc++; idStr::Copynz( tokenized + totalLen, token.c_str(), sizeof( tokenized ) - totalLen ); totalLen += len + 1; } } /* ============ idCmdArgs::AppendArg ============ */ void idCmdArgs::AppendArg( const char *text ) { if ( !argc ) { argc = 1; argv[ 0 ] = tokenized; idStr::Copynz( tokenized, text, sizeof( tokenized ) ); } else { argv[ argc ] = argv[ argc-1 ] + strlen( argv[ argc-1 ] ) + 1; idStr::Copynz( argv[ argc ], text, sizeof( tokenized ) - ( argv[ argc ] - tokenized ) ); argc++; } } /* ============ idCmdArgs::GetArgs ============ */ const char **idCmdArgs::GetArgs( int *_argc ) { *_argc = argc; return (const char **)&argv[0]; }