#!/usr/bin/python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

""""Processes a log file and resolves IPC message identifiers.

Resolves IPC messages of the form [unknown type NNNNNN] to named IPC messages.

e.g. logfile containing

I/stderr  ( 3915): ipc 3915.3.1370207904 2147483647 S [unknown type 66372]

will be transformed to:

I/stderr  ( 3915): ipc 3915.3.1370207904 2147483647 S ViewMsg_SetCSSColors

In order to find the message header files efficiently, it requires that
Chromium is checked out using git.
"""

from __future__ import print_function

import optparse
import os
import re
import subprocess
import sys


def _SourceDir():
  """Get chromium's source directory."""
  return os.path.join(sys.path[0], '..')


def _ReadLines(f):
  """Read from file f and generate right-stripped lines."""
  for line in f:
    yield line.rstrip()


def _GetMsgStartTable():
  """Read MsgStart enumeration from ipc/ipc_message_utils.h.

  Determines the message type identifiers by reading.
  header file ipc/ipc_message_utils.h and looking for
  enum IPCMessageStart.  Assumes following code format in header file:
  enum IPCMessageStart {
     Type1MsgStart ...,
     Type2MsgStart,
  };

  Returns:
      A dictionary mapping StartName to enumeration value.
  """
  ipc_message_file = _SourceDir() + '/ipc/ipc_message_utils.h'
  ipc_message_lines = _ReadLines(open(ipc_message_file))
  is_msg_start = False
  count = 0
  msg_start_table = dict()
  for line in ipc_message_lines:
    if is_msg_start:
      if line.strip() == '};':
        break
      msgstart_index = line.find('MsgStart')
      msg_type = line[:msgstart_index] + 'MsgStart'
      msg_start_table[msg_type.strip()] = count
      count+=1
    elif line.strip() == 'enum IPCMessageStart {':
      is_msg_start = True

  return msg_start_table


def _FindMessageHeaderFiles():
  """Look through the source directory for *_messages.h."""
  os.chdir(_SourceDir())
  pipe = subprocess.Popen(['git', 'ls-files', '--', '*_messages.h'],
                          stdout=subprocess.PIPE)
  return _ReadLines(pipe.stdout)


def _GetMsgId(msg_start, line_number, msg_start_table):
  """Construct the meessage id given the msg_start and the line number."""
  hex_str = '%x%04x' % (msg_start_table[msg_start], line_number)
  return int(hex_str, 16)


def _ReadHeaderFile(f, msg_start_table, msg_map):
  """Read a header file and construct a map from message_id to message name."""
  msg_def_re = re.compile(
      '^IPC_(?:SYNC_)?MESSAGE_[A-Z0-9_]+\(([A-Za-z0-9_]+).*')
  msg_start_re = re.compile(
      '^\s*#define\s+IPC_MESSAGE_START\s+([a-zA-Z0-9_]+MsgStart).*')
  msg_start = None
  msg_name = None
  line_number = 0

  for line in f:
    line_number+=1
    match = re.match(msg_start_re, line)
    if match:
      msg_start = match.group(1)
      # print("msg_start = " + msg_start)
    match = re.match(msg_def_re, line)
    if match:
      msg_name = match.group(1)
      # print("msg_name = " + msg_name)
    if msg_start and msg_name:
      msg_id = _GetMsgId(msg_start, line_number, msg_start_table)
      msg_map[msg_id] = msg_name
  return msg_map


def _ResolveMsg(msg_type, msg_map):
  """Fully resolve a message type to a name."""
  if msg_type in msg_map:
    return msg_map[msg_type]
  else:
    return '[Unknown message %d (0x%x)]x' % (msg_type, msg_type)


def _ProcessLog(f, msg_map):
  """Read lines from f and resolve the IPC messages according to msg_map."""
  unknown_msg_re = re.compile('\[unknown type (\d+)\]')
  for line in f:
    line = line.rstrip()
    match = re.search(unknown_msg_re, line)
    if match:
      line = re.sub(unknown_msg_re,
                    _ResolveMsg(int(match.group(1)), msg_map),
                    line)
    print(line)


def _GetMsgMap():
  """Returns a dictionary mapping from message number to message name."""
  msg_start_table = _GetMsgStartTable()
  msg_map = dict()
  for header_file in _FindMessageHeaderFiles():
    _ReadHeaderFile(open(header_file),
                    msg_start_table,
                    msg_map)
  return msg_map


def main():
  """Processes one or more log files with IPC logging messages.

     Replaces '[unknown type NNNNNN]' with resolved
     IPC messages.

     Reads from standard input if no log files specified on the
     command line.
  """
  parser = optparse.OptionParser('usage: %prog [LOGFILE...]')
  (_, args) = parser.parse_args()

  msg_map = _GetMsgMap()
  log_files = args

  if log_files:
    for log_file in log_files:
      _ProcessLog(open(log_file), msg_map)
  else:
    _ProcessLog(sys.stdin, msg_map)


if __name__ == '__main__':
  main()
