# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""A code generator for TPM 2.0 commands.

The command generator takes as input a list of command objects generated by
parsing the TCG specification and outputs valid C code to marshal command
input and output structures, and also generates functions ParseHandleBuffer
and CommandDispatcher defined by the TCG TPM2.0 Library Specification.

"""

from __future__ import print_function

import re
from subprocess import call

from structure_generator import COPYRIGHT_HEADER
from structure_generator import Field

_HEADER_FILE_GUARD_HEADER = """
#ifndef TPM2_%(name)s_FP_H_
#define TPM2_%(name)s_FP_H_
"""
_HEADER_FILE_GUARD_FOOTER = """
#endif  // TPM2_%(name)s_FP_H
"""
_HEADER_FILE_INCLUDES = """
#include "tpm_generated.h"
"""
_IMPLEMENTATION_FILE_INCLUDES = """
#include "MemoryLib_fp.h"
#include "%(command_name)s_fp.h"
"""
_COMMAND_DISPATCHER_INCLUDES = '#include "%(command_name)s_fp.h"\n'
_COMMAND_DISPATCHER_START = """
#include "Implementation.h"
#include "CommandDispatcher_fp.h"

TPM_RC CommandDispatcher(
    TPMI_ST_COMMAND_TAG tag,
    TPM_CC command_code,
    INT32 *request_parameter_buffer_size,
    BYTE *request_parameter_buffer_start,
    TPM_HANDLE request_handles[],
    UINT32 *response_handle_buffer_size,
    UINT32 *response_parameter_buffer_size) {
  BYTE *request_parameter_buffer = request_parameter_buffer_start;
  switch(command_code) {"""
_COMMAND_DISPATCHER_CASE = """
#ifdef %(command_code)s
    case %(command_code)s:
      return Exec_%(command_name)s(tag, &request_parameter_buffer,
          request_parameter_buffer_size, request_handles,
          response_handle_buffer_size, response_parameter_buffer_size);
#endif"""
_COMMAND_DISPATCHER_END = """
    default:
      return TPM_RC_COMMAND_CODE;
  }
}"""
_HANDLE_PROCESS_START = """
#include "tpm_generated.h"
#include "HandleProcess_fp.h"
#include "Implementation.h"
#include "TPM_Types.h"

TPM_RC ParseHandleBuffer(
    TPM_CC command_code,
    BYTE **request_handle_buffer_start,
    INT32 *request_buffer_remaining_size,
    TPM_HANDLE request_handles[],
    UINT32 *num_request_handles) {
  TPM_RC result = TPM_RC_SUCCESS;
  *num_request_handles = 0;
  switch(command_code) {
"""
_HANDLE_PROCESS_CASE_START = """
#ifdef %(command_code)s
    case %(command_code)s:"""
_HANDLE_PROCESS_CASE_UNMARSHAL = """
      result = %(handle_type)s_Unmarshal(
          (%(handle_type)s*)&request_handles[*num_request_handles],
          request_handle_buffer_start,
          request_buffer_remaining_size);"""
_HANDLE_PROCESS_CASE_UNMARSHAL_FLAG = """
      result = %(handle_type)s_Unmarshal(
          (%(handle_type)s*)&request_handles[*num_request_handles],
          request_handle_buffer_start,
          request_buffer_remaining_size,
          %(flag_val)s);"""
_HANDLE_PROCESS_CASE_CHECK = """
      if (result != TPM_RC_SUCCESS) {
        return result;
      }
      ++(*num_request_handles);"""
_HANDLE_PROCESS_CASE_END = """
      return TPM_RC_SUCCESS;
#endif"""
_HANDLE_PROCESS_END = """
    default:
      return TPM_RC_COMMAND_CODE;
  }
}"""
_GET_COMMAND_CODE_STRING_HEADER = """
#ifndef TPM2_GET_COMMAND_CODE_STRING_FP_H_
#define TPM2_GET_COMMAND_CODE_STRING_FP_H_

#include "TPM_Types.h"

const char* GetCommandCodeString(TPM_CC command_code);

#endif  // TPM2_GET_COMMAND_CODE_STRING_FP_H_"""
_GET_COMMAND_CODE_STRING_START = """
#include "GetCommandCodeString_fp.h"

const char* GetCommandCodeString(TPM_CC command_code) {
  switch(command_code) {"""
_GET_COMMAND_CODE_STRING_CASE = """
#ifdef TPM_CC_%(command_name)s
  case TPM_CC_%(command_name)s:
      return "%(command_name)s";
#endif"""
_GET_COMMAND_CODE_STRING_END = """
    default:
      return "Unknown command";
  }
}"""


class Command(object):
  """Represents a TPM command.

  Attributes:
    name: The command name (e.g. 'TPM2_Startup').
    command_code: The name of the command code constant (e.g. TPM2_CC_Startup).
    request_args: A list to hold command input arguments. Each element is a dict
        and has these keys:
            'type': The argument type.
            'name': The argument name.
            'command_code': The optional value of the command code constant.
            'description': Optional descriptive text for the argument.
            'has_conditional': String literal 'TRUE' or 'FALSE' indicating
                whether 'type' is allowed to have a conditional value.
    response_args: A list identical in form to request_args but to hold command
        output arguments.
  """

  _HANDLE_RE = re.compile(r'TPMI_.H_.*')
  _STRUCT_DECL_START = """
typedef struct {"""
  _STRUCT_DECL_FIELD = """
  %(type)s %(name)s;"""
  _STRUCT_DECL_END = """
} %(command_name)s_%(direction)s;
"""
  _FUNCTION_DECL_IN_OUT = """
// Executes %(command_name)s with request handles and parameters from
// |in| and computes response handles and parameters to |out|.
TPM_RC TPM2_%(command_name)s(
    %(command_name)s_In *in,
    %(command_name)s_Out *out);

// Initializes handle fields in |target| from |request_handles|. Unmarshals
// parameter fields in |target| from |buffer|.
TPM_RC %(command_name)s_In_Unmarshal(
    %(command_name)s_In *target,
    TPM_HANDLE request_handles[],
    BYTE **buffer,
    INT32 *size);

// Marshals response handles and parameters from |source| to |buffer|. Computes
// and marshals the size of the parameter area (parameter_size) if |tag| ==
// TPM_ST_SESSIONS. Returns size of (parameter area + handle area) in bytes.
// Return value does not include parameter_size field.
UINT16 %(command_name)s_Out_Marshal(
    %(command_name)s_Out *source,
    TPMI_ST_COMMAND_TAG tag,
    BYTE **buffer,
    INT32 *size);
"""
  _FUNCTION_DECL_IN = """
// Executes %(command_name)s with request handles and parameters from |in|.
TPM_RC TPM2_%(command_name)s(
    %(command_name)s_In *in);

// Initializes handle fields in |target| from |request_handles|. Unmarshals
// parameter fields in |target| from |buffer|.
TPM_RC %(command_name)s_In_Unmarshal(
    %(command_name)s_In *target,
    TPM_HANDLE request_handles[],
    BYTE **buffer,
    INT32 *size);
"""
  _FUNCTION_DECL_OUT = """
// Executes %(command_name)s and computes response handles and parameters
// to |out|.
TPM_RC TPM2_%(command_name)s(
    %(command_name)s_Out *out);

// Marshals response handles and parameters from |source| to |buffer|. Computes
// and marshals the size of the parameter area (parameter_size) if |tag| ==
// TPM_ST_SESSIONS. Returns size of (parameter area + handle area) in bytes.
// Does not include parameter_size field.
UINT16 %(command_name)s_Out_Marshal(
    %(command_name)s_Out *source,
    TPMI_ST_COMMAND_TAG tag,
    BYTE **buffer,
    INT32 *size);
"""
  _EXEC_DECL = """
// Unmarshals any request parameters starting at |request_parameter_buffer|.
// Executes command. Marshals any response handles and parameters to the
// global response buffer and computes |*response_handle_buffer_size| and
// |*response_parameter_buffer_size|. If |tag| == TPM_ST_SESSIONS, marshals
// parameter_size indicating the size of the parameter area. parameter_size
// field is located between the handle area and parameter area.
TPM_RC Exec_%(command_name)s(
    TPMI_ST_COMMAND_TAG tag,
    BYTE **request_parameter_buffer,
    INT32 *request_parameter_buffer_size,
    TPM_HANDLE request_handles[],
    UINT32 *response_handle_buffer_size,
    UINT32 *response_parameter_buffer_size);
"""
  _EXEC_COMMAND_IMPL_START = """
TPM_RC Exec_%(command_name)s(
    TPMI_ST_COMMAND_TAG tag,
    BYTE **request_parameter_buffer,
    INT32 *request_parameter_buffer_size,
    TPM_HANDLE request_handles[],
    UINT32 *response_handle_buffer_size,
    UINT32 *response_parameter_buffer_size) {
  TPM_RC result = TPM_RC_SUCCESS;"""
  _EXEC_COMMAND_IMPL_IN_OUT = """
  %(command_name)s_In in;
  %(command_name)s_Out out;
#ifdef %(command_code)s
  BYTE *response_buffer;
  INT32 response_buffer_size;
  UINT16 bytes_marshalled;
  UINT16 num_response_handles = %(num_response_handles)s;
#endif
  *response_handle_buffer_size = 0;
  *response_parameter_buffer_size = 0;
  // Unmarshal request parameters to input structure.
  result = %(command_name)s_In_Unmarshal(&in, request_handles,
      request_parameter_buffer, request_parameter_buffer_size);
  if (result != TPM_RC_SUCCESS) {
    return result;
  }
  // Execute command.
  result = TPM2_%(command_name)s(&in, &out);
  if (result != TPM_RC_SUCCESS) {
    return result;
  }
  // Marshal output structure to global response buffer.
#ifdef %(command_code)s
  response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
  response_buffer_size = MAX_RESPONSE_SIZE - 10;
  bytes_marshalled = %(command_name)s_Out_Marshal(
      &out, tag, &response_buffer, &response_buffer_size);
  *response_handle_buffer_size = num_response_handles*sizeof(TPM_HANDLE);
  *response_parameter_buffer_size =
      bytes_marshalled - *response_handle_buffer_size;
  return TPM_RC_SUCCESS;
#endif
  return TPM_RC_COMMAND_CODE;
}
"""
  _EXEC_COMMAND_IMPL_IN = """
  %(command_name)s_In in;
#ifdef %(command_code)s
  BYTE *response_buffer;
  INT32 response_buffer_size;
#endif
  *response_handle_buffer_size = 0;
  *response_parameter_buffer_size = 0;
  // Unmarshal request parameters to input structure.
  result = %(command_name)s_In_Unmarshal(&in, request_handles,
      request_parameter_buffer, request_parameter_buffer_size);
  if (result != TPM_RC_SUCCESS) {
    return result;
  }
  // Execute command.
  result = TPM2_%(command_name)s(&in);
  if (result != TPM_RC_SUCCESS) {
    return result;
  }
#ifdef %(command_code)s
  response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
  response_buffer_size = MAX_RESPONSE_SIZE - 10;
  // Add parameter_size field, always equal to 0 here.
  if (tag == TPM_ST_SESSIONS) {
    UINT32_Marshal(response_parameter_buffer_size, &response_buffer,
        &response_buffer_size);
  }
  return TPM_RC_SUCCESS;
#endif
  return TPM_RC_COMMAND_CODE;
}
"""
  _EXEC_COMMAND_IMPL_OUT = """
  %(command_name)s_Out out;
#ifdef %(command_code)s
  BYTE *response_buffer;
  INT32 response_buffer_size;
  UINT16 bytes_marshalled;
  UINT16 num_response_handles = %(num_response_handles)s;
#endif
  *response_handle_buffer_size = 0;
  *response_parameter_buffer_size = 0;
  // Execute command.
  result = TPM2_%(command_name)s(&out);
  if (result != TPM_RC_SUCCESS) {
    return result;
  }
  // Marshal output structure containing response handles and parameters to
  // response buffer.
#ifdef %(command_code)s
  response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
  response_buffer_size = MAX_RESPONSE_SIZE - 10;
  bytes_marshalled = %(command_name)s_Out_Marshal(
      &out, tag, &response_buffer, &response_buffer_size);
  *response_handle_buffer_size = num_response_handles*sizeof(TPM_HANDLE);
  *response_parameter_buffer_size =
      bytes_marshalled - *response_handle_buffer_size;
  return TPM_RC_SUCCESS;
#endif
  return TPM_RC_COMMAND_CODE;
}
"""
  _UNMARSHAL_COMMAND_START = """
TPM_RC %(command_name)s_In_Unmarshal(
    %(command_name)s_In *target,
    TPM_HANDLE request_handles[],
    BYTE **buffer,
    INT32 *size) {
  TPM_RC result = TPM_RC_SUCCESS;"""
  _MARSHAL_COMMAND_START = """
UINT16 %(command_name)s_Out_Marshal(
    %(command_name)s_Out *source,
    TPMI_ST_COMMAND_TAG tag,
    BYTE **buffer,
    INT32 *size) {
  UINT16 total_size = 0;
  UINT32 parameter_size = 0;
  BYTE *parameter_size_location;
  INT32 parameter_size_size = sizeof(UINT32);
  UINT32 num_response_handles = %(num_response_handles)s;"""
  _UNMARSHAL_END = """
  if ((result == TPM_RC_SUCCESS) && *size) {
    result = TPM_RC_SIZE;
  }
  return result;
}
"""
  _MARSHAL_END = """
  // Compute actual parameter_size. Don't add result to total_size.
  if (tag == TPM_ST_SESSIONS) {
    parameter_size = total_size - num_response_handles*sizeof(TPM_HANDLE);
    UINT32_Marshal(
        &parameter_size, &parameter_size_location, &parameter_size_size);
  }
  return total_size;
}
"""
  _SET_COMMAND_HANDLE = """
  target->%(field_name)s = request_handles[%(num)s];"""
  _PARAMETERSIZE_CHECK = """
  // Add parameter_size=0 to indicate size of the parameter area. Will be
  // replaced later by computed parameter_size.
  if (tag == TPM_ST_SESSIONS) {
    parameter_size_location = *buffer;
    // Don't add to total_size, but increment *buffer and decrement *size.
    UINT32_Marshal(&parameter_size, buffer, size);
  }"""

  def __init__(self, name):
    """Initializes a Command instance.

    Initially the request_args and response_args attributes are not set.

    Args:
      name: The command name (e.g. 'TPM2_Startup').
    """
    self.name = name
    self.request_args = None
    self.response_args = None
    if name.startswith('TPM2_'):
      self.command_code = name.replace('TPM2_', 'TPM_CC_')
    else:
      self.command_code = ''

  def __str__(self):
    s = ['%s:' % self.name,]
    if self.request_args:
      s.append(' req:')
      for r in self.request_args:
        s.append('  %s: %s' % (r['type'], r['name']))
    if self.response_args:
      s.append(' resp:')
      for r in self.response_args:
        s.append('  %s: %s' % (r['type'], r['name']))
    s.append('')
    return '\n'.join(s)

  def OutputMarshalFunction(self, out_file, typemap):
    """Generates a marshal function for the command output structure.

    Args:
      out_file: File to be written to opened by the caller.
      typemap: A dict mapping type names to the corresponding object.
          Generated by structure_generator.
    """
    if not self.response_args:
      return
    # Categorize arguments as either handles or parameters.
    handles, parameters = self._SplitArgs(self.response_args)
    out_file.write(self._MARSHAL_COMMAND_START % {
        'command_name': self.MethodName(),
        'num_response_handles': self._GetNumberOfResponseHandles()})
    if handles:
      out_file.write('\n  // Marshal response handles.')
    for handle in handles:
      typemap[handle['type']].OutputMarshalCall(
          out_file, Field(handle['type'],
                          handle['name'],
                          conditional_value=handle['has_conditional']))
    out_file.write(self._PARAMETERSIZE_CHECK)
    if parameters:
      out_file.write('\n  // Marshal response parameters.')
    for parameter in parameters:
      typemap[parameter['type']].OutputMarshalCall(
          out_file, Field(parameter['type'], parameter['name'],
                          conditional_value=parameter['has_conditional']))
    out_file.write(self._MARSHAL_END)

  def OutputUnmarshalFunction(self, out_file, typemap):
    """Generates a unmarshal function for the command input structure.

    Args:
      out_file: File to be written to opened by the caller.
      typemap: A dict mapping type names to the corresponding object.
          Generated by structure_generator.
    """
    if not self.request_args:
      return
    # Categorize arguments as either handles or parameters.
    handles, parameters = self._SplitArgs(self.request_args)
    out_file.write(self._UNMARSHAL_COMMAND_START % {
        'command_name': self.MethodName()})
    if handles:
      out_file.write('\n  // Get request handles from request_handles array.')
    for index, handle in enumerate(handles):
      out_file.write(self._SET_COMMAND_HANDLE % {'field_name': handle['name'],
                                                 'num': index})
    if parameters:
      out_file.write('\n  // Unmarshal request parameters.')
    for parameter in parameters:
      typemap[parameter['type']].OutputUnmarshalCall(
          out_file, Field(parameter['type'],
                          parameter['name'],
                          conditional_value=parameter['has_conditional']))
    out_file.write(self._UNMARSHAL_END)

  def OutputExecFunction(self, out_file):
    """Generates an exec function for the command.

    Args:
      out_file: File to be written to opened by the caller.
    """
    out_file.write(
        self._EXEC_COMMAND_IMPL_START % {'command_name': self.MethodName()})
    if self.request_args and self.response_args:
      out_file.write(self._EXEC_COMMAND_IMPL_IN_OUT % {
          'command_name': self.MethodName(),
          'command_code': self.command_code,
          'num_response_handles': self._GetNumberOfResponseHandles()})
    elif self.request_args:
      out_file.write(self._EXEC_COMMAND_IMPL_IN % {
          'command_name': self.MethodName(),
          'command_code': self.command_code})
    elif self.response_args:
      out_file.write(self._EXEC_COMMAND_IMPL_OUT % {
          'command_name': self.MethodName(),
          'command_code': self.command_code,
          'num_response_handles': self._GetNumberOfResponseHandles()})

  def OutputDecl(self, out_file):
    """Generates a TPM object declaration."""
    if self.request_args:
      out_file.write(self._STRUCT_DECL_START)
      for arg in self.request_args:
        out_file.write(self._STRUCT_DECL_FIELD % {'type': arg['type'],
                                                  'name': arg['name']})
      out_file.write(self._STRUCT_DECL_END % {'command_name': self.MethodName(),
                                              'direction': 'In'})
    if self.response_args:
      out_file.write(self._STRUCT_DECL_START)
      for arg in self.response_args:
        out_file.write(self._STRUCT_DECL_FIELD % {'type': arg['type'],
                                                  'name': arg['name']})
      out_file.write(self._STRUCT_DECL_END % {'command_name': self.MethodName(),
                                              'direction': 'Out'})
    if len(self.response_args) and len(self.request_args):
      out_file.write(
          self._FUNCTION_DECL_IN_OUT % {'command_name': self.MethodName()})
    elif self.response_args:
      out_file.write(
          self._FUNCTION_DECL_OUT % {'command_name': self.MethodName()})
    elif self.request_args:
      out_file.write(
          self._FUNCTION_DECL_IN % {'command_name': self.MethodName()})
    out_file.write(self._EXEC_DECL % {'command_name': self.MethodName()})

  def _GetNumberOfRequestHandles(self):
    """Returns the number of input handles for this command."""
    return len(self._SplitArgs(self.request_args)[0])

  def _GetNumberOfResponseHandles(self):
    """Returns the number of output handles for this command."""
    return len(self._SplitArgs(self.response_args)[0])

  def MethodName(self):
    """Creates an appropriate generated method name for the command.

    We use the command name without the TPM2_ prefix.

    Returns:
      The method name.
    """
    if not self.name.startswith('TPM2_'):
      return self.name
    return self.name[5:]

  def GetRequestHandles(self):
    """Returns a list of input handles for this command."""
    return self._SplitArgs(self.request_args)[0]

  def _SplitArgs(self, args):
    """Splits a list of args into handles and parameters."""
    always_params = {
        'TPM_CC_FlushContext': 'TPMI_DH_CONTEXT',
        'TPM_CC_Hash': 'TPMI_RH_HIERARCHY',
        'TPM_CC_LoadExternal': 'TPMI_RH_HIERARCHY',
        'TPM_CC_SequenceComplete': 'TPMI_RH_HIERARCHY',
    }
    handles = []
    parameters = []
    always_handle = set(['TPM_HANDLE'])
    # Handle types that appear as command parameters.
    always_parameter = set(['TPMI_RH_ENABLES', 'TPMI_DH_PERSISTENT'])
    if self.command_code in always_params:
      always_parameter.add(always_params[self.command_code])
    for arg in args:
      if (arg['type'] in always_handle or
          (self._HANDLE_RE.search(arg['type']) and
           arg['type'] not in always_parameter)):
        handles.append(arg)
      else:
        parameters.append(arg)
    return handles, parameters


def _OutputCommandDispatcher(commands):
  """Generates implementation file for CommandDispatcher function.

  Args:
    commands: A list of Command objects.
  """
  with open('CommandDispatcher.c', 'w') as out_file:
    out_file.write(COPYRIGHT_HEADER)
    for command in commands:
      out_file.write(_COMMAND_DISPATCHER_INCLUDES %
                     {'command_name': command.MethodName()})
    out_file.write(_COMMAND_DISPATCHER_START)
    for command in commands:
      command_code = 'TPM_CC_' + command.MethodName()
      out_file.write(_COMMAND_DISPATCHER_CASE %
                     {'command_code': command_code,
                      'command_name': command.MethodName()})
    out_file.write(_COMMAND_DISPATCHER_END)
  call(['clang-format', '-i', '-style=Chromium', 'CommandDispatcher.c'])


def _OutputHandleProcess(commands, typemap):
  """Generates implementation file for ParseHandleBuffer function.

  Args:
    commands: A list of Command objects.
    typemap: A dict mapping type names to the corresponding object.
        Generated by structure_generator.
  """
  with open('HandleProcess.c', 'w') as out_file:
    out_file.write(COPYRIGHT_HEADER)
    out_file.write(_HANDLE_PROCESS_START)
    for command in commands:
      command_code = 'TPM_CC_' + command.MethodName()
      out_file.write(_HANDLE_PROCESS_CASE_START %
                     {'command_code': command_code})
      for handle in command.GetRequestHandles():
        if typemap[handle['type']].HasConditional():
          out_file.write(_HANDLE_PROCESS_CASE_UNMARSHAL_FLAG %
                         {'handle_type': handle['type'],
                          'flag_val': handle['has_conditional']})
        else:
          out_file.write(_HANDLE_PROCESS_CASE_UNMARSHAL %
                         {'handle_type': handle['type']})
        out_file.write(_HANDLE_PROCESS_CASE_CHECK)
      out_file.write(_HANDLE_PROCESS_CASE_END)
    out_file.write(_HANDLE_PROCESS_END)
  call(['clang-format', '-i', '-style=Chromium', 'HandleProcess.c'])


def _OutputGetCommandCodeString(commands):
  """Generates header and implementation files for GetCommandCodeString.

  Args:
    commands: A list of Command objects.
  """
  with open('GetCommandCodeString_fp.h', 'w') as out_file:
    out_file.write(COPYRIGHT_HEADER)
    out_file.write(_GET_COMMAND_CODE_STRING_HEADER)
  call(['clang-format', '-i', '-style=Chromium', 'GetCommandCodeString_fp.h'])
  with open('GetCommandCodeString.c', 'w') as out_file:
    out_file.write(COPYRIGHT_HEADER)
    out_file.write(_GET_COMMAND_CODE_STRING_START)
    for command in commands:
      out_file.write(_GET_COMMAND_CODE_STRING_CASE %
                     {'command_name': command.MethodName()})
    out_file.write(_GET_COMMAND_CODE_STRING_END)
  call(['clang-format', '-i', '-style=Chromium', 'GetCommandCodeString.c'])


def GenerateHeader(commands):
  """Generates a header file with declarations for all given generator objects.

  Args:
    commands: A list of Command objects.
  """
  for command in commands:
    command_header_file = command.MethodName()+'_fp.h'
    with open(command_header_file, 'w') as out_file:
      out_file.write(COPYRIGHT_HEADER)
      out_file.write(
          _HEADER_FILE_GUARD_HEADER % {'name': command.MethodName().upper()})
      out_file.write(_HEADER_FILE_INCLUDES)
      command.OutputDecl(out_file)
      out_file.write(
          _HEADER_FILE_GUARD_FOOTER % {'name': command.MethodName().upper()})
    call(['clang-format', '-i', '-style=Chromium', command_header_file])


def GenerateImplementation(commands, typemap):
  """Generates implementation code for each command.

  Args:
    commands: A list of Command objects.
    typemap: A dict mapping type names to the corresponding object.
        Generated by structure_generator.
  """
  for command in commands:
    marshal_command_file = 'Marshal_'+command.MethodName()+'.c'
    with open(marshal_command_file, 'w') as out_file:
      out_file.write(COPYRIGHT_HEADER)
      out_file.write(_IMPLEMENTATION_FILE_INCLUDES %
                     {'command_name': command.MethodName()})
      command.OutputMarshalFunction(out_file, typemap)
      command.OutputUnmarshalFunction(out_file, typemap)
      command.OutputExecFunction(out_file)
    call(['clang-format', '-i', '-style=Chromium', marshal_command_file])
  _OutputHandleProcess(commands, typemap)
  _OutputCommandDispatcher(commands)
  _OutputGetCommandCodeString(commands)