Subversion Repositories HomeAutomation

Rev

Rev 1026 | Rev 1060 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
969 runge 1
/***************************************************************************
2
 *   Copyright (C) December 10, 2008 by Mattias Runge                             *
3
 *   mattias@runge.se                                                      *
4
 *   virtualmachine.cpp                                            *
5
 *                                                                         *
6
 *   This program is free software; you can redistribute it and/or modify  *
7
 *   it under the terms of the GNU General Public License as published by  *
8
 *   the Free Software Foundation; either version 2 of the License, or     *
9
 *   (at your option) any later version.                                   *
10
 *                                                                         *
11
 *   This program is distributed in the hope that it will be useful,       *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU General Public License for more details.                          *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU General Public License     *
17
 *   along with this program; if not, write to the                         *
18
 *   Free Software Foundation, Inc.,                                       *
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20
 ***************************************************************************/
21
 
22
#include "virtualmachine.h"
23
 
24
VirtualMachine* VirtualMachine::myInstance = NULL;
25
 
26
VirtualMachine& VirtualMachine::getInstance()
27
{
28
	if (myInstance == NULL)
29
	{
30
		myInstance = new VirtualMachine();
31
	}
32
 
33
	return *myInstance;
34
}
35
 
36
void VirtualMachine::deleteInstance()
37
{
38
	if (myInstance != NULL)
39
	{
40
		delete myInstance;
41
		myInstance = NULL;
42
	}
43
}
44
 
45
VirtualMachine::VirtualMachine()
46
{
47
}
48
 
49
VirtualMachine::~VirtualMachine()
50
{
981 runge 51
	stop();
997 runge 52
 
999 runge 53
	myCommandThread.stop();
54
 
997 runge 55
	///FIXME: Verify that this works and does not cause segfaults
56
	for (map<int, SocketThread*>::iterator iter = mySocketThreads.begin(); iter != mySocketThreads.end(); iter++)
57
	{
999 runge 58
		iter->second->stop();
997 runge 59
		delete iter->second;
999 runge 60
		//mySocketThreads.erase(iter);
997 runge 61
	}
999 runge 62
 
63
	mySocketThreads.clear();
64
 
65
	for (map<int, IntervalThread*>::iterator iter = myIntervalThreads.begin(); iter != myIntervalThreads.end(); iter++)
66
	{
67
		iter->second->stop();
68
		delete iter->second;
69
		//myIntervalThreads.erase(iter);
70
	}
71
 
72
	myIntervalThreads.clear();
969 runge 73
}
74
 
