CmdArgs.cpp (5124B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 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. 25 26 =========================================================================== 27 */ 28 29 #include "precompiled.h" 30 #pragma hdrstop 31 32 /* 33 ============ 34 idCmdArgs::operator= 35 ============ 36 */ 37 void idCmdArgs::operator=( const idCmdArgs &args ) { 38 int i; 39 40 argc = args.argc; 41 memcpy( tokenized, args.tokenized, MAX_COMMAND_STRING ); 42 for ( i = 0; i < argc; i++ ) { 43 argv[ i ] = tokenized + ( args.argv[ i ] - args.tokenized ); 44 } 45 } 46 47 /* 48 ============ 49 idCmdArgs::Args 50 ============ 51 */ 52 const char *idCmdArgs::Args( int start, int end, bool escapeArgs ) const { 53 static char cmd_args[MAX_COMMAND_STRING]; 54 int i; 55 56 assert( argc < MAX_COMMAND_ARGS ); 57 if ( end < 0 ) { 58 end = argc - 1; 59 } else if ( end >= argc ) { 60 end = argc - 1; 61 } 62 cmd_args[0] = '\0'; 63 if ( escapeArgs ) { 64 strcat( cmd_args, "\"" ); 65 } 66 for ( i = start; i <= end; i++ ) { 67 if ( i > start ) { 68 if ( escapeArgs ) { 69 strcat( cmd_args, "\" \"" ); 70 } else { 71 strcat( cmd_args, " " ); 72 } 73 } 74 if ( escapeArgs && strchr( argv[i], '\\' ) ) { 75 char *p = argv[i]; 76 while ( *p != '\0' ) { 77 if ( *p == '\\' ) { 78 strcat( cmd_args, "\\\\" ); 79 } else { 80 int l = strlen( cmd_args ); 81 cmd_args[ l ] = *p; 82 cmd_args[ l+1 ] = '\0'; 83 } 84 p++; 85 } 86 } else { 87 strcat( cmd_args, argv[i] ); 88 } 89 } 90 if ( escapeArgs ) { 91 strcat( cmd_args, "\"" ); 92 } 93 94 return cmd_args; 95 } 96 97 /* 98 ============ 99 idCmdArgs::TokenizeString 100 101 Parses the given string into command line tokens. 102 The text is copied to a separate buffer and 0 characters 103 are inserted in the appropriate place. The argv array 104 will point into this temporary buffer. 105 ============ 106 */ 107 void idCmdArgs::TokenizeString( const char *text, bool keepAsStrings ) { 108 idLexer lex; 109 idToken token, number; 110 int len, totalLen; 111 112 // clear previous args 113 argc = 0; 114 115 if ( !text ) { 116 return; 117 } 118 119 lex.LoadMemory( text, strlen( text ), "idCmdSystemLocal::TokenizeString" ); 120 lex.SetFlags( LEXFL_NOERRORS 121 | LEXFL_NOWARNINGS 122 | LEXFL_NOSTRINGCONCAT 123 | LEXFL_ALLOWPATHNAMES 124 | LEXFL_NOSTRINGESCAPECHARS 125 | LEXFL_ALLOWIPADDRESSES | ( keepAsStrings ? LEXFL_ONLYSTRINGS : 0 ) ); 126 127 totalLen = 0; 128 129 while ( 1 ) { 130 if ( argc == MAX_COMMAND_ARGS ) { 131 return; // this is usually something malicious 132 } 133 134 if ( !lex.ReadToken( &token ) ) { 135 return; 136 } 137 138 // check for negative numbers 139 if ( !keepAsStrings && ( token == "-" ) ) { 140 if ( lex.CheckTokenType( TT_NUMBER, 0, &number ) ) { 141 token = "-" + number; 142 } 143 } 144 145 // check for cvar expansion 146 if ( token == "$" ) { 147 if ( !lex.ReadToken( &token ) ) { 148 return; 149 } 150 if ( idLib::cvarSystem ) { 151 token = idLib::cvarSystem->GetCVarString( token.c_str() ); 152 } else { 153 token = "<unknown>"; 154 } 155 } 156 157 len = token.Length(); 158 159 if ( totalLen + len + 1 > sizeof( tokenized ) ) { 160 return; // this is usually something malicious 161 } 162 163 // regular token 164 argv[argc] = tokenized + totalLen; 165 argc++; 166 167 idStr::Copynz( tokenized + totalLen, token.c_str(), sizeof( tokenized ) - totalLen ); 168 169 totalLen += len + 1; 170 } 171 } 172 173 /* 174 ============ 175 idCmdArgs::AppendArg 176 ============ 177 */ 178 void idCmdArgs::AppendArg( const char *text ) { 179 if ( argc >= MAX_COMMAND_ARGS ) { 180 return; 181 } 182 if ( !argc ) { 183 argc = 1; 184 argv[ 0 ] = tokenized; 185 idStr::Copynz( tokenized, text, sizeof( tokenized ) ); 186 } else { 187 argv[ argc ] = argv[ argc-1 ] + strlen( argv[ argc-1 ] ) + 1; 188 idStr::Copynz( argv[ argc ], text, sizeof( tokenized ) - ( argv[ argc ] - tokenized ) ); 189 argc++; 190 } 191 } 192 193 /* 194 ============ 195 idCmdArgs::GetArgs 196 ============ 197 */ 198 const char * const * idCmdArgs::GetArgs( int *_argc ) { 199 *_argc = argc; 200 return (const char **)&argv[0]; 201 } 202