docs: def _do_math(self, offset, expression):
          '''
          Parses and evaluates complex expressions, e.g., "(4.l+12)", "(6*32)", etc.
  
          @offset      - The offset inside self.data that the current signature starts at.
          @expressions - The expression to evaluate.
  
          Returns an integer value that is the result of the evaluated expression.
          '''
          # Does the expression contain an offset (e.g., "(4.l+12)")?
          if '.' in expression and '(' in expression:
              replacements = {}
  
              for period in [match.start() for match in self.period.finditer(expression)]:
                  # Separate the offset field into the integer offset and type
                  # values (o and t respsectively)
                  s = expression[:period].rfind('(') + 1
                  # The offset address may be an evaluatable expression, such as '(4+0.L)', typically the result
                  # of the original offset being something like '(&0.L)'.
                  o = binwalk.core.common.MathExpression(expression[s:period]).value
                  t = expression[period + 1]
  
                  # Re-build just the parsed offset portion of the expression
                  text = "%s.%c" % (expression[s:period], t)
  
                  # Have we already evaluated this offset expression? If so, skip
                  # it.
                  if binwalk.core.common.has_key(replacements, text):
                      continue
  
                  # The offset specified in the expression is relative to the
                  # starting offset inside self.data
                  o += offset
  
                  # Read the value from self.data at the specified offset
                  try:
                      # Big and little endian byte format
                      if t in ['b', 'B']:
                          v = struct.unpack('b', binwalk.core.compat.str2bytes(self.data[o:o + 1]))[0]
                      # Little endian short format
                      elif t == 's':
                          v = struct.unpack('<h', binwalk.core.compat.str2bytes(self.data[o:o + 2]))[0]
                      # Little endian long format
                      elif t == 'l':
                          v = struct.unpack('<i', binwalk.core.compat.str2bytes(self.data[o:o + 4]))[0]
                      # Big endian short format
                      elif t == 'S':
                          v = struct.unpack('>h', binwalk.core.compat.str2bytes(self.data[o:o + 2]))[0]
                      # Bit endian long format
                      elif t == 'L':
                          v = struct.unpack('>i', binwalk.core.compat.str2bytes(self.data[o:o + 4]))[0]
                  # struct.error is thrown if there is not enough bytes in
                  # self.data for the specified format type
                  except struct.error as e:
                      v = 0
  
                  # Keep track of all the recovered values from self.data
                  replacements[text] = v
  
              # Finally, replace all offset expressions with their corresponding
              # text value
              v = expression
              for (text, value) in binwalk.core.common.iterator(replacements):
                  v = v.replace(text, "%d" % value)
  
          # If no offset, then it's just an evaluatable math expression (e.g.,
          # "(32+0x20)")
          else:
              v = expression
  
          # Evaluate the final expression
          value = binwalk.core.common.MathExpression(v).value
  
          return value