75
void VirtualMachine::run()
76
{
77
	myGlobal = ObjectTemplate::New();
999 runge 78
	myGlobal->Set(String::New("_quit"), FunctionTemplate::New(VirtualMachine::_quit));
79
	myGlobal->Set(String::New("_print"), FunctionTemplate::New(VirtualMachine::_print));
80
	myGlobal->Set(String::New("log"), FunctionTemplate::New(VirtualMachine::_log));
81
	myGlobal->Set(String::New("sendCanMessage"), FunctionTemplate::New(VirtualMachine::_sendCanMessage));
82
	myGlobal->Set(String::New("sendCanNMTMessage"), FunctionTemplate::New(VirtualMachine::_sendCanNMTMessage));
83
	myGlobal->Set(String::New("loadScript"), FunctionTemplate::New(VirtualMachine::_loadScript));
84
	myGlobal->Set(String::New("startIntervalThread"), FunctionTemplate::New(VirtualMachine::_startIntervalThread));
85
	myGlobal->Set(String::New("stopIntervalThread"), FunctionTemplate::New(VirtualMachine::_stopIntervalThread));
1042 runge 86
	myGlobal->Set(String::New("setIntervalThreadTimeout"), FunctionTemplate::New(VirtualMachine::_setIntervalThreadTimeout));
999 runge 87
	myGlobal->Set(String::New("startSocketThread"), FunctionTemplate::New(VirtualMachine::_startSocketThread));
88
	myGlobal->Set(String::New("stopSocketThread"), FunctionTemplate::New(VirtualMachine::_stopSocketThread));
89
	myGlobal->Set(String::New("sendToSocketThread"), FunctionTemplate::New(VirtualMachine::_sendToSocketThread));
1007 runge 90
	myGlobal->Set(String::New("loadDataStore"), FunctionTemplate::New(VirtualMachine::_loadDataStore));
1008 runge 91
	myGlobal->Set(String::New("getFileContents"), FunctionTemplate::New(VirtualMachine::_getFileContents));
1011 runge 92
	myGlobal->Set(String::New("uint2hex"), FunctionTemplate::New(VirtualMachine::_uint2hex));
93
	myGlobal->Set(String::New("hex2bin"), FunctionTemplate::New(VirtualMachine::_hex2bin));
94
	myGlobal->Set(String::New("bin2hex"), FunctionTemplate::New(VirtualMachine::_bin2hex));
95
	myGlobal->Set(String::New("bin2float"), FunctionTemplate::New(VirtualMachine::_bin2float));
96
	myGlobal->Set(String::New("float2bin"), FunctionTemplate::New(VirtualMachine::_float2bin));
97
	myGlobal->Set(String::New("bin2uint"), FunctionTemplate::New(VirtualMachine::_bin2uint));
98
	myGlobal->Set(String::New("uint2bin"), FunctionTemplate::New(VirtualMachine::_uint2bin));
99
	myGlobal->Set(String::New("hex2uint"), FunctionTemplate::New(VirtualMachine::_hex2uint));
969 runge 100
	myContext = Context::New(NULL, myGlobal);
101
 
102
 
997 runge 103
	if (loadScript("System/Base.js"))
104
	{
105
		loadScript("System/Startup.js");
969 runge 106
 
997 runge 107
		loadScript("Autostart.js");
108
 
109
		Context::Scope contextScope(myContext);
110
 
111
		myFunctionStartup = Handle<Function>::Cast(myContext->Global()->Get(String::New("startup")));
969 runge 112
	}
113
	else
114
	{
997 runge 115
		///FIXME: We should probably exit the application here
116
		return;
969 runge 117
	}
118
 
119
	const int argc = 0;
120
	Handle<Value> argv[argc] = { };
997 runge 121
	Handle<Value> result = myFunctionStartup->Call(myFunctionStartup, argc, argv);
969 runge 122
 
999 runge 123
 
124
	string commandPort = Settings::get("CommandPort");
125
	if (commandPort != "")
126
	{
127
		myCommandThread.setSettings(stoi(commandPort), "Command console");
128
		myCommandThread.start();
129
	}
130
	else
131
	{
1024 runge 132
		Logger &log = Logger::getInstance();
133
		log.add("CommandPort is not defined, can not start Command console socket\n");
999 runge 134
	}
135
 
136
 
969 runge 137
	mySemaphore.lock();
138
 
997 runge 139
	while (true)
969 runge 140
	{
141
		while (myExpressions.size() > 0)
142
		{
999 runge 143
			runExpression(myExpressions.pop());
969 runge 144
		}
145
 
146
		mySemaphore.wait();
147
	}
148
 
149
	mySemaphore.unlock();
150
}
151
 
999 runge 152
void VirtualMachine::queueExpression(Expression expression)
969 runge 153
{
999 runge 154
	myExpressions.push(expression);
969 runge 155
	mySemaphore.broadcast();
156
}
157
 
999 runge 158
string VirtualMachine::formatException(TryCatch* tryCatch)
969 runge 159
{
999 runge 160
	string result;
161
 
162
	HandleScope handleScope;
163
	String::Utf8Value exception(tryCatch->Exception());
164
	Handle<v8::Message> message = tryCatch->Message();
165
 
166
	string strException = *exception;
167
 
168
	if (message.IsEmpty())
169
	{
170
		result += strException + "\n";
171
	}
172
	else
173
	{
174
		String::Utf8Value filename(message->GetScriptResourceName());
175
		string strFilename = *filename;
176
 
177
		result += strFilename + ":" + itos(message->GetLineNumber()) + ": " + strException + "\n";
178
 
179
		String::Utf8Value sourceline(message->GetSourceLine());
180
		string strSourceline = *sourceline;
181
 
182
		result += strSourceline + "\n";
183
 
184
		string underline = rpad("", message->GetStartColumn(), ' ');
185
		underline = rpad(underline, message->GetEndColumn(), '^');
186
 
187
		result += underline + "\n";
188
	}
189
 
190
	return result;
969 runge 191
}
192
 
