1 #include "memorywatch.hpp"
3 #include "mathexpr-error.hpp"
7 memorywatch_memread_oper::memorywatch_memread_oper()
8 : mathexpr_operinfo("(readmemory)")
12 memorywatch_memread_oper::~memorywatch_memread_oper() {}
14 void memorywatch_memread_oper::evaluate(mathexpr_value target
, std::vector
<std::function
<mathexpr_value()>> promises
)
16 if(promises
.size() != 1)
17 throw mathexpr_error(mathexpr_error::ARGCOUNT
, "Memory read operator takes 1 argument");
18 static const int system_endian
= memory_space::get_system_endian();
23 void* res
= val
.value
;
24 addr
= val
.type
->tounsigned(res
);
28 } catch(std::exception
& e
) {
29 throw mathexpr_error(mathexpr_error::ADDR
, e
.what());
32 throw mathexpr_error(mathexpr_error::SIZE
, "Memory read size out of range");
34 mspace
->read_range(addr
, buf
, bytes
);
35 //Endian swap if needed.
36 if(system_endian
!= endianess
)
37 for(unsigned i
= 0; i
< bytes
/ 2; i
++)
38 std::swap(buf
[i
], buf
[bytes
- i
- 1]);
42 throw mathexpr_error(mathexpr_error::SIZE
, "1 byte floats not supported");
44 target
.type
->parse_s(target
.value
, *(int8_t*)buf
);
46 target
.type
->parse_u(target
.value
, *(uint8_t*)buf
);
50 throw mathexpr_error(mathexpr_error::SIZE
, "2 byte floats not supported");
52 target
.type
->parse_s(target
.value
, *(int16_t*)buf
);
54 target
.type
->parse_u(target
.value
, *(uint16_t*)buf
);
58 throw mathexpr_error(mathexpr_error::SIZE
, "3 byte floats not supported");
60 target
.type
->parse_s(target
.value
, *(ss_int24_t
*)buf
);
62 target
.type
->parse_u(target
.value
, *(ss_uint24_t
*)buf
);
66 target
.type
->parse_f(target
.value
, *(float*)buf
);
68 target
.type
->parse_s(target
.value
, *(int32_t*)buf
);
70 target
.type
->parse_u(target
.value
, *(uint32_t*)buf
);
74 target
.type
->parse_f(target
.value
, *(double*)buf
);
76 target
.type
->parse_s(target
.value
, *(int64_t*)buf
);
78 target
.type
->parse_u(target
.value
, *(uint64_t*)buf
);
81 throw mathexpr_error(mathexpr_error::SIZE
, "Memory address size not supported");
84 target
.type
->scale(target
.value
, scale_div
);
89 bool is_terminal(char ch
)
91 if(ch
== '%') return true;
92 if(ch
== 'b') return true;
93 if(ch
== 'B') return true;
94 if(ch
== 'd') return true;
95 if(ch
== 'i') return true;
96 if(ch
== 'o') return true;
97 if(ch
== 's') return true;
98 if(ch
== 'u') return true;
99 if(ch
== 'x') return true;
100 if(ch
== 'X') return true;
104 std::string
get_placeholder(const std::string
& str
, size_t idx
)
106 std::ostringstream p
;
107 for(size_t i
= idx
; i
< str
.length(); i
++) {
109 if(is_terminal(str
[idx
]))
123 memorywatch_item_printer::~memorywatch_item_printer()
127 void memorywatch_item_printer::trace()
131 std::string
memorywatch_item::get_value()
136 fmt
.type
= mathexpr_format::DEFAULT
;
137 mathexpr_value v
= expr
->evaluate();
138 return v
.type
->format(v
.value
, fmt
);
140 std::ostringstream out
;
141 for(size_t i
= 0; i
< format
.length(); i
++) {
145 //Format placeholder.
146 std::string p
= get_placeholder(format
, i
+ 1);
150 if(p
[p
.length() - 1] == '%') {
155 fmt
.showsign
= false;
156 fmt
.fillzeros
= false;
159 fmt
.uppercasehex
= false;
160 auto r
= regex("([+0]*)([1-9][0-9]*)?(\\.(0|[1-9][0-9]*))?([bBdiosuxX])", p
);
162 throw mathexpr_error(mathexpr_error::FORMAT
, "Bad format placeholder");
165 std::string flags
= r
[1];
167 for(i
= 0; i
< flags
.length(); i
++) {
171 fmt
.fillzeros
= true;
173 //The remaining part is width.precision.
176 fmt
.width
= parse_value
<int>(r
[2]);
180 fmt
.precision
= parse_value
<int>(r
[4]);
183 case 'b': fmt
.type
= mathexpr_format::BINARY
; break;
184 case 'B': fmt
.type
= mathexpr_format::BOOLEAN
; break;
185 case 'd': fmt
.type
= mathexpr_format::DECIMAL
; break;
186 case 'i': fmt
.type
= mathexpr_format::DECIMAL
; break;
187 case 'o': fmt
.type
= mathexpr_format::OCTAL
; break;
188 case 's': fmt
.type
= mathexpr_format::STRING
; break;
189 case 'u': fmt
.type
= mathexpr_format::DECIMAL
; break;
190 case 'x': fmt
.type
= mathexpr_format::HEXADECIMAL
; break;
191 case 'X': fmt
.type
= mathexpr_format::HEXADECIMAL
; fmt
.uppercasehex
= true; break;
193 mathexpr_value v
= expr
->evaluate();
194 out
<< v
.type
->format(v
.value
, fmt
);
200 void memorywatch_item::show(const std::string
& n
)
205 } catch(std::bad_alloc
& e
) {
207 } catch(mathexpr_error
& e
) {
208 x
= e
.get_short_error();
209 } catch(std::runtime_error
& e
) {
217 memorywatch_set::~memorywatch_set()
220 garbage_collectable::do_gc();
223 void memorywatch_set::reset()
225 for(auto& i
: roots
) {
227 i
.second
.printer
->reset();
228 i
.second
.expr
->reset();
232 void memorywatch_set::refresh()
235 i
.second
.expr
->reset();
237 i
.second
.show(i
.first
);
240 std::set
<std::string
> memorywatch_set::set()
242 std::set
<std::string
> r
;
248 memorywatch_item
& memorywatch_set::get(const std::string
& name
)
250 auto i
= get_soft(name
);
252 throw std::runtime_error("No such watch '" + name
+ "'");
256 memorywatch_item
* memorywatch_set::get_soft(const std::string
& name
)
258 if(!roots
.count(name
))
260 return &(roots
.find(name
)->second
);
263 memorywatch_item
* memorywatch_set::create(const std::string
& name
, memorywatch_item
& item
)
265 roots
.insert(std::make_pair(name
, item
));
266 return &(roots
.find(name
)->second
);
269 void memorywatch_set::destroy(const std::string
& name
)
271 if(!roots
.count(name
))
274 garbage_collectable::do_gc();
277 const std::string
& memorywatch_set::get_longest_name(std::function
<size_t(const std::string
& n
)> rate
)
279 static std::string empty
;
281 const std::string
* best
= &empty
;
282 for(auto& i
: roots
) {
283 size_t r
= rate(i
.first
);
292 size_t memorywatch_set::utflength_rate(const std::string
& n
)
294 return utf8::strlen(n
);
297 void memorywatch_set::foreach(std::function
<void(memorywatch_item
& item
)> cb
)
303 void memorywatch_set::swap(memorywatch_set
& s
) throw()
305 std::swap(roots
, s
.roots
);
308 #ifdef TEST_MEMORYWATCH
309 #include "mathexpr-ntype.hpp"
311 struct stdout_item_printer
: public memorywatch_item_printer
313 ~stdout_item_printer()
316 void show(const std::string
& n
, const std::string
& v
)
318 std::cout
<< n
<< " --> " << v
<< std::endl
;
325 int main2(int argc
, char** argv
)
327 memorywatch_set mset
;
328 gcroot_pointer
<memorywatch_item_printer
> printer(new stdout_item_printer
);
329 std::function
<gcroot_pointer
<mathexpr
>(const std::string
&)> vars_fn
= [&mset
]
330 (const std::string
& n
) -> gcroot_pointer
<mathexpr
> {
331 auto p
= mset
.get_soft(n
);
333 memorywatch_item
i(*expression_value());
334 p
= mset
.create(n
, i
);
338 for(int i
= 1; i
< argc
; i
++) {
339 regex_results r
= regex("([^=]+)=\\[(.*)\\](.*)", argv
[i
]);
341 throw std::runtime_error("Bad argument '" + std::string(argv
[i
]) + "'");
342 *vars_fn(r
[1]) = *mathexpr::parse(*expression_value(), r
[3], vars_fn
);
343 mset
.get(r
[1]).format
= r
[2];
344 mset
.get(r
[1]).printer
= printer
;
346 garbage_collectable::do_gc();
347 garbage_collectable::do_gc();
352 int main(int argc
, char** argv
)
354 int r
= main2(argc
, argv
);
355 garbage_collectable::do_gc();