Edouard@592: #!/usr/bin/env python
Edouard@592: # -*- coding: utf-8 -*-
Edouard@592: #
andrej@1667: # See COPYING.Runtime file for copyrights details.
Edouard@592: #
andrej@1881: 
andrej@1881: from __future__ import absolute_import
Edouard@1433: import ctypes
andrej@1783: from ctypes import *
andrej@1783: from datetime import timedelta as td
andrej@1783: 
Edouard@1433: ctypes.pythonapi.PyString_AsString.argtypes = (ctypes.c_void_p,)
Edouard@1433: ctypes.pythonapi.PyString_AsString.restype = ctypes.POINTER(ctypes.c_char)
Edouard@1433: 
Edouard@1433: 
Edouard@592: class IEC_STRING(Structure):
Edouard@592:     """
Edouard@592:     Must be changed according to changes in iec_types.h
Edouard@592:     """
Edouard@592:     _fields_ = [("len", c_uint8),
Edouard@1433:                 ("body", c_char * 126)]
Edouard@592: 
andrej@1736: 
Edouard@592: class IEC_TIME(Structure):
Edouard@592:     """
Edouard@592:     Must be changed according to changes in iec_types.h
Edouard@592:     """
andrej@1737:     _fields_ = [("s", c_long),   # tv_sec
andrej@1737:                 ("ns", c_long)]  # tv_nsec
Edouard@592: 
andrej@1736: 
andrej@1835: def _t(t, u=lambda x: x.value, p=lambda t, x: t(x)):
andrej@1835:     return (t, u, p)
andrej@1736: 
andrej@1736: 
andrej@1835: def _ttime():
andrej@1835:     return (IEC_TIME,
surkovsv93@1963:             lambda x: td(0, x.s, x.ns/1000.0),
andrej@1835:             lambda t, x: t(x.days * 24 * 3600 + x.seconds, x.microseconds*1000))
Edouard@592: 
andrej@1749: 
Edouard@592: SameEndianessTypeTranslator = {
andrej@1774:     "BOOL":       _t(c_uint8, lambda x: x.value != 0),
andrej@1739:     "STEP":       _t(c_uint8),
andrej@1739:     "TRANSITION": _t(c_uint8),
andrej@1739:     "ACTION":     _t(c_uint8),
andrej@1739:     "SINT":       _t(c_int8),
andrej@1739:     "USINT":      _t(c_uint8),
andrej@1739:     "BYTE":       _t(c_uint8),
andrej@1739:     "STRING":     (IEC_STRING,
andrej@1740:                    lambda x: x.body[:x.len],
andrej@1740:                    lambda t, x: t(len(x), x)),
andrej@1739:     "INT":        _t(c_int16),
andrej@1739:     "UINT":       _t(c_uint16),
andrej@1739:     "WORD":       _t(c_uint16),
andrej@1739:     "DINT":       _t(c_int32),
andrej@1739:     "UDINT":      _t(c_uint32),
andrej@1739:     "DWORD":      _t(c_uint32),
andrej@1739:     "LINT":       _t(c_int64),
andrej@1739:     "ULINT":      _t(c_uint64),
andrej@1739:     "LWORD":      _t(c_uint64),
andrej@1739:     "REAL":       _t(c_float),
andrej@1739:     "LREAL":      _t(c_double),
andrej@1739:     "TIME":       _ttime(),
andrej@1739:     "TOD":        _ttime(),
andrej@1739:     "DATE":       _ttime(),
andrej@1739:     "DT":         _ttime(),
Edouard@1433:     }
Edouard@592: 
Edouard@592: SwapedEndianessTypeTranslator = {
andrej@1733:     # TODO
Edouard@1433:     }
Edouard@592: 
andrej@1742: TypeTranslator = SameEndianessTypeTranslator
Edouard@1075: 
Edouard@592: # Construct debugger natively supported types
andrej@1758: DebugTypesSize = dict([(key, sizeof(t)) for key, (t, p, u) in SameEndianessTypeTranslator.iteritems() if t is not None])
Edouard@592: 
andrej@1736: 
Edouard@1433: def UnpackDebugBuffer(buff, indexes):
andrej@1758:     res = []
Edouard@1433:     buffoffset = 0
Edouard@1433:     buffsize = len(buff)
andrej@1740:     buffptr = cast(ctypes.pythonapi.PyString_AsString(id(buff)), c_void_p).value
Edouard@1433:     for iectype in indexes:
andrej@1847:         c_type, unpack_func, _pack_func = \
andrej@1767:             TypeTranslator.get(iectype, (None, None, None))
Edouard@1433:         if c_type is not None and buffoffset < buffsize:
andrej@1747:             cursor = c_void_p(buffptr + buffoffset)
andrej@1747:             value = unpack_func(cast(cursor,
andrej@1768:                                      POINTER(c_type)).contents)
Edouard@1433:             buffoffset += sizeof(c_type) if iectype != "STRING" else len(value)+1
Edouard@1433:             res.append(value)
Edouard@1075:         else:
Edouard@1075:             break
Edouard@1433:     if buffoffset and buffoffset == buffsize:
Edouard@1075:         return res
Edouard@1075:     return None