1007 runge 193
bool VirtualMachine::loadDataStore(string storeName)
194
{
1024 runge 195
	Logger &log = Logger::getInstance();
1007 runge 196
 
197
	string basePath = Settings::get("BasePath") + "Services/DataStores/";
198
	string scriptFileName = basePath + storeName + ".js";
199
 
200
	if (!file_exists(scriptFileName))
201
	{
1024 runge 202
		log.add("Failed to load datastore " + scriptFileName + ", file does not exist.\n");
1007 runge 203
		return false;
204
	}
205
 
206
	string scriptSource = file_get_contents(scriptFileName);
207
 
208
	scriptSource = "DataStore.addStore('" + storeName + "', " + str_replace("\n", "", scriptSource) + ");";
209
 
210
	Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
211
	Handle<String> name = String::New(scriptFileName.c_str(), scriptFileName.length());
212
 
213
	Context::Scope contextScope(myContext);
214
 
215
	TryCatch tryCatch;
216
 
217
	Handle<Script> script = Script::Compile(source, name);
218
 
219
	if (script.IsEmpty())
220
	{
1024 runge 221
		log.add(formatException(&tryCatch));
1007 runge 222
		return false;
223
	}
224
	else
225
	{
226
		Handle<Value> result = script->Run();
227
 
228
		if (result.IsEmpty())
229
		{
1024 runge 230
			log.add(formatException(&tryCatch));
1007 runge 231
			return false;
232
		}
233
 
1024 runge 234
		log.add("Loaded datastore " + storeName + "\n");
1007 runge 235
	}
236
 
237
	return true;
238
}
239
 
969 runge 240
bool VirtualMachine::loadScript(string scriptName)
241
{
1024 runge 242
	Logger &log = Logger::getInstance();
969 runge 243
 
981 runge 244
	string basePath = Settings::get("BasePath") + "Services/";
969 runge 245
	string scriptFileName = basePath + scriptName;
246
 
247
	if (!file_exists(scriptFileName))
248
	{
1024 runge 249
		log.add("Failed to load " + scriptFileName + ", file does not exist.\n");
969 runge 250
		return false;
251
	}
252
 
253
	string scriptSource = file_get_contents(scriptFileName);
254
 
255
	Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
256
	Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
257
 
997 runge 258
	Context::Scope contextScope(myContext);
259
 
995 runge 260
	TryCatch tryCatch;
997 runge 261
 
969 runge 262
	Handle<Script> script = Script::Compile(source, name);
263
 
264
	if (script.IsEmpty())
265
	{
1024 runge 266
		log.addToSyslog(formatException(&tryCatch));
969 runge 267
		return false;
268
	}
269
	else
270
	{
271
		Handle<Value> result = script->Run();
272
 
273
		if (result.IsEmpty())
274
		{
1024 runge 275
			log.addToSyslog(formatException(&tryCatch));
969 runge 276
			return false;
277
		}
977 runge 278
 
1024 runge 279
		log.add("Loaded " + scriptName + "\n");
969 runge 280
	}
281
 
282
	return true;
283
}
284
 
971 runge 285
unsigned int VirtualMachine::startIntervalThread(unsigned int timeout)
969 runge 286
{
999 runge 287
	IntervalThread *intervalThread = new IntervalThread(timeout);
969 runge 288
 
999 runge 289
	myIntervalThreads[intervalThread->getId()] = intervalThread;
290
	myIntervalThreads[intervalThread->getId()]->start();
969 runge 291
 
999 runge 292
	return intervalThread->getId();
969 runge 293
}
294
 
971 runge 295
bool VirtualMachine::stopIntervalThread(unsigned int id)
969 runge 296
{
971 runge 297
	if (myIntervalThreads.find(id) != myIntervalThreads.end())
969 runge 298
	{
1042 runge 299
		myIntervalThreads[id]->stop();
999 runge 300
		delete myIntervalThreads[id];
971 runge 301
		myIntervalThreads.erase(id);
1042 runge 302
 
969 runge 303
		return true;
304
	}
305
 
306
	return false;
307
}
308
 
