Pol  Revision:cb584c9
console.cpp
Go to the documentation of this file.
1 
7 #include "console.h"
8 
9 #include <ctype.h>
10 #include <stddef.h>
11 
12 #include <format/format.h>
13 #include "../bscript/eprog.h"
14 #include "../bscript/impstr.h"
15 #include "../clib/cfgelem.h"
16 #include "../clib/cfgfile.h"
17 #include "../clib/fileutil.h"
18 #include "../clib/kbhit.h"
19 #include "../clib/logfacility.h"
20 #include "../clib/refptr.h"
21 #include "../clib/stlutil.h"
22 #include "../plib/systemstate.h"
23 #include "globals/state.h"
24 #include "globals/uvars.h"
25 #include "polsem.h"
26 #include "polsig.h"
27 #include "scrdef.h"
28 #include "scrsched.h"
29 #include "scrstore.h"
30 
31 #ifdef _WIN32
32 #include <conio.h>
33 #endif
34 
35 #include <exception>
36 #include <stdexcept>
37 #include <string>
38 
39 namespace Pol
40 {
41 namespace Core
42 {
45 
46 ConsoleCommand::ConsoleCommand( Clib::ConfigElem& elem, const std::string& cmd )
47 {
48  ISTRINGSTREAM is( cmd );
49  std::string charspec;
50  if ( !( is >> charspec >> script ) )
51  {
52  elem.throw_error( "Ill-formed console command desc: " + cmd );
53  }
54  if ( charspec[0] == '^' && charspec.size() == 2 )
55  {
56  ch = static_cast<char>( toupper( charspec[1] ) ) - 'A' + 1;
57  }
58  else if ( charspec.size() == 1 )
59  {
60  ch = charspec[0];
61  }
62  else
63  {
64  elem.throw_error( "Ill-formed console command char: " + charspec );
65  }
66  getline( is, description );
67  while ( description.size() > 0 && isspace( description[0] ) )
68  {
69  description.erase( 0, 1 );
70  }
71 
72  if ( script == "[unlock]" || script == "[lock/unlock]" )
73  ConsoleCommand::unlock_char = ch;
74 }
75 
77 {
78  return sizeof( char ) + script.capacity() + description.capacity();
79 }
80 
81 std::string getcmdstr( char ch )
82 {
83  if ( iscntrl( ch ) )
84  {
85  char s[3];
86  s[0] = '^';
87  s[1] = ch + 'A' - 1;
88  s[2] = '\0';
89  return s;
90  }
91  else
92  {
93  char s[2];
94  s[0] = ch;
95  s[1] = '\0';
96  return s;
97  }
98 }
99 
101 {
102  for ( unsigned i = 0; i < gamestate.console_commands.size(); ++i )
103  {
105  if ( cmd.ch == ch )
106  return &cmd;
107  }
108  return nullptr;
109 }
110 
112 {
113  if ( !Clib::FileExists( "config/console.cfg" ) )
114  return;
115 
116  Clib::ConfigFile cf( "config/console.cfg", "Commands" );
117  Clib::ConfigElem elem;
118 
119  gamestate.console_commands.clear();
120 
121  while ( cf.read( elem ) )
122  {
123  std::string tmp;
124  while ( elem.remove_prop( "CMD", &tmp ) )
125  {
126  ConsoleCommand cmd( elem, tmp );
127  gamestate.console_commands.push_back( cmd );
128  }
129  }
130 }
131 
133 {
134 #ifdef WIN32
135  // cope with function keys.
136  if ( ch == 0 || static_cast<unsigned char>( ch ) == 0xE0 )
137  {
138  getch();
139  ch = '?';
140  }
141 #endif
142  if ( ch == '?' )
143  {
144  fmt::Writer tmp;
145  tmp << "Commands: \n";
146  for ( unsigned i = 0; i < gamestate.console_commands.size(); ++i )
147  {
149  std::string sc = getcmdstr( cmd.ch );
150  if ( sc.size() == 1 )
151  tmp << " ";
152  tmp << " " << sc << ": ";
153  tmp << cmd.description << "\n";
154  }
155  tmp << " ?: Help (This list)\n";
156  INFO_PRINT << tmp.str();
157  return;
158  }
159 
160 
162  if ( !cmd )
163  {
164  INFO_PRINT << "Unknown console command: '" << getcmdstr( ch ) << "'\n";
165  return;
166  }
167  if ( cmd->script == "[lock]" )
168  {
169  ConsoleCommand::console_locked = true;
170  INFO_PRINT << "Console is now locked.\n";
171  return;
172  }
173  if ( cmd->script == "[unlock]" )
174  {
175  ConsoleCommand::console_locked = true;
176  INFO_PRINT << "Console is now unlocked.\n";
177  return;
178  }
179  if ( cmd->script == "[lock/unlock]" )
180  {
181  ConsoleCommand::console_locked = !ConsoleCommand::console_locked;
182  if ( ConsoleCommand::console_locked )
183  INFO_PRINT << "Console is now locked.\n";
184  else
185  INFO_PRINT << "Console is now unlocked.\n";
186  return;
187  }
188  if ( cmd->script == "[threadstatus]" )
189  {
191  return;
192  }
193  if ( cmd->script == "[crash]" )
194  {
195  int* p = (int*)17;
196  *p = 32;
197  return;
198  }
199 
200  if ( ConsoleCommand::console_locked )
201  {
202  INFO_PRINT << "Console is locked. Press '" << ConsoleCommand::unlock_char << "' to unlock.\n";
203  return;
204  }
205 
206  std::string filename = "scripts/console/" + cmd->script;
207  try
208  {
209  PolLock lck;
210  ScriptDef sd;
211  sd.quickconfig( filename + ".ecl" );
213  find_script2( sd, true, Plib::systemstate.config.cache_interactive_scripts );
214  if ( prog.get() != nullptr )
215  start_script( prog, new Bscript::String( getcmdstr( ch ) ) );
216  }
217  catch ( const char* msg )
218  {
219  ERROR_PRINT << "Command aborted due to: " << msg << "\n";
220  }
221  catch ( std::string& str )
222  {
223  ERROR_PRINT << "Command aborted due to: " << str << "\n";
224  } // egcs has some trouble realizing 'exception' should catch
225  catch ( std::runtime_error& re ) // runtime_errors, so...
226  {
227  ERROR_PRINT << "Command aborted due to: " << re.what() << "\n";
228  }
229  catch ( std::exception& ex )
230  {
231  ERROR_PRINT << "Command aborted due to: " << ex.what() << "\n";
232  }
233  catch ( int xn )
234  {
235  ERROR_PRINT << "Command aborted due to: " << xn << "\n";
236  }
237  return;
238 }
239 #ifdef _WIN32
241 {
242  if ( kbhit() )
243  {
244  exec_console_cmd( static_cast<char>( getch() ) );
245  }
246 }
247 #else
249 {
250  if ( kb->kbhit() )
251  {
252  exec_console_cmd( kb->getch() );
253  }
254 }
255 #endif
256 }
257 }
ref_ptr< Bscript::EScriptProgram > find_script2(const ScriptDef &script, bool complain_if_not_found, bool cache_script)
Definition: scrstore.cpp:83
void quickconfig(const Plib::Package *pkg, const std::string &name_ecl)
Definition: scrdef.cpp:112
SystemState systemstate
Definition: systemstate.cpp:12
static void load_console_commands()
Definition: console.cpp:111
T * get() const
Definition: refptr.h:176
static void check_console_commands(Clib::KeyboardHook *kb)
Definition: console.cpp:248
static bool console_locked
Definition: console.h:37
static char unlock_char
Definition: console.h:38
POL_NORETURN void throw_error(const std::string &errmsg) const
Definition: cfgfile.cpp:285
std::vector< ConsoleCommand > console_commands
Definition: uvars.h:220
std::string getcmdstr(char ch)
Definition: console.cpp:81
static ConsoleCommand * find_console_command(char ch)
Definition: console.cpp:100
volatile bool report_status_signalled
Definition: polsig.h:20
std::string description
Definition: console.h:26
GameState gamestate
Definition: uvars.cpp:74
StateManager stateManager
Definition: state.cpp:8
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:128
static void exec_console_cmd(char ch)
Definition: console.cpp:132
#define ISTRINGSTREAM
Definition: stlutil.h:73
std::string script
Definition: console.h:25
size_t estimateSize() const
Definition: console.cpp:76
#define ERROR_PRINT
Definition: logfacility.h:230
bool FileExists(const char *filename)
Definition: fileutil.cpp:118
bool read(ConfigElem &elem)
Definition: cfgfile.cpp:1015
#define INFO_PRINT
Definition: logfacility.h:223
void start_script(const char *filename, Bscript::BObjectImp *param0, Bscript::BObjectImp *param1)
Definition: scrsched.cpp:150
Definition: berror.cpp:12
ConsoleCommand(Clib::ConfigElem &elem, const std::string &cmd)
Definition: console.cpp:46