]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - support/sdk/python/tinyos/tossim/TossimNescDecls.py
Merge devel code into the trunk.
[tinyos-2.x.git] / support / sdk / python / tinyos / tossim / TossimNescDecls.py
diff --git a/support/sdk/python/tinyos/tossim/TossimNescDecls.py b/support/sdk/python/tinyos/tossim/TossimNescDecls.py
new file mode 100644 (file)
index 0000000..67a15c5
--- /dev/null
@@ -0,0 +1,771 @@
+# "Copyright (c) 2000-2003 The Regents of the University of California.  
+# All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose, without fee, and without written agreement
+# is hereby granted, provided that the above copyright notice, the following
+# two paragraphs and the author appear in all copies of this software.
+# 
+# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
+# OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# 
+# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+# ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+#
+# @author Kamin Whitehouse 
+#
+
+import sys, string, math, re, os
+from struct import *
+from xml.dom import minidom
+from copy import deepcopy
+
+###########
+# This class can be used to hold a basic nesc type, eg uint8_t It can
+# be set and get through nescType.value, and does type checking
+# 
+###########
+
+def findBuildFile(givenString, desiredFilename) :
+  """This function will find a desiredFilename (eg. nescDecls.xml) the build directory
+  from a givenString (e.g 'build/pc').  Legal givenStrings are:
+  1.  Full path,     eg: /home/kamin/tinyos-1.x/...
+  2.  relative path, eg: apps/TestRpc/build/pc
+  3.  platform name, eg: pc or telosb
+  """
+
+  #check to see if the given string contains the desiredFilename
+  if givenString.find(desiredFilename) >= 0 :
+    filename = givenString
+
+  #then check to see if it is an absolute or relative path
+  elif givenString.find('/') >= 0 :
+    filename = givenString + desiredFilename
+
+  #then check to see if it is just the platform name
+  elif len(givenString) > 0:
+    filename = 'build/' + givenString + '/' + desiredFilename
+
+  #check if a default platform environment variable is defined
+  elif os.environ.has_key("TINYOS_DEFAULT_PLATFORM") :
+    filename = 'build/' + os.environ["TINYOS_DEFAULT_PLATFORM"] + '/' + desiredFilename
+
+  #otherwise, assume the file is in './'
+  else :
+    filename = desiredFilename
+    
+  #check to see if the file was successfully found
+  if not os.path.isfile(filename) :
+    raise IOError("File %s not found" % filename)
+  return filename
+
+  
+class nescType( object ) :
+  """A python representation of a nesc type.
+
+  usage:
+  X = nescType.value
+  nescType.value = X
+  bytes = nescType.getBytes()
+  nescType.setBytes(bytes)
+  nescType
+  print nescType
+  """
+
+  def __init__( self , nescType, cType, pythonType, xmlTag,
+                conversionString, size, defaultValue) :
+    """create a new nescType"""
+    self.nescType = nescType
+    self.cType = cType
+    self.pythonType = pythonType
+    self._xmlTag = xmlTag
+    self.size = size
+    self._conversionString = conversionString
+    self.value = defaultValue
+
+  def __repr__(self) :
+    return "%s object at %s:\n\n%20s : %s" % (self.__class__, hex(id(self)), "value", str(self))
+
+  def __str__(self) :
+    if self._conversionString == "c" :
+        return "'" + str(self.value) + "'"
+    else :
+        return str(self.value)
+
+  #   this func could be used for type checking 
+  def __setattr__(self, name, value) :
+    if self.__dict__.has_key("value") and name == "value":
+        #use the type conversions built into pack
+        pack(self._conversionString, value)
+    self.__dict__[name] = value
+
+  def oneLineStr(self) :
+    return str(self)
+
+  def __deepcopy__(self, memo={}) :
+    result = nescType(self.nescType, self.cType, self.pythonType,
+                    self._xmlTag, self._conversionString, self.size,
+                    deepcopy(self.value, memo))
+    memo[id(self)] = result
+    return result
+  
+  def isType(self, xmlDefinition) :
+    """returns 1 if the xml definition describes this type.
+    Returns 0 otherwise."""
+    if xmlDefinition != None and xmlDefinition.tagName == self._xmlTag and \
+           xmlDefinition.hasAttribute("cname") and \
+           xmlDefinition.getAttribute("cname") == self.cType :
+      return 1
+    elif self.nescType == "void" and xmlDefinition.tagName == self._xmlTag :
+      #void is a special xml case that doesn't have cname defined (grr)
+      return 1
+    else :
+      return 0
+  
+  def getBytes(self) :
+    """Hexidecimal representation of a value of this type"""
+    if self.nescType == "void" :
+      return ''
+    try:
+      bytes = pack(self._conversionString, self.value)
+    except Exception, inst:
+      print inst
+      raise Exception("Bytes conversion error: %s %d bytes to %d" %
+                      (self.nescType, len(bytes), self.size) )
+    if len(bytes) != self.size:
+      raise Exception("Wrong number of bytes for conversion: %s %d bytes to %d" %
+                      (self.nescType, len(bytes), self.size))
+    return bytes
+  
+  def setBytes(self, bytes):
+    """A value of this type from a hexidecimal representation"""
+    if self.nescType == "void" :
+      return bytes
+    if len(bytes) < self.size:
+      raise Exception("Wrong number of bytes for conversion: %s %d bytes to %d" %
+                      (self.nescType, len(bytes), self.size))
+    try:
+      self.value, = unpack( self._conversionString, bytes[:self.size])
+    except Exception, inst:
+      print inst
+      raise Exception("Bytes conversion error: %s %d bytes to %d" %
+                      ( self.nescType, len(bytes), self.size) )
+    return bytes[self.size:]
+
+###########
+# Array of basic nesc types,
+###########
+
+class nescArray( object ) :
+  """A python representation of a nesc array.
+
+  usage:
+  array = nescArray(size, nescType)
+  array = nescArray(myTypes, xmlDecl)
+  X = array[3]
+  X = array[3:6] (returns a list or, if char[] array, a python string)
+  array[3] = X
+  array[3:6] [X,Y,Z] (or, if char[], \"foo\")
+  bytes = array.getBytes()
+  array.setBytes(bytes)
+  array
+  print array
+  """
+
+  def __init__( self , *varargs) :
+    """initialize all elements to 0"""
+    if len(varargs) == 0 :
+      return
+    elif len(varargs) == 2 and type(varargs[0]) == int :
+      (self.len,self.elementType) = varargs[:]
+      bracketStr = "[" + str(self.len) + "]"
+    elif len(varargs) == 2 :
+      (nescTypes, xmlDefinition) = varargs[:]
+      if xmlDefinition.tagName != "type-array" :
+        raise Exception("Not array definition")
+      child = getUniqueChild(xmlDefinition)
+      self.elementType = nescTypes.getTypeFromXML(child)
+      sizeStr = xmlDefinition.getAttribute("elements")[2:]
+      self.len = int(sizeStr)
+      bracketStr = "[" + sizeStr + "]"
+    else :
+      raise Exception("Illegal array params")
+    self.nescType = self.elementType.nescType + bracketStr
+    self.cType = self.elementType.cType + bracketStr
+    self.pythonType = self.elementType.pythonType + bracketStr
+    self.size = self.len * self.elementType.size
+    self.value = []
+    for i in range(self.len):
+      self.value.append(deepcopy(self.elementType))
+      
+
+  def __repr__(self) :
+    """A printable representation of the value"""
+    return "%s object at %s:\n\n\t%s" % (self.__class__, hex(id(self)), str(self))
+    
+  def __str__(self) :
+    """A printable representation of the value"""
+    string = "nescArray of type %s:\n" % self.nescType
+#     if self.elementType._conversionString == "c":
+#       string += self.oneLineStr()
+#     else:
+    for i in range(self.len) :
+      string += "%2d: %s\n" % (i, self.value[i].oneLineStr())
+    return string
+
+  def __getitem__(self, key) :
+      if self.elementType.__class__ == nescType :
+          if key.__class__ == slice:
+              if self.elementType._conversionString == "c":
+                  string = ""
+                  for item in self.value.__getitem__(key) :
+                      string += item.value
+                  return string
+              else:
+                  return [item.value for item in self.value.__getitem__(key)]
+          else:
+              return self.value.__getitem__(key).value
+      else:
+          return self.value.__getitem__(key)
+      
+  def __setitem__(self, key, value) : 
+      if self.elementType.__class__ == nescType :
+        if key.__class__ == slice:
+            i=0;
+            for item in self.value.__getitem__(key) :
+                item.value = value[i]
+                i += 1
+        else:
+            self.value.__getitem__(key).value = value
+      else :
+          self.value.__setitem__(key, value)
+
+  def __delitem__(self, key) : 
+      return self.value.__delitem__(key)
+
+  def oneLineStr(self) :
+    """A one-line representation of the value"""
+    #maybe the string should just print like a string
+    #but the \x00 chars look like nothing
+#     if self.elementType._conversionString == "c":
+#       string = '\''
+#       for c in self.value :
+#         string += c.value
+#       string += '\''
+#     else:
+    tmpStr = str(self.elementType)
+    if tmpStr.find("\n") >= 0 or len(tmpStr) > 5 :
+      return self.nescType
+    else :
+      i = 0; string = "["
+      while len(string) < 40 and i < self.len :
+        string += str(self.value[i]) + ", "
+        i += 1
+      if i < self.len :
+        string += "...]"
+      else:
+        string += "\b\b]"
+    return string
+  def __deepcopy__(self, memo={}) :
+    result = nescArray()
+    memo[id(self)] = result
+    result.elementType = deepcopy(self.elementType, memo)
+    result.nescType = self.nescType
+    result.cType = self.cType
+    result.pythonType = self.pythonType
+    result.len = self.len
+    result.size = self.size
+    result.value = deepcopy(self.value, memo)
+    return result
+
+  def isType(self, xmlDefinition) :
+    """returns 1 if the xml definition describes this type.
+    Returns 0 otherwise."""
+    if ( xmlDefinition != None and xmlDefinition.tagName == "type-array" and
+         int(xmlDefinition.getAttribute("elements")[2:]) == self.len ) :
+      child = getUniqueChild(xmlDefinition)
+      return self.elementType.isType(child)
+    else :
+      return 0
+
+  def getBytes(self) :
+    """Hexidecimal representation of a value of this type"""
+    bytes = ""
+    for i in range(self.len):
+      bytes += self.value[i].getBytes()
+    if len(bytes) != self.size:
+      raise Exception("Byte conversion error: %s %d bytes to %d" %
+                      ( self.nescType, len(bytes), self.size))
+    return bytes
+    
+  
+  def setBytes(self, bytes) :
+    """A value of this type from a hexidecimal representation"""
+    if len(bytes) < self.size:
+        raise Exception("Byte conversion error: %s %d bytes to %d" %
+                        (self.nescType, len(bytes), self.size) )
+    for i in range(self.len) :
+      bytes = self.value[i].setBytes(bytes)
+    return bytes
+
+###########
+# Pointer to basic nesc types,
+###########
+
+class nescPointer( object ) :
+  """A python representation of a nesc pointer.
+
+  usage:
+  pointer = nescPointer(ptrSize, nescType)
+  pointer = nescPointer(myTypes, xmlDecl)
+  nescType = pointer.value
+  pointer.value = nescType
+  bytes = pointer.getBytes()
+  pointer.setBytes(bytes)
+  pointer
+  print pointer
+  """
+  
+  def __init__( self , *varargs) :
+    """initialize all elements to 0"""
+    if len(varargs) == 0:
+      return
+    elif len(varargs) == 2 and varargs[1].__dict__.has_key("tagName"):
+      (nescTypes, xmlDefinition) = varargs[:]
+      if xmlDefinition.tagName != "type-pointer" :
+        raise Exception("Not pointer definition")
+      child = getUniqueChild(xmlDefinition)
+      self.value = nescTypes.getTypeFromXML(child)
+      self.size = int(xmlDefinition.getAttribute("size")[2:])
+    elif len(varargs) == 2 :
+      self.size = varargs[0].types["unsigned int"].size
+      self.value = varargs[1]
+    else :
+      raise Exception("Illegal nescPointer constructor arguments")
+    self.nescType = self.value.nescType + "*"
+    self.cType = self.value.cType + "*"
+    self.pythonType = self.value.pythonType + "*"
+      
+  def __repr__(self) :
+    return "%s object at %s:\n\n\t%s" % (self.__class__, hex(id(self)), str(self))
+
+  def __str__(self) :
+    """A text representation of the value"""
+    return "ptr-> %s" % str(self.value)
+
+  def oneLineStr(self) :
+    """A one-line representation of the value"""
+    return  "ptr-> %s" % self.value.oneLineStr()
+
+  def __deepcopy__(self, memo={}) :
+    result = nescPointer()
+    memo[id(self)] = result
+    result.value = deepcopy(self.value, memo)
+    result.size = self.size
+    result.nescType = self.nescType
+    result.cType = self.cType
+    result.pythonType = self.pythonType
+    return result
+
+  def isType(self, xmlDefinition) :
+    """returns 1 if the xml definition describes this type.
+    Returns 0 otherwise."""
+    if xmlDefinition != None and xmlDefinition.tagName == "type-pointer" :
+      child = getUniqueChild(xmlDefinition)
+      return self.value.isType(child)
+    else :
+      return 0
+
+  def getBytes(self) :
+      bytes = pack (str(self.size)+"s",'\x00')
+      if len(bytes) != self.size:
+          raise Exception("Byte conversion error: %s %d bytes to %d" %
+                          (self.nescType, len(bytes), self.size) )
+      return bytes
+  
+  def setBytes(self, bytes) :
+    if len(bytes) < self.size:
+        raise Exception("Byte conversion error: %s %d bytes to %d" %
+                        ( self.nescType, len(bytes), self.size) )
+    return bytes[self.size:]
+
+
+###########
+# Struct of basic nesc types,
+###########
+
+class nescStruct( object ) :
+  """A python representation of a nesc structure.
+
+  usage:
+  struct = nescStruct(myTypes, xmlDecl)
+  struct = nescStruct(structName, (fieldName, type) (fieldName, type), ...)
+  X = struct.field
+  struct.field = X
+  bytes = struct.getBytes()
+  struct.setBytes(bytes)
+  struct
+  print struct
+  """
+
+  def __init__( self, *varargs) :
+    """initialize all fields to 0"""
+    self.__dict__["value"] = {}
+    self.fields = []
+    self.size = 0
+    if len(varargs) == 0 :
+      self.nescType = ""
+    #create the struct from nescType args
+    elif len(varargs) >= 1 and ( type(varargs[0]) == str or
+                                 type(varargs[0]) == unicode ) :
+      self.nescType = varargs[0]
+      self._parseNescTypeFields(varargs[1:])
+    ## parse the struct def from xml
+    elif len(varargs) == 2 and type(varargs[1]) != tuple :
+      (nescTypes, xmlDefinition) = varargs[:]
+      if xmlDefinition.tagName != "struct" :
+        raise Exception("Not struct definition")
+      if xmlDefinition.hasAttribute("name") == False:
+        raise Exception("Anonymous struct")
+      self.nescType = xmlDefinition.getAttribute("name")
+      if xmlDefinition.getAttribute("size")[2:]:
+        self.size = int(xmlDefinition.getAttribute("size")[2:])
+      else:
+        self.size = 0
+      self._parseXMLFields(nescTypes, xmlDefinition)
+    else :
+      raise Exception("Illegal nescStruct constructor args")
+    self.cType = self.nescType
+    self.pythonType = self.nescType
+    self.__initialized = True
+    
+  def __getattr__(self, name) :
+    if self.__dict__.has_key("value") :
+      if self.value.has_key(name) :
+        if self.value[name].__class__ == nescType :
+          return self.value[name].value
+        else :
+          return self.value[name]
+    else :
+      raise AttributeError("No such field \"%s\" in the nescStruct \"%s\"" % (name, self.nescType))
+
+  def __setattr__(self, name, value) :
+    if not self.__dict__.has_key("_nescStruct__initialized") :
+      self.__dict__[name] = value
+      return
+    if self.value.has_key(name) :
+      if self.value[name].__class__ == nescType :
+          self.value[name].value = value;
+      else :
+          self.value[name] = value;
+    elif self.__dict__.has_key(name) :
+      self.__dict__[name] = value
+    else :
+      raise AttributeError("No such field \"%s\" in the nescStruct \"%s\"" % (name, self.nescType))
+        
+
+  def __repr__(self) :
+    return "%s object at %s:\n\n\t%s" % (self.__class__, hex(id(self)), str(self))
+    
+  def __str__(self) :
+    """All fields and values as a readable string"""
+    string = self.nescType + ": \n"
+    for field in self.fields :
+      string += "%30s  : %s\n" % (
+        "%s %s" % (self.value[field["name"]].nescType, field["name"]),
+        self.value[field["name"]].oneLineStr() )
+    return string
+
+  def oneLineStr(self) :
+    """A one-line representation of the struct"""
+    return self.nescType
+
+  def __deepcopy__(self, memo={}) :
+    result = self.__class__()
+    memo[id(self)] = result
+    self._copyFields(result, memo)
+    return result
+
+  def _copyFields(self, other, memo=None) :
+    other.size = self.size
+    other.nescType = self.nescType
+    other.cType = self.cType
+    other.pythonType = self.pythonType
+    if memo == None :
+      other.value = deepcopy(self.value)
+      other.fields = deepcopy(self.fields)
+    else :
+      other.value = deepcopy(self.value, memo)
+      other.fields = deepcopy(self.fields, memo)
+    other.__initialized = True
+
+  def _parseXMLFields(self, nescTypes, xmlDefinition) :
+    """Create a list of fields & values given a struct xml declaration."""
+    fields = [node for node in xmlDefinition.getElementsByTagName("field")]
+    fields.sort( lambda A, B :  int(A.getAttribute("bit-offset")[2:]) - int(B.getAttribute("bit-offset")[2:]))
+    for fieldDef in fields:
+      field = {}
+      field["name"] = fieldDef.getAttribute("name")
+      field["bitOffset"] = int(fieldDef.getAttribute("bit-offset")[2:])
+      if fieldDef.hasAttribute("bit-size"):
+          field["bitSize"] = int(fieldDef.getAttribute("bit-size")[2:])
+      elif fieldDef.hasAttribute("size"):
+          field["bitSize"] = int(fieldDef.getAttribute("size")[2:])*8
+      self.fields.append(field)
+      self.value[fieldDef.getAttribute("name")] = nescTypes.getTypeFromXML(fieldDef)
+    #here's a weird bug in the nesc.xml generation where the "size" attribute
+    #for packed structs is actually the size of the unpacked struct.
+    if xmlDefinition.hasAttribute("packed") :
+      self.size = self.packedSize()
+    elif xmlDefinition.getAttribute("size")[2:]:
+      self.size = int(xmlDefinition.getAttribute("size")[2:])
+    else:
+      self.size = 0
+  def _parseNescTypeFields(self, fields) :
+    """Create a list of fields & values given a tuple of
+    fieldname,value sequences."""
+    self.size = 0
+    for fieldDef in fields:
+      field = {}
+      (field["name"],fType) = fieldDef
+      field["bitOffset"] = self.size*8
+      field["bitSize"] = fType.size*8
+      self.fields.append(field)
+      self.value[field["name"]] = fType
+      self.size += fType.size
+  
+  def isType(self, xmlDefinition) :
+    """returns 1 if the xml definition describes this type.
+    Returns 0 otherwise."""
+    if xmlDefinition == None :
+      return 0
+    child = getUniqueChild(xmlDefinition)
+    if ( ( xmlDefinition.tagName == "struct" and
+           xmlDefinition.getAttribute("name") == self.nescType) or
+         ( xmlDefinition.tagName == "type-tag" and child != None and 
+           child.tagName == "struct-ref" and
+           child.getAttribute("name") == self.nescType ) ) :
+      return 1
+    else :
+      return 0
+
+  def getBytes(self) :
+    """Hexidecimal representation of struct"""
+    # We have to be careful in here about:
+    # 1.  bit fields (ie. bitSize shorter than nominal type size)
+    # 2.  packing (ie. bits that are not part of any particular field)
+    bits = ""
+    for field in self.fields :
+      for i in range(len(bits), field["bitOffset"]) :
+        bits += "0"
+      newBits = hex2bin(self.value[field["name"]].getBytes())
+      bits += newBits[-field["bitSize"]:]
+      #the following loop is just type checking for bit fields.  Can we do this on setattr?
+      for i in range(len(newBits)-field["bitSize"]):
+          if newBits[i] == "1":
+              print "Bit-field type error: value of %s.%s being truncated" % (self.nescType,
+                                                        field["name"])
+    for i in range(len(bits), self.size*8) :
+      bits += "0"
+    bytes = bin2hex(bits)
+    if len(bytes) != self.size:
+      raise Exception("Byte conversion error: %s %d bytes to %d" %
+                      ( self.nescType, len(bytes), self.size))
+    return bytes
+
+  def setBytes(self, bytes) :
+    """Set all values using hexidecimal representation"""
+    # We have to be careful in here about:
+    # 1.  bit fields (ie. bitSize shorter than nominal type size)
+    # 2.  packing (ie. bits that are not part of any particular field)
+    if len(bytes) < self.size:
+      raise Exception("Byte conversion error: %s %d bytes to %d" %
+                      (self.nescType, len(bytes), self.size) )
+    bits = hex2bin(bytes)
+    for field in self.fields :
+      newBits = ""
+      for i in range(self.value[field["name"]].size*8) :
+        newBits += "0"
+      selectedBits=bits[field["bitOffset"]:field["bitOffset"]+field["bitSize"]]
+      newBits = newBits[:-field["bitSize"]] + selectedBits
+      newBytes = ""
+      for i in range(self.value[field["name"]].size) :
+        newBytes += '\x00'
+      tmpBytes = bin2hex(newBits)
+      newBytes = newBytes[:-len(tmpBytes)] + tmpBytes
+      self.value[field["name"]].setBytes(newBytes);
+    return bytes[self.size:]
+
+  def packedSize(self) :
+    if len(self.fields) == 0 :
+      trueSize = 0
+    else :
+      a,b,lastField = self._findLastNestedField()
+      trueSize = (lastField["bitOffset"] + lastField["bitSize"]) /8
+    return trueSize
+
+  def _findLastNestedField(self) :
+    lastField = self
+    parents = []
+    #find the last (possibly nested) field
+    while issubclass(type(lastField), nescStruct) and len(lastField.fields) > 0 :
+      parent = lastField
+      lastFieldDef = parent.fields[-1]
+      lastField = parent.value[lastFieldDef["name"]]
+      parents.append( parent )
+    return (lastField, parents, lastFieldDef)
+
+
+
+
+
+class TosMsg ( nescStruct ) :
+    """A python representation of a TosMsg.
+    Is a nescStruct object.
+    Can be used with
+    pytos.comm.send, pytos.comm.register, pytos.comm.unregister.
+    
+    usage:
+    msg = TosMsg(amType)
+    msg = TosMsg(amType, nescStruct)
+    msg = TosMsg(amType, <nescStruct constructor args>)
+    print msg
+    msg.field = X
+    comm.send(msg)
+    comm.register(msg, f)
+    comm.unregister(msg, f)
+    migMsg = msg.createMigMsg()
+    msg.parseMigMsg(migMsg)
+    """
+
+    def __init__(self, amType, *varargs):
+        self.amType = amType
+        self.parentMsg = None
+        #if this is a nescStruct argument, make myself a clone of it
+        if len(varargs) == 1 and issubclass(type(varargs[0]), nescStruct) :
+            nescStruct._copyFields(varargs[0],self)
+        #otherwise, make myself into a struct with the struct args
+        elif len(varargs) >= 1:
+            nescStruct.__init__(self, *varargs)
+
+    def __deepcopy__(self, memo={}) :
+      result = self.__class__(self.amType)
+      memo[id(self)] = result
+      self._copyFields(result, memo)
+      result.parentMsg = deepcopy(self.parentMsg, memo)
+      return result
+
+    def getParentMsg(self, amOrName) :
+      """This function will get the parent message with the amType or name specified"""
+      if self.parentMsg == None :
+        return None
+      elif self.parentMsg.nescType == amOrName or self.parentMsg.amType == amOrName :
+        return self.parentMsg
+      else :
+        return self.parentMsg.getParentMsg(amOrName)
+      
+    def createMigMsg(self) :
+        """Returns a java BaseTOSMsg with same amType and length
+        and with data payload of same bytes"""
+        Message = tinyos.message.Message()
+        msg = Message(self.size)
+        msg.dataSet(unpack( str(self.size) + 'b', self.getBytes() ) )
+        msg.amTypeSet(self.amType)
+#        msg.set_type( self.amType )
+#        msg.set_length(self.size)
+        return msg
+
+    def parseMigMsg(self, msg) :
+        """Takes a java BaseTOSMsg and creates TosMsg
+        with same amType and length and with data payload of same bytes"""
+        self.amType = msg.amType()
+        data = list(msg.dataGet())
+        self.setBytes(pack(str(len(data)) + 'b', *data))
+
+    def __repr__(self) :
+      return "%s object at %s:\n\n\t%s" % (self.__class__, hex(id(self)), str(self))
+      
+    def __str__(self) :
+        """All fields and values as a readable string"""
+        return "TosMsg(am=%d) " % self.amType + nescStruct.__str__(self)
+        
+    def setBytes(self, bytes) :
+        """Extend this msg to be longer, if necessary to accomodate extra data.
+        This only happens if the last field is a nescArray of length 0.
+        Unlike nescStructs, TosMsg objects are not nested recursively, so it is
+        Ok to do this."""
+        if len(bytes) > self.size : #trueSize() :
+            #print "there are more bytes than fit in this msg... trying to grow msg"
+            lastField, parents,b = self._findLastNestedField()
+            #see if it is an array of size 0
+            if type(lastField) == nescArray and lastField.len == 0 :
+                #make it bigger
+                #print "last field is nescArray[0]... growing"
+                lastFieldSize = lastField.elementType.size
+                numExtraBytes = len(bytes) - self.size #trueSize()
+                if numExtraBytes % lastFieldSize == 0:
+                    requiredArraySize = int( numExtraBytes/lastFieldSize )
+                    lastField = nescArray(requiredArraySize, lastField.elementType)
+                #print "new size is %d" % numExtraBytes
+                #and set it, changing the size of all parent structs
+                parents.reverse()
+                for parent in parents :
+#                    trueSize = parent.trueSize()
+                    parent.value[parent.fields[-1]["name"]] = lastField
+                    parent.fields[-1]["bitSize"] = lastField.size*8
+                    parent.size = self.packedSize()# + lastField.size
+                    lastField = parent
+            else:
+                #print "last field is not nescArray[0]. Cannot grow. Ignoring extra data."
+                pass
+            
+        #make sure everything worked out correctly and call parent's function
+        if len(bytes) != self.size :#trueSize() :
+            raise Exception("Incorrect number of bytes for TosMsg. Byte conversion error: %s %d bytes to %d" % ( self.nescType, len(bytes), self.size) )
+        #print "passing to child to set bytes."
+        nescStruct.setBytes(self,bytes)
+
+
+
+
+
+
+
+def getUniqueChild(xmlDefinition) :
+  child = None
+  for childNode in xmlDefinition.childNodes :
+    if childNode.nodeType == 1 :
+      child = childNode
+      break
+  return child
+
+def bin2hex(bits) :
+    bytes = ""
+    for i in range(0, len(bits), 8 ):
+        bytes += pack('B',int(bits[i:i+8],2))
+    return bytes
+
+def hex2bin(bytes) :
+    bits = ""
+    for i in range(len(bytes)) :
+        val, = unpack('B',bytes[i])
+        for j in range(7,-1,-1):
+            if val>= pow(2,j):
+                bits += "1"
+                val -= pow(2,j)
+            else :
+                bits += "0"
+    return bits
+
+
+def TestAppTypes() :
+    testRpc = appTypes('/home/kamin/tinyos-1.x/contrib/hood/apps/TestRpc/build/telosb/nesc.xml')
+    print testRpc
+    
+if __name__ == "__main__": TestAppTypes()