Pol  Revision:4b29d2b
eprog_read.cpp
Go to the documentation of this file.
1 
7 #include <cstdio>
8 #include <exception>
9 #include <string>
10 
11 #include "../clib/logfacility.h"
12 #include "../clib/rawtypes.h"
13 #include "../clib/strutil.h"
14 #include "eprog.h"
15 #include "executor.h"
16 #include "filefmt.h"
17 #include "fmodule.h"
18 #include "modules.h"
19 #include "objmethods.h"
20 #include "symcont.h"
21 #include "token.h"
22 #include "tokens.h"
23 
24 namespace Pol
25 {
26 namespace Bscript
27 {
33 int EScriptProgram::read( const char* fname )
34 {
35  FILE* fp = NULL;
36 
37  try
38  {
39  name = fname;
40 
41  fp = fopen( fname, "rb" );
42  if ( !fp )
43  throw std::runtime_error( std::string( "Unable to open " ) + fname + " for reading." );
44 
45  BSCRIPT_FILE_HDR hdr;
46  if ( fread( &hdr, sizeof hdr, 1, fp ) != 1 )
47  {
48  ERROR_PRINT << "Error loading script " << fname << ": error reading header\n";
49  fclose( fp );
50  return -1;
51  }
52  if ( hdr.magic2[0] != BSCRIPT_FILE_MAGIC0 || hdr.magic2[1] != BSCRIPT_FILE_MAGIC1 )
53  {
54  ERROR_PRINT << "Error loading script " << fname << ": bad magic value '" << hdr.magic2[0]
55  << hdr.magic2[1] << "'\n";
56  fclose( fp );
57  return -1;
58  }
59  // auto-check for latest version (see filefmt.h for setting)
60  if ( hdr.version != ESCRIPT_FILE_VER_CURRENT )
61  {
62  ERROR_PRINT << "Error loading script " << fname << ": Recompile required. Bad version number "
63  << hdr.version << "\n";
64  fclose( fp );
65  return -1;
66  }
67  version = hdr.version;
68  nglobals = hdr.globals;
69  BSCRIPT_SECTION_HDR sechdr;
70  while ( fread( &sechdr, sizeof sechdr, 1, fp ) == 1 )
71  {
72  switch ( sechdr.type )
73  {
75  if ( read_progdef_hdr( fp ) )
76  {
77  ERROR_PRINT << "Error loading script " << fname << ": error reading progdef section\n";
78  fclose( fp );
79  return -1;
80  }
81  break;
82 
84  if ( read_module( fp ) )
85  {
86  ERROR_PRINT << "Error loading script " << fname << ": error reading module section\n";
87  fclose( fp );
88  return -1;
89  }
90  break;
92  tokens.read( fp );
93  break;
95  symbols.read( fp );
96  break;
98  if ( read_globalvarnames( fp ) )
99  {
100  ERROR_PRINT << "Error loading script " << fname
101  << ": error reading global variable name section\n";
102  fclose( fp );
103  return -1;
104  }
105  break;
107  if ( read_exported_functions( fp, &sechdr ) )
108  {
109  ERROR_PRINT << "Error loading script " << fname
110  << ": error reading exported functions section\n";
111  fclose( fp );
112  return -1;
113  }
114  break;
115  default:
116  ERROR_PRINT << "Error loading script " << fname << ": unknown section type " << sechdr.type
117  << "\n";
118  fclose( fp );
119  return -1;
120  }
121  }
122  fclose( fp );
123 
124  return create_instructions();
125  }
126  catch ( std::exception& ex )
127  {
128  ERROR_PRINT << "Exception caught while loading script " << fname << ": " << ex.what() << "\n";
129  if ( fp != NULL )
130  fclose( fp );
131  return -1;
132  }
133 #ifndef WIN32
134  catch ( ... )
135  {
136  ERROR_PRINT << "Exception caught while loading script " << fname << "\n";
137  if ( fp != NULL )
138  fclose( fp );
139  return -1;
140  }
141 #endif
142 }
144 {
145  int nLines = tokens.length() / sizeof( StoredToken );
146  instr.resize( nLines ); // = new Instruction[ nLines ];
147 
148  for ( int i = 0; i < nLines; i++ )
149  {
150  Instruction& ins = instr[i];
151  if ( _readToken( ins.token, i ) )
152  return -1;
153 
154  // executor only:
155  ins.func = Executor::GetInstrFunc( ins.token );
156  }
157  return 0;
158 }
159 
164 {
166  if ( fread( &hdr, sizeof hdr, 1, fp ) != 1 )
167  return -1;
168 
169  haveProgram = true;
171  return 0;
172 }
173 
178 {
179  BSCRIPT_MODULE_HDR hdr;
180  if ( fread( &hdr, sizeof hdr, 1, fp ) != 1 )
181  return -1;
182  auto fm = new FunctionalityModule( hdr.modulename );
183  for ( unsigned i = 0; i < hdr.nfuncs; i++ )
184  {
186  if ( fread( &func, sizeof func, 1, fp ) != 1 )
187  {
188  delete fm;
189  return -1;
190  }
191  fm->addFunction( func.funcname, func.nargs );
192  }
193  modules.push_back( fm );
194  return 0;
195 }
196 
197 /* Note: This function is ONLY used from Executor::read(). */
198 int EScriptProgram::_readToken( Token& token, unsigned position ) const
199 {
200  StoredToken st;
201  tokens.atGet1( position, st );
202  // StoredToken& st = tokens[position];
203 
204  token.module = (ModuleID)st.module;
205  token.id = static_cast<BTokenId>( st.id );
206  token.type = static_cast<BTokenType>( st.type );
207  token.lval = st.offset;
208 
209  token.nulStr();
210 
211  // FIXME: USED to set lval to 0 for TYP_FUNC. Not sure if needed anymore.
212  // FIXME: Doesn't seem to be, but must be sure before removal
213  switch ( st.id )
214  {
215  case INS_CASEJMP:
216  if ( st.offset >= symbols.length() )
217  {
218  throw std::runtime_error(
219  "Symbol offset of " + Clib::decint( st.offset ) + " exceeds symbol store length of " +
220  Clib::decint( symbols.length() ) + " at PC=" + Clib::decint( position ) );
221  }
222  token.dataptr = reinterpret_cast<const unsigned char*>( symbols.array() + st.offset );
223  return 0;
224  case TOK_LONG:
225  if ( st.offset >= symbols.length() )
226  {
227  throw std::runtime_error(
228  "Symbol offset of " + Clib::decint( st.offset ) + " exceeds symbol store length of " +
229  Clib::decint( symbols.length() ) + " at PC=" + Clib::decint( position ) );
230  }
231  std::memcpy( &token.lval, symbols.array() + st.offset, sizeof( int ) );
232  return 0;
233  case TOK_DOUBLE:
234  if ( st.offset >= symbols.length() )
235  {
236  throw std::runtime_error(
237  "Symbol offset of " + Clib::decint( st.offset ) + " exceeds symbol store length of " +
238  Clib::decint( symbols.length() ) + " at PC=" + Clib::decint( position ) );
239  }
240  std::memcpy( &token.dval, symbols.array() + st.offset, sizeof( double ) );
241  return 0;
242 
243  case CTRL_STATEMENTBEGIN:
244  if ( st.offset )
245  {
246  if ( st.offset >= symbols.length() )
247  {
248  throw std::runtime_error(
249  "Symbol offset of " + Clib::decint( st.offset ) + " exceeds symbol store length of " +
250  Clib::decint( symbols.length() ) + " at PC=" + Clib::decint( position ) );
251  }
252  DebugToken* dt = (DebugToken*)( symbols.array() + st.offset );
253  token.sourceFile = dt->sourceFile;
254  token.lval = dt->offset;
255 
256  if ( dt->strOffset >= symbols.length() )
257  {
258  throw std::runtime_error( "Symbol offset of " + Clib::decint( dt->strOffset ) +
259  " exceeds symbol store length of " +
261  " at PC=" + Clib::decint( position ) );
262  }
263  if ( dt->strOffset )
264  token.setStr( symbols.array() + dt->strOffset );
265  }
266  return 0;
267 
268  case INS_INITFOREACH:
269  case INS_STEPFOREACH:
270  case INS_INITFOR:
271  case INS_NEXTFOR:
272  case TOK_GLOBALVAR:
273  case TOK_LOCALVAR:
274  case CTRL_JSR_USERFUNC:
275  case CTRL_LEAVE_BLOCK:
276  case TOK_ARRAY_SUBSCRIPT:
277  case RSV_JMPIFFALSE:
278  case RSV_JMPIFTRUE:
279  case RSV_GOTO:
280  case RSV_LOCAL:
281  case RSV_GLOBAL:
283  case INS_ASSIGN_LOCALVAR:
284  case INS_GET_MEMBER_ID:
285  case INS_SET_MEMBER_ID:
287  case INS_CALL_METHOD_ID:
293  token.lval = st.offset;
294  return 0;
295  case TOK_FUNCREF:
296  token.lval = st.offset;
297  return 0;
298 
299  case INS_CALL_METHOD:
300  case TOK_FUNC:
301  case TOK_USERFUNC:
302  token.lval = st.type;
303  token.type = ( st.id == TOK_FUNC ) ? TYP_FUNC : TYP_USERFUNC;
304  if ( st.offset )
305  {
306  if ( st.offset >= symbols.length() )
307  {
308  throw std::runtime_error(
309  "Symbol offset of " + Clib::decint( st.offset ) + " exceeds symbol store length of " +
310  Clib::decint( symbols.length() ) + " at PC=" + Clib::decint( position ) );
311  }
312  token.setStr( symbols.array() + st.offset );
313  }
314  else if ( token.type == TYP_FUNC )
315  {
316  FunctionalityModule* modl = modules[token.module];
317  const ModuleFunction* modfunc;
318 
319  // executor only:
320  modfunc = modl->functions.at( token.lval );
321 
322  token.setStr( modfunc->name.get().c_str() );
323  }
324  return 0;
325 
326  default:
327  if ( st.offset )
328  {
329  if ( st.offset >= symbols.length() )
330  {
331  throw std::runtime_error(
332  "Symbol offset of " + Clib::decint( st.offset ) + " exceeds symbol store length of " +
333  Clib::decint( symbols.length() ) + " at PC=" + Clib::decint( position ) );
334  }
335  token.setStr( symbols.array() + st.offset );
336  }
337  return 0;
338  }
339 }
340 
342 {
344  if ( fread( &hdr, sizeof hdr, 1, fp ) != 1 )
345  return -1;
346  int res = 0;
347  unsigned bufalloc = 20;
348  auto buffer = new char[bufalloc];
349  for ( unsigned idx = 0; idx < hdr.nGlobalVars; ++idx )
350  {
352  if ( fread( &ghdr, sizeof ghdr, 1, fp ) != 1 )
353  {
354  res = -1;
355  break;
356  }
357  if ( ghdr.namelen >= bufalloc )
358  {
359  bufalloc = ghdr.namelen + 5;
360  delete[] buffer;
361  buffer = new char[bufalloc];
362  }
363  if ( fread( buffer, ghdr.namelen + 1, 1, fp ) != 1 )
364  {
365  res = -1;
366  break;
367  }
368  globalvarnames.push_back( std::string( buffer ) );
369  }
370  delete[] buffer;
371  buffer = NULL;
372  return res;
373 }
374 
376 {
378  ObjMethod* mth;
379 
380  unsigned nexports = hdr->length / sizeof bef;
381  while ( nexports-- )
382  {
383  if ( fread( &bef, sizeof bef, 1, fp ) != 1 )
384  return -1;
386  ef.name = bef.funcname;
387  ef.nargs = bef.nargs;
388  ef.PC = bef.PC;
389  exported_functions.push_back( ef );
390  if ( ( mth = getKnownObjMethod( ef.name.c_str() ) ) != NULL )
391  mth->overridden = true;
392  }
393  return 0;
394 }
395 
397 {
398  if ( debug_loaded )
399  return 0;
400 
401  std::string mname = name;
402  mname.replace( mname.size() - 3, 3, "dbg" );
403  FILE* fp = fopen( mname.c_str(), "rb" );
404  if ( !fp )
405  {
406  ERROR_PRINT << "Unable to open " << mname << "\n";
407  return -1;
408  }
409 
410  u32 dbgversion;
411  size_t fread_res = fread( &dbgversion, sizeof dbgversion, 1, fp );
412  if ( fread_res != 1 || ( dbgversion != 2 && dbgversion != 3 ) )
413  {
414  ERROR_PRINT << "Recompile required. Bad version " << dbgversion << " in " << mname
415  << ", expected version 2\n";
416  fclose( fp );
417  return -1;
418  }
419 
420  size_t bufalloc = 20;
421  auto buffer = std::unique_ptr<char[]>( new char[bufalloc] );
422  int res = 0;
423 
424  u32 count;
425  fread_res = fread( &count, sizeof count, 1, fp );
426  if ( fread_res != 1 )
427  {
428  fclose( fp );
429  return -1;
430  }
431  dbg_filenames.resize( count );
432  for ( auto& elem : dbg_filenames )
433  {
434  fread_res = fread( &count, sizeof count, 1, fp );
435  if ( fread_res != 1 )
436  {
437  fclose( fp );
438  return -1;
439  }
440  if ( count >= bufalloc )
441  {
442  bufalloc = count * 2;
443  buffer.reset( new char[bufalloc] );
444  }
445  fread_res = fread( buffer.get(), count, 1, fp );
446  if ( fread_res != 1 )
447  {
448  fclose( fp );
449  return -1;
450  }
451  elem = buffer.get();
452  }
453 
454  fread_res = fread( &count, sizeof count, 1, fp );
455  if ( fread_res != 1 )
456  {
457  fclose( fp );
458  return -1;
459  }
460  globalvarnames.resize( count );
461  for ( auto& elem : globalvarnames )
462  {
463  fread_res = fread( &count, sizeof count, 1, fp );
464  if ( fread_res != 1 )
465  {
466  fclose( fp );
467  return -1;
468  }
469  if ( count >= bufalloc )
470  {
471  bufalloc = count * 2;
472  buffer.reset( new char[bufalloc] );
473  }
474  fread_res = fread( buffer.get(), count, 1, fp );
475  if ( fread_res != 1 )
476  {
477  fclose( fp );
478  return -1;
479  }
480  elem = buffer.get();
481  }
482 
483  fread_res = fread( &count, sizeof count, 1, fp );
484  if ( fread_res != 1 )
485  {
486  fclose( fp );
487  return -1;
488  }
489  dbg_filenum.resize( count );
490  dbg_linenum.resize( count );
491  dbg_ins_blocks.resize( count );
492  dbg_ins_statementbegin.resize( count );
493  for ( unsigned i = 0; i < tokens.count(); ++i )
494  {
496  fread_res = fread( &ins, sizeof ins, 1, fp );
497  if ( fread_res != 1 )
498  {
499  fclose( fp );
500  return -1;
501  }
502  dbg_filenum[i] = ins.filenum;
503  dbg_linenum[i] = ins.linenum;
504  dbg_ins_blocks[i] = ins.blocknum;
505  dbg_ins_statementbegin[i] = ins.statementbegin ? true : false;
506  }
507  fread_res = fread( &count, sizeof count, 1, fp );
508  if ( fread_res != 1 )
509  {
510  fclose( fp );
511  return -1;
512  }
513  blocks.resize( count );
514  for ( auto& block : blocks )
515  {
516  u32 tmp;
517 
518  fread_res = fread( &tmp, sizeof tmp, 1, fp );
519  if ( fread_res != 1 )
520  {
521  fclose( fp );
522  return -1;
523  }
524  block.parentblockidx = tmp;
525 
526  fread_res = fread( &tmp, sizeof tmp, 1, fp );
527  if ( fread_res != 1 )
528  {
529  fclose( fp );
530  return -1;
531  }
532  block.parentvariables = tmp;
533 
534  fread_res = fread( &tmp, sizeof tmp, 1, fp );
535  if ( fread_res != 1 )
536  {
537  fclose( fp );
538  return -1;
539  }
540  block.localvarnames.resize( tmp );
541 
542  for ( auto& elem : block.localvarnames )
543  {
544  fread_res = fread( &count, sizeof count, 1, fp );
545  if ( fread_res != 1 )
546  {
547  fclose( fp );
548  return -1;
549  }
550  if ( count >= bufalloc )
551  {
552  bufalloc = count * 2;
553  buffer.reset( new char[bufalloc] );
554  }
555  fread_res = fread( buffer.get(), count, 1, fp );
556  if ( fread_res != 1 )
557  {
558  fclose( fp );
559  return -1;
560  }
561  elem = buffer.get();
562  }
563  }
564  if ( dbgversion >= 3 )
565  {
566  fread_res = fread( &count, sizeof count, 1, fp );
567  if ( fread_res != 1 )
568  {
569  fclose( fp );
570  return -1;
571  }
572  dbg_functions.resize( count );
573  for ( auto& func : dbg_functions )
574  {
575  u32 tmp;
576  fread_res = fread( &tmp, sizeof tmp, 1, fp );
577  if ( fread_res != 1 )
578  {
579  fclose( fp );
580  return -1;
581  }
582  if ( tmp >= bufalloc )
583  {
584  bufalloc = tmp * 2;
585  buffer.reset( new char[bufalloc] );
586  }
587  fread_res = fread( buffer.get(), tmp, 1, fp );
588  if ( fread_res != 1 )
589  {
590  fclose( fp );
591  return -1;
592  }
593  func.name = buffer.get();
594 
595  fread_res = fread( &tmp, sizeof tmp, 1, fp );
596  if ( fread_res != 1 )
597  {
598  fclose( fp );
599  return -1;
600  }
601  func.firstPC = tmp;
602  fread_res = fread( &tmp, sizeof tmp, 1, fp );
603  if ( fread_res != 1 )
604  {
605  fclose( fp );
606  return -1;
607  }
608  func.lastPC = tmp;
609  }
610  }
611 
612  fclose( fp );
613  debug_loaded = true;
614  return res;
615 }
616 }
617 }
std::vector< unsigned > dbg_ins_blocks
Definition: eprog.h:141
void atGet1(unsigned position, StoredToken &token) const
Definition: symcont.cpp:191
BTokenType type
Definition: token.h:40
#define ESCRIPT_FILE_VER_CURRENT
Definition: filefmt.h:44
std::vector< bool > dbg_ins_statementbegin
Definition: eprog.h:142
unsigned char type
Definition: symcont.h:31
#define BSCRIPT_FILE_MAGIC0
Definition: filefmt.h:21
BTokenId id
Definition: token.h:39
std::string decint(unsigned short v)
Definition: strutil.cpp:64
std::vector< EPExportedFunction > exported_functions
Definition: eprog.h:117
unsigned short globals
Definition: filefmt.h:50
SymbolContainer symbols
Definition: eprog.h:94
boost_utils::script_name_flystring name
Definition: eprog.h:91
int _readToken(Token &token, unsigned position) const
Definition: eprog_read.cpp:198
ObjMethod * getKnownObjMethod(const char *token)
Definition: parser.cpp:665
unsigned short version
Definition: eprog.h:120
virtual void read(FILE *fp) POL_OVERRIDE
Definition: symcont.cpp:155
unsigned short offset
Definition: symcont.h:33
std::vector< EPDbgFunction > dbg_functions
Definition: eprog.h:135
unsigned char buffer[10000]
Definition: UoToolMain.cpp:109
unsigned int u32
Definition: rawtypes.h:27
unsigned short version
Definition: filefmt.h:49
boost_utils::function_name_flystring name
Definition: fmodule.h:27
int read_globalvarnames(FILE *fp)
Definition: eprog_read.cpp:341
std::vector< std::string > globalvarnames
Definition: eprog.h:133
#define BSCRIPT_FILE_MAGIC1
Definition: filefmt.h:22
std::vector< std::string > dbg_filenames
Definition: eprog.h:136
unsigned count(void) const
Definition: symcont.h:94
int read_exported_functions(FILE *fp, BSCRIPT_SECTION_HDR *hdr)
Definition: eprog_read.cpp:375
std::vector< Instruction > instr
Definition: eprog.h:124
unsigned length(void) const
Definition: symcont.h:67
std::vector< ModuleFunction * > functions
Definition: fmodule.h:43
std::vector< EPDbgBlock > blocks
Definition: eprog.h:134
unsigned int count() const
Definition: refptr.h:130
const unsigned char * dataptr
Definition: token.h:50
StoredTokenContainer tokens
Definition: eprog.h:93
unsigned char id
Definition: symcont.h:32
std::vector< unsigned > dbg_linenum
Definition: eprog.h:140
std::vector< unsigned > dbg_filenum
Definition: eprog.h:139
int read(const char *fname)
Definition: eprog_read.cpp:33
virtual void read(FILE *fp)
Definition: symcont.cpp:140
const char * array(void) const
Definition: symcont.h:69
unsigned char module
Definition: token.h:55
#define ERROR_PRINT
Definition: logfacility.h:230
void setStr(const char *s)
Definition: token.cpp:204
Definition: berror.cpp:12
std::vector< FunctionalityModule * > modules
Definition: eprog.h:92
static ExecInstrFunc GetInstrFunc(const Token &token)
Definition: executor.cpp:2576
unsigned char module
Definition: symcont.h:34
ExecInstrFunc func
Definition: eprog.h:40