|
1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 # |
|
4 # See COPYING.Runtime file for copyrights details. |
|
5 # |
|
6 |
|
7 from __future__ import absolute_import |
|
8 import ctypes |
|
9 from ctypes import * |
|
10 from datetime import timedelta as td |
|
11 |
|
12 ctypes.pythonapi.PyString_AsString.argtypes = (ctypes.c_void_p,) |
|
13 ctypes.pythonapi.PyString_AsString.restype = ctypes.POINTER(ctypes.c_char) |
|
14 |
|
15 |
|
16 class IEC_STRING(Structure): |
|
17 """ |
|
18 Must be changed according to changes in iec_types.h |
|
19 """ |
|
20 _fields_ = [("len", c_uint8), |
|
21 ("body", c_char * 126)] |
|
22 |
|
23 |
|
24 class IEC_TIME(Structure): |
|
25 """ |
|
26 Must be changed according to changes in iec_types.h |
|
27 """ |
|
28 _fields_ = [("s", c_long), # tv_sec |
|
29 ("ns", c_long)] # tv_nsec |
|
30 |
|
31 |
|
32 def _t(t, u=lambda x: x.value, p=lambda t, x: t(x)): |
|
33 return (t, u, p) |
|
34 |
|
35 |
|
36 def _ttime(): |
|
37 return (IEC_TIME, |
|
38 lambda x: td(0, x.s, x.ns/1000), |
|
39 lambda t, x: t(x.days * 24 * 3600 + x.seconds, x.microseconds*1000)) |
|
40 |
|
41 |
|
42 SameEndianessTypeTranslator = { |
|
43 "BOOL": _t(c_uint8, lambda x: x.value != 0), |
|
44 "STEP": _t(c_uint8), |
|
45 "TRANSITION": _t(c_uint8), |
|
46 "ACTION": _t(c_uint8), |
|
47 "SINT": _t(c_int8), |
|
48 "USINT": _t(c_uint8), |
|
49 "BYTE": _t(c_uint8), |
|
50 "STRING": (IEC_STRING, |
|
51 lambda x: x.body[:x.len], |
|
52 lambda t, x: t(len(x), x)), |
|
53 "INT": _t(c_int16), |
|
54 "UINT": _t(c_uint16), |
|
55 "WORD": _t(c_uint16), |
|
56 "DINT": _t(c_int32), |
|
57 "UDINT": _t(c_uint32), |
|
58 "DWORD": _t(c_uint32), |
|
59 "LINT": _t(c_int64), |
|
60 "ULINT": _t(c_uint64), |
|
61 "LWORD": _t(c_uint64), |
|
62 "REAL": _t(c_float), |
|
63 "LREAL": _t(c_double), |
|
64 "TIME": _ttime(), |
|
65 "TOD": _ttime(), |
|
66 "DATE": _ttime(), |
|
67 "DT": _ttime(), |
|
68 } |
|
69 |
|
70 SwapedEndianessTypeTranslator = { |
|
71 # TODO |
|
72 } |
|
73 |
|
74 TypeTranslator = SameEndianessTypeTranslator |
|
75 |
|
76 # Construct debugger natively supported types |
|
77 DebugTypesSize = dict([(key, sizeof(t)) for key, (t, p, u) in SameEndianessTypeTranslator.iteritems() if t is not None]) |
|
78 |
|
79 |
|
80 def UnpackDebugBuffer(buff, indexes): |
|
81 res = [] |
|
82 buffoffset = 0 |
|
83 buffsize = len(buff) |
|
84 buffptr = cast(ctypes.pythonapi.PyString_AsString(id(buff)), c_void_p).value |
|
85 for iectype in indexes: |
|
86 c_type, unpack_func, _pack_func = \ |
|
87 TypeTranslator.get(iectype, (None, None, None)) |
|
88 if c_type is not None and buffoffset < buffsize: |
|
89 cursor = c_void_p(buffptr + buffoffset) |
|
90 value = unpack_func(cast(cursor, |
|
91 POINTER(c_type)).contents) |
|
92 buffoffset += sizeof(c_type) if iectype != "STRING" else len(value)+1 |
|
93 res.append(value) |
|
94 else: |
|
95 break |
|
96 if buffoffset and buffoffset == buffsize: |
|
97 return res |
|
98 return None |