avr: fixed some memory leaks
[avr-sim.git] / src / ScriptableAnalyzer.cpp
blob9fab754f83b5292f7e6ef4c272a1c8c5484fc675
1 /*
2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "ScriptableAnalyzer.h"
20 #include "ScriptEngine.h"
21 #include "script/ScriptException.h"
22 #include "Core.h"
24 #include "Format.h"
25 #include <string>
26 #include <fstream>
27 #include <iostream>
29 #define ANALYZER_PATH "./analyzers/:./"
31 namespace avr {
33 static std::string locateScript(const std::string & name) {
34 static const std::string path(ANALYZER_PATH);
35 static const std::string delimiters(":");
36 static const std::string empty;
38 size_t i = 0, j;
39 do {
40 j = path.find_first_of(delimiters, i);
42 std::string test;
43 if( j != std::string::npos )
44 test = path.substr(i, j) + name + ".lua";
45 else
46 test = path.substr(i) + name + ".lua";
48 std::ifstream f( test.c_str() );
49 if( f.is_open() )
50 return test;
52 i = j + 1;
53 } while( j != std::string::npos );
55 return empty;
58 using script::ScriptMethod;
59 using script::ScriptUtil;
61 ScriptMethod<ScriptableAnalyzer> ScriptableAnalyzer::sm_methods[] = {
62 ScriptMethod<ScriptableAnalyzer>( "breakSystem", &ScriptableAnalyzer::script_breakSystem ),
63 ScriptMethod<ScriptableAnalyzer>( "register", &ScriptableAnalyzer::script_register ),
64 ScriptMethod<ScriptableAnalyzer>( "ioregister", &ScriptableAnalyzer::script_ioregister ),
67 ScriptableAnalyzer::ScriptableAnalyzer(Core *core, ScriptEngine *vm,
68 const char *scriptname)
69 : Analyzer(core), script::Scriptable(vm), scriptname(scriptname) {
71 std::string path = locateScript(scriptname);
72 if( path == "" )
73 throw ScriptException(
74 util::format("Unable to locate script %s") % scriptname );
76 methodBase = ScriptUtil<ScriptableAnalyzer,Scriptable>::addMethods( this,
77 sm_methods, sizeof(sm_methods)/sizeof(sm_methods[0]) );
79 try {
80 compileFile( path.c_str() );
81 registerClass(scriptname);
82 setNumber("pcBytes", core->pcBytes());
83 } catch( script::ScriptException & ex ) {
84 throw ScriptException( ex.message() );
88 ScriptableAnalyzer::~ScriptableAnalyzer() {
89 try {
90 const char *method = "finish";
91 if( hasMethod(method) ) {
92 pushMethod(method);
93 Scriptable::call(0, 0);
96 unregisterClass(scriptname);
97 } catch( script::ScriptException & ex ) {
99 * Throwing exceptions in destructors is a bad idea
100 * see http://www.kolpackov.net/projects/c++/eh/dtor-1.xhtml
101 * for an interesting overview of the problems
103 //throw ScriptException( ex.message() );
104 std::cerr << "~ScriptableAnalyzer: " << ex.message() << std::endl;
108 void ScriptableAnalyzer::callHelper(const char *method) {
109 try {
110 if( hasMethod(method) ) {
111 pushMethod(method);
112 Scriptable::call(0, 0);
114 } catch( script::ScriptException & ex ) {
115 throw ScriptException( ex.message() );
119 void ScriptableAnalyzer::callHelperb(const char *method, bool b) {
120 try {
121 if( hasMethod(method) ) {
122 pushMethod(method);
123 vm->pushBoolean(b);
124 Scriptable::call(1, 0);
126 } catch( script::ScriptException & ex ) {
127 throw ScriptException( ex.message() );
131 void ScriptableAnalyzer::callHelper(const char *method, float x) {
132 try {
133 if( hasMethod(method) ) {
134 pushMethod(method);
135 vm->pushNumber(x);
136 Scriptable::call(1, 0);
138 } catch( script::ScriptException & ex ) {
139 throw ScriptException( ex.message() );
143 void ScriptableAnalyzer::callHelperb(const char *method, float x, bool b) {
144 try {
145 if( hasMethod(method) ) {
146 pushMethod(method);
147 vm->pushNumber(x);
148 vm->pushBoolean(b);
149 Scriptable::call(2, 0);
151 } catch( script::ScriptException & ex ) {
152 throw ScriptException( ex.message() );
156 void ScriptableAnalyzer::callHelper(const char *method, float x, float y) {
157 try {
158 if( hasMethod(method) ) {
159 pushMethod(method);
160 vm->pushNumber(x);
161 vm->pushNumber(y);
162 Scriptable::call(2, 0);
164 } catch( script::ScriptException & ex ) {
165 throw ScriptException( ex.message() );
169 int ScriptableAnalyzer::methodCall(int i) {
170 return ScriptUtil<ScriptableAnalyzer,Scriptable>::methodCall(this, i, methodBase,
171 sm_methods, sizeof(sm_methods)/sizeof(sm_methods[0]) );
174 void ScriptableAnalyzer::reset(unsigned int type) {
175 const char *methodName = "reset";
176 callHelper(methodName, type);
179 void ScriptableAnalyzer::trace(dword address) {
180 const char *methodName = "trace";
181 callHelper(methodName, address);
184 void ScriptableAnalyzer::step(lword ticks) {
185 const char *methodName = "step";
186 try {
187 // Store tick count
188 setNumber("ticks", ticks);
190 if( hasMethod(methodName) ) {
191 pushMethod(methodName);
192 vm->pushNumber(ticks);
193 Scriptable::call(1, 0);
195 } catch( script::ScriptException & ex ) {
196 throw ScriptException( ex.message() );
200 void ScriptableAnalyzer::readRegister(unsigned int r, byte val) {
201 const char *methodName = "readRegister";
202 callHelper(methodName, r, val);
205 void ScriptableAnalyzer::writeRegister(unsigned int r, byte val) {
206 const char *methodName = "writeRegister";
207 callHelper(methodName, r, val);
210 void ScriptableAnalyzer::readByte(unsigned int addr, byte val) {
211 const char *methodName = "readByte";
212 callHelper(methodName, addr, val);
215 void ScriptableAnalyzer::writeByte(unsigned int addr, byte val) {
216 const char *methodName = "writeByte";
217 callHelper(methodName, addr, val);
220 void ScriptableAnalyzer::readFlash(unsigned int addr, byte val) {
221 const char *methodName = "readFlash";
222 callHelper(methodName, addr, val);
225 void ScriptableAnalyzer::writeFlash(unsigned int addr, word val) {
226 const char *methodName = "writeFlash";
227 callHelper(methodName, addr, val);
230 void ScriptableAnalyzer::fetchOperand(word val) {
231 const char *methodName = "fetchOperand";
232 callHelper(methodName, val);
235 void ScriptableAnalyzer::push(byte val) {
236 const char *methodName = "push";
237 callHelper(methodName, val);
240 void ScriptableAnalyzer::pop(byte val) {
241 const char *methodName = "pop";
242 callHelper(methodName, val);
245 void ScriptableAnalyzer::jump(dword address, bool push) {
246 const char *methodName = "jump";
247 callHelperb(methodName, address, push);
250 void ScriptableAnalyzer::skip() {
251 const char *methodName = "skip";
252 callHelper(methodName);
255 void ScriptableAnalyzer::call(dword address, bool push) {
256 const char *methodName = "call";
257 callHelperb(methodName, address, push);
260 void ScriptableAnalyzer::ret(bool interrupt) {
261 const char *methodName = "ret";
262 callHelperb(methodName, interrupt);
265 void ScriptableAnalyzer::sleep(unsigned int mode) {
266 const char *methodName = "sleep";
267 callHelper(methodName, mode);
270 void ScriptableAnalyzer::systemBreak() {
271 const char *methodName = "systemBreak";
272 callHelper(methodName);
275 void ScriptableAnalyzer::interrupt(unsigned int vector, unsigned int addr) {
276 const char *methodName = "interrupt";
277 callHelper(methodName, vector, addr);
280 int ScriptableAnalyzer::script_breakSystem(const char *funcName) {
281 core->systemBreak();
282 return 0;
285 int ScriptableAnalyzer::script_register(const char *funcName) {
286 if ( vm->top() != 1 || vm->getType(1) != script::VM::Number )
287 throw script::ScriptException("expects a register index");
289 try {
290 int r = (int)vm->toNumber(1);
291 byte val = core->getR( r );
292 vm->pushNumber( val );
293 return 1;
294 } catch( util::Exception & ex ) {
295 throw script::ScriptException( ex.message() );
299 int ScriptableAnalyzer::script_ioregister(const char *funcName) {
300 if ( vm->top() != 1 || vm->getType(1) != script::VM::Number )
301 throw script::ScriptException("expects a io register index");
303 try {
304 int r = (int)vm->toNumber(1);
305 byte val = core->getIoreg( r );
306 vm->pushNumber( val );
307 return 1;
308 } catch( util::Exception & ex ) {
309 throw script::ScriptException( ex.message() );