1042 runge 309
bool VirtualMachine::setIntervalThreadTimeout(unsigned int id, unsigned int timeout)
310
{
311
	if (myIntervalThreads.find(id) != myIntervalThreads.end())
312
	{
313
		myIntervalThreads[id]->setTimeout(timeout);
314
		return true;
315
	}
316
 
317
	return false;
318
}
319
 
976 runge 320
unsigned int VirtualMachine::startSocketThread(string address, int port, unsigned int reconnectTimeout)
321
{
983 runge 322
	SocketThread *socketThread = new SocketThread(address, port, reconnectTimeout);
323
	mySocketThreads[socketThread->getId()] = socketThread;
324
	mySocketThreads[socketThread->getId()]->start();
976 runge 325
 
983 runge 326
	return socketThread->getId();
976 runge 327
}
328
 
329
bool VirtualMachine::stopSocketThread(unsigned int id)
330
{
331
	if (mySocketThreads.find(id) != mySocketThreads.end())
332
	{
983 runge 333
		delete mySocketThreads[id];
976 runge 334
		mySocketThreads.erase(id);
335
		return true;
336
	}
337
 
338
	return false;
339
}
340
 
341
void VirtualMachine::sendToSocketThread(unsigned int id, string data)
342
{
343
	if (mySocketThreads.find(id) != mySocketThreads.end())
344
	{
983 runge 345
		mySocketThreads[id]->send(data);
976 runge 346
	}
347
}
348
 
999 runge 349
void VirtualMachine::disconnectCommandClient(unsigned int id)
969 runge 350
{
999 runge 351
	myCommandThread.disconnectClient(id);
352
}
353
 
354
void VirtualMachine::sendToCommandClient(unsigned int id, string data)
355
{
356
	myCommandThread.sendTo(id, data);
357
}
358
 
359
void VirtualMachine::print(unsigned int id, string data)
360
{
361
	if (id == 0)
362
	{
1024 runge 363
		Logger &log = Logger::getInstance();
364
		log.add(data);
999 runge 365
	}
366
	else
367
	{
368
		VirtualMachine &vm = VirtualMachine::getInstance();
369
		vm.sendToCommandClient(id, data);
370
	}
371
}
372
 
373
bool VirtualMachine::runExpression(Expression expression)
374
{
969 runge 375
	string scriptName = "runExpression";
376
 
999 runge 377
	string scriptData = expression.getScript();
378
 
1008 runge 379
	scriptData = "setClientId(" + itos(expression.getTargetId()) + ");\n" + scriptData + "\n";
999 runge 380
 
381
	Handle<String> source =  String::New(scriptData.c_str(), scriptData.length());
969 runge 382
	Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
383
 
997 runge 384
	Context::Scope contextScope(myContext);
385
 
995 runge 386
	TryCatch tryCatch;
997 runge 387
 
969 runge 388
	Handle<Script> script = Script::Compile(source, name);
389
 
390
	if (script.IsEmpty())
391
	{
999 runge 392
		print(expression.getTargetId(), formatException(&tryCatch));
969 runge 393
		return false;
394
	}
395
	else
396
	{
397
		Handle<Value> result = script->Run();
398
 
399
		if (result.IsEmpty())
400
		{
999 runge 401
			print(expression.getTargetId(), formatException(&tryCatch));
969 runge 402
			return false;
403
		}
999 runge 404
		else if (expression.getTargetId() != 0)
405
		{
406
			 String::AsciiValue ascii(result);
407
			 string resultString = *ascii;
408
 
409
			 if (resultString != "undefined")
410
			 {
411
				print(expression.getTargetId(), resultString + "\n");
412
			 }
413
		}
969 runge 414
	}
415
 
416
	return true;
417
}
418
 
999 runge 419
 
420
Handle<Value> VirtualMachine::_quit(const Arguments& args)
995 runge 421
{
999 runge 422
	VirtualMachine &vm = VirtualMachine::getInstance();
995 runge 423
 
999 runge 424
	vm.disconnectCommandClient(args[0]->Uint32Value());
995 runge 425
 
999 runge 426
	return Undefined();
427
}
995 runge 428
 
999 runge 429
Handle<Value> VirtualMachine::_log(const Arguments& args)
430
{
1024 runge 431
	Logger &log = Logger::getInstance();
995 runge 432
 
999 runge 433
	String::AsciiValue str(args[0]);
995 runge 434
 
1024 runge 435
	log.add(*str);
995 runge 436
 
999 runge 437
	return Undefined();
995 runge 438
}
439
 
999 runge 440
Handle<Value> VirtualMachine::_print(const Arguments& args)
969 runge 441
{
999 runge 442
	VirtualMachine &vm = VirtualMachine::getInstance();
969 runge 443
 
999 runge 444
	String::AsciiValue str(args[1]);
969 runge 445
 
999 runge 446
	vm.print(args[0]->Uint32Value(), *str);
969 runge 447
 
448
	return Undefined();
449
}
450
 
999 runge 451
Handle<Value> VirtualMachine::_sendCanMessage(const Arguments& args)
969 runge 452
{
453
	CanNetManager &canMan = CanNetManager::getInstance();
454
 
455
	CanMessage canMessage;
456
 
457
	String::AsciiValue className(args[0]);
458
	canMessage.setClassName(*className);
459
	String::AsciiValue directionFlag(args[1]);
460
	canMessage.setDirectionFlag(*directionFlag);
461
	String::AsciiValue moduleName(args[2]);
462
	canMessage.setModuleName(*moduleName);
463
	canMessage.setModuleId(args[3]->Uint32Value());
464
	String::AsciiValue commandName(args[4]);
465
	canMessage.setCommandName(*commandName);
466
 
467
	String::AsciiValue dataString(args[5]);
468
 
469
	vector<string> parts = explode(",", trim(*dataString, ','));
470
	map<string, CanVariable> data;
471
 
472
	for (int n = 0; n < parts.size(); n++)
473
	{
474
		vector<string> keyAndValue = explode(":", parts[n]);
475
 
476
		data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
477
	}
478
 
479
	canMessage.setData(data);
480
 
481
	canMan.sendMessage(canMessage);
482
 
483
	return Undefined();
484
}
485
 
999 runge 486
Handle<Value> VirtualMachine::_sendCanNMTMessage(const Arguments& args)
986 runge 487
{
488
	CanNetManager &canMan = CanNetManager::getInstance();
489
 
490
	CanMessage canMessage;
491
 
492
	String::AsciiValue className(args[0]);
493
	canMessage.setClassName(*className);
494
	String::AsciiValue commandName(args[1]);
495
	canMessage.setCommandName(*commandName);
496
 
497
	String::AsciiValue dataString(args[2]);
498
 
499
	vector<string> parts = explode(",", trim(*dataString, ','));
500
	map<string, CanVariable> data;
501
 
502
	for (int n = 0; n < parts.size(); n++)
503
	{
504
		vector<string> keyAndValue = explode(":", parts[n]);
505
 
506
		data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
507
	}
508
 
509
	canMessage.setData(data);
510
 
511
	canMan.sendMessage(canMessage);
512
 
513
	return Undefined();
514
}
515
 
999 runge 516
Handle<Value> VirtualMachine::_loadScript(const Arguments& args)
969 runge 517
{
518
	VirtualMachine &vm = VirtualMachine::getInstance();
519
 
520
	String::AsciiValue str(args[0]);
521
 
522
	return Boolean::New(vm.loadScript(*str));
523
}
524
 
1007 runge 525
Handle<Value> VirtualMachine::_loadDataStore(const Arguments& args)
526
{
527
	VirtualMachine &vm = VirtualMachine::getInstance();
528
 
529
	String::AsciiValue str(args[0]);
530
 
531
	return Boolean::New(vm.loadDataStore(*str));
532
}
533
 
999 runge 534
Handle<Value> VirtualMachine::_startIntervalThread(const Arguments& args)
969 runge 535
{
536
	VirtualMachine &vm = VirtualMachine::getInstance();
999 runge 537
	return Integer::New(vm.startIntervalThread(args[0]->Uint32Value()));
969 runge 538
}
539
 
999 runge 540
Handle<Value> VirtualMachine::_stopIntervalThread(const Arguments& args)
969 runge 541
{
542
	VirtualMachine &vm = VirtualMachine::getInstance();
999 runge 543
	return Boolean::New(vm.stopIntervalThread(args[0]->Uint32Value()));
969 runge 544
}
976 runge 545
 
1042 runge 546
Handle<Value> VirtualMachine::_setIntervalThreadTimeout(const Arguments& args)
547
{
548
	VirtualMachine &vm = VirtualMachine::getInstance();
549
	return Integer::New(vm.setIntervalThreadTimeout(args[0]->Uint32Value(), args[1]->Uint32Value()));
550
}
551
 
999 runge 552
Handle<Value> VirtualMachine::_startSocketThread(const Arguments& args)
976 runge 553
{
554
	VirtualMachine &vm = VirtualMachine::getInstance();
555
 
556
	String::AsciiValue address(args[0]);
557
 
999 runge 558
	return Integer::New(vm.startSocketThread(*address, args[1]->Uint32Value(), args[2]->Uint32Value()));
976 runge 559
}
560
 
999 runge 561
Handle<Value> VirtualMachine::_stopSocketThread(const Arguments& args)
976 runge 562
{
563
	VirtualMachine &vm = VirtualMachine::getInstance();
564
 
999 runge 565
	return Boolean::New(vm.stopSocketThread(args[0]->Uint32Value()));
976 runge 566
}
567
 
999 runge 568
Handle<Value> VirtualMachine::_sendToSocketThread(const Arguments& args)
976 runge 569
{
570
	VirtualMachine &vm = VirtualMachine::getInstance();
571
 
572
	String::AsciiValue data(args[1]);
573
 
999 runge 574
	vm.sendToSocketThread(args[0]->Uint32Value(), *data);
976 runge 575
 
576
	return Undefined();
577
}
578
 
1008 runge 579
Handle<Value> VirtualMachine::_getFileContents(const Arguments& args)
580
{
581
	String::AsciiValue filename(args[0]);
582
 
583
	if (!file_exists(*filename))
584
	{
585
		return Undefined();
586
	}
587
 
588
	string content = file_get_contents(*filename);
589
 
590
	return String::New(content.c_str());
591
}
592
 
1010 runge 593
Handle<Value> VirtualMachine::_uint2hex(const Arguments& args)
594
{
595
	string hex = uint2hex(args[0]->Uint32Value(), args[1]->Uint32Value());
596
	return String::New(hex.c_str());
597
}
598
 
599
Handle<Value> VirtualMachine::_hex2bin(const Arguments& args)
600
{
601
	String::AsciiValue hex(args[0]);
602
	string bin = hex2bin(*hex);
603
	return String::New(bin.c_str());
604
}
605
 
606
Handle<Value> VirtualMachine::_bin2hex(const Arguments& args)
607
{
608
	String::AsciiValue bin(args[0]);
609
	string hex = bin2hex(*bin);
610
	return String::New(hex.c_str());
611
}
612
 
613
Handle<Value> VirtualMachine::_bin2float(const Arguments& args)
614
{
615
	String::AsciiValue bin(args[0]);
616
	float f = bin2float(*bin);
617
	return Number::New(f);
618
}
619
 
620
Handle<Value> VirtualMachine::_float2bin(const Arguments& args)
621
{
622
	string bin = float2bin(args[0]->NumberValue(), args[1]->Uint32Value());
623
	return String::New(bin.c_str());
624
}
625
 
626
Handle<Value> VirtualMachine::_bin2uint(const Arguments& args)
627
{
628
	String::AsciiValue bin(args[0]);
629
	unsigned int num = bin2uint(*bin);
1012 runge 630
	return Number::New(num);
1010 runge 631
}
632
 
633
Handle<Value> VirtualMachine::_uint2bin(const Arguments& args)
634
{
635
	string bin = uint2bin(args[0]->Uint32Value(), args[1]->Uint32Value());
636
	return String::New(bin.c_str());
637
}
638
 
1011 runge 639
Handle<Value> VirtualMachine::_hex2uint(const Arguments& args)
640
{
641
	String::AsciiValue hex(args[0]);
642
	unsigned int num = hex2uint(*hex);
1012 runge 643
	return Number::New(num);
1011 runge 644
}