Created a code generator for TPM 2.0 structures and commands.

The generator generates declarations for all types and all command
methods. This CL does not generate the implementation of these methods.

BUG=chromium:372002
TEST=ran unit tests
     manual inspection, lint, and compilation of generated code

Change-Id: Ica564c96241b998a6a1a3e9f9203c5f357745d4f
Reviewed-on: https://chromium-review.googlesource.com/200097
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
Commit-Queue: Darren Krahn <dkrahn@chromium.org>
Tested-by: Darren Krahn <dkrahn@chromium.org>
diff --git a/trunks/generator/generator.py b/trunks/generator/generator.py
new file mode 100755
index 0000000..077ebf3
--- /dev/null
+++ b/trunks/generator/generator.py
@@ -0,0 +1,726 @@
+#!/usr/bin/python
+
+# Copyright (c) 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 structures and commands.
+
+The generator takes as input a structures file as emitted by the
+extract_structures.sh script and a commands file as emitted by the
+extract_commands.sh script.  It outputs valid C++ into tpm_generated.{h,cc}.
+
+The input grammar is documented in the extract_* scripts. Sample input for
+structures looks like this:
+_BEGIN_TYPES
+_OLD_TYPE UINT32
+_NEW_TYPE TPM_HANDLE
+_END
+_BEGIN_CONSTANTS
+_CONSTANTS (UINT32) TPM_SPEC
+_TYPE UINT32
+_NAME TPM_SPEC_FAMILY
+_VALUE 0x322E3000
+_NAME TPM_SPEC_LEVEL
+_VALUE 00
+_END
+_BEGIN_STRUCTURES
+_STRUCTURE TPMS_TIME_INFO
+_TYPE UINT64
+_NAME time
+_TYPE TPMS_CLOCK_INFO
+_NAME clockInfo
+_END
+
+Sample input for commands looks like this:
+_BEGIN
+_INPUT_START TPM2_Startup
+_TYPE TPMI_ST_COMMAND_TAG
+_NAME tag
+_COMMENT TPM_ST_NO_SESSIONS
+_TYPE UINT32
+_NAME commandSize
+_TYPE TPM_CC
+_NAME commandCode
+_COMMENT TPM_CC_Startup {NV}
+_TYPE TPM_SU
+_NAME startupType
+_COMMENT TPM_SU_CLEAR or TPM_SU_STATE
+_OUTPUT_START TPM2_Startup
+_TYPE TPM_ST
+_NAME tag
+_COMMENT see clause 8
+_TYPE UINT32
+_NAME responseSize
+_TYPE TPM_RC
+_NAME responseCode
+_END
+"""
+
+import argparse
+import re
+
+
+_COPYRIGHT_HEADER = ('// Copyright (c) 2014 The Chromium OS Authors. All '
+                     'rights reserved.\n// Use of this source code is '
+                     'governed by a BSD-style license that can be found\n'
+                     '// in the LICENSE file.\n\n// THIS CODE IS GENERATED - '
+                     'DO NOT MODIFY!\n')
+_HEADER_FILE_GUARD_HEADER = '\n#ifndef %(name)s\n#define %(name)s\n'
+_HEADER_FILE_GUARD_FOOTER = '\n#endif  // %(name)s\n'
+_HEADER_FILE_INCLUDES = ('\n#include <stdint.h>\n\n'
+                         '#include <string>\n\n'
+                         '#include <base/callback_forward.h>\n')
+_LOCAL_INCLUDE = '\n#include "%(filename)s"\n\n'
+_NAMESPACE_BEGIN = '\nnamespace Trunks {\n\n'
+_NAMESPACE_END = '\n}  // namespace Trunks\n'
+_CLASS_BEGIN = '\nclass Tpm {\n public:\n'
+_CLASS_END = '};\n'
+_OUTPUT_FILE_H = 'tpm_generated.h'
+_OUTPUT_FILE_CC = 'tpm_generated.cc'
+
+
+class Typedef(object):
+  """Represents a TPM typedef."""
+
+  _TYPEDEF = 'typedef %(old_type)s %(new_type)s;\n'
+
+  def __init__(self, old_type, new_type):
+    self.old_type = old_type
+    self.new_type = new_type
+
+  def OutputForward(self, out_file, defined_types, typemap):
+    """Outputs a typedef definition, forward declaration does not apply."""
+    self.Output(out_file, defined_types, typemap)
+
+  def Output(self, out_file, defined_types, typemap):
+    """Writes a typedef definition to |out_file|.
+
+    Any outstanding dependencies will be forward declared.
+
+    Args:
+      out_file: The output file.
+      defined_types: A set of types for which definitions have already been
+        generated.
+      typemap: A dict mapping type names to the corresponding object.
+    """
+    if self.new_type in defined_types:
+      return
+    # Make sure the dependency is already defined.
+    if self.old_type not in defined_types:
+      typemap[self.old_type].OutputForward(out_file, defined_types, typemap)
+    out_file.write(self._TYPEDEF % {'old_type': self.old_type,
+                                    'new_type': self.new_type})
+    defined_types.add(self.new_type)
+
+
+class Constant(object):
+  """Represents a TPM constant."""
+
+  _CONSTANT = 'const %(type)s %(name)s = %(value)s;\n'
+
+  def __init__(self, const_type, name, value):
+    self.const_type = const_type
+    self.name = name
+    self.value = value
+
+  def Output(self, out_file, defined_types, typemap):
+    """Writes a constant definition to |out_file|.
+
+    Any outstanding dependencies will be forward declared.
+
+    Args:
+      out_file: The output file.
+      defined_types: A set of types for which definitions have already been
+        generated.
+      typemap: A dict mapping type names to the corresponding object.
+    """
+    # Make sure the dependency is already defined.
+    if self.const_type not in defined_types:
+      typemap[self.const_type].OutputForward(out_file, defined_types, typemap)
+    out_file.write(self._CONSTANT % {'type': self.const_type,
+                                     'name': self.name,
+                                     'value': self.value})
+
+
+class Structure(object):
+  """Represents a TPM structure or union."""
+
+  _STRUCTURE = 'struct %(name)s {\n'
+  _STRUCTURE_FORWARD = 'struct %(name)s;\n'
+  _UNION = 'union %(name)s {\n'
+  _UNION_FORWARD = 'union %(name)s;\n'
+  _STRUCTURE_END = '};\n\n'
+  _STRUCTURE_FIELD = '  %(type)s %(name)s;\n'
+
+  def __init__(self, name, is_union):
+    self.name = name
+    self.is_union = is_union
+    self.fields = []
+    self.depends_on = []
+    self.forwarded = False
+
+  def AddField(self, field_name, field_type):
+    """Adds a field for this struct."""
+    self.fields.append((field_name, field_type))
+
+  def AddDependency(self, required_type):
+    """Adds an explicit dependency on another type.
+
+    This is used in cases where there is an additional dependency other than the
+    field types, which are implicit dependencies.  For example, a field like
+    FIELD_TYPE value[sizeof(OTHER_TYPE)] would need OTHER_TYPE to be already
+    declared.
+
+    Args:
+      required_type: The type this structure depends on.
+    """
+    self.depends_on.append(required_type)
+
+  def _GetFieldTypes(self):
+    return set([field[0] for field in self.fields])
+
+  def OutputForward(self, out_file, unused_defined_types, unused_typemap):
+    """Writes a structure forward declaration to |out_file|."""
+    if self.forwarded:
+      return
+    if self.is_union:
+      out_file.write(self._UNION_FORWARD % {'name': self.name})
+    else:
+      out_file.write(self._STRUCTURE_FORWARD % {'name': self.name})
+    self.forwarded = True
+
+  def Output(self, out_file, defined_types, typemap):
+    """Writes a structure definition to |out_file|.
+
+    Any outstanding dependencies will be defined.
+
+    Args:
+      out_file: The output file.
+      defined_types: A set of types for which definitions have already been
+        generated.
+      typemap: A dict mapping type names to the corresponding object.
+    """
+    if self.name in defined_types:
+      return
+    # Make sure any dependencies are already defined.
+    for field_type in self._GetFieldTypes():
+      if field_type not in defined_types:
+        typemap[field_type].Output(out_file, defined_types, typemap)
+    for required_type in self.depends_on:
+      if required_type not in defined_types:
+        typemap[required_type].Output(out_file, defined_types, typemap)
+    if self.is_union:
+      out_file.write(self._UNION % {'name': self.name})
+    else:
+      out_file.write(self._STRUCTURE % {'name': self.name})
+    for field in self.fields:
+      out_file.write(self._STRUCTURE_FIELD % {'type': field[0],
+                                              'name': field[1]})
+    out_file.write(self._STRUCTURE_END)
+    defined_types.add(self.name)
+
+
+class Define(object):
+  """Represents a preprocessor define."""
+
+  _DEFINE = '#if !defined(%(name)s)\n#define %(name)s %(value)s\n#endif\n'
+
+  def __init__(self, name, value):
+    self.name = name
+    self.value = value
+
+  def Output(self, out_file):
+    """Writes a preprocessor define to |out_file|."""
+    out_file.write(self._DEFINE % {'name': self.name, 'value': self.value})
+
+
+class StructureParser(object):
+  """Structure definition parser.
+
+  The input text file is extracted from the PDF file containing the TPM
+  structures specification from the Trusted Computing Group. The syntax
+  of the text file is defined by extract_structures.sh.
+
+  - Parses typedefs to a list of Typedef objects.
+  - Parses constants to a list of Constant objects.
+  - Parses structs and unions to a list of Structure objects.
+  - Parses defines to a list of Define objects.
+
+  The parser also creates 'typemap' dict which maps every type to its generator
+  object.  This typemap helps manage type dependencies.
+  """
+
+  # Compile regular expressions.
+  _BEGIN_TYPES_RE = re.compile(r'^_BEGIN_TYPES$')
+  _BEGIN_CONSTANTS_RE = re.compile(r'^_BEGIN_CONSTANTS$')
+  _BEGIN_STRUCTURES_RE = re.compile(r'^_BEGIN_STRUCTURES$')
+  _BEGIN_UNIONS_RE = re.compile(r'^_BEGIN_UNIONS$')
+  _BEGIN_DEFINES_RE = re.compile(r'^_BEGIN_DEFINES$')
+  _END_RE = re.compile(r'^_END$')
+  _OLD_TYPE_RE = re.compile(r'^_OLD_TYPE\s+(\w+)$')
+  _NEW_TYPE_RE = re.compile(r'^_NEW_TYPE\s+(\w+)$')
+  _CONSTANTS_SECTION_RE = re.compile(r'^_CONSTANTS.* (\w+)$')
+  _STRUCTURE_SECTION_RE = re.compile(r'^_STRUCTURE\s+(\w+)$')
+  _UNION_SECTION_RE = re.compile(r'^_UNION\s+(\w+)$')
+  _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
+  _NAME_RE = re.compile(r'^_NAME\s+([a-zA-Z0-9_()\[\]/\*\+\-]+)$')
+  _VALUE_RE = re.compile(r'^_VALUE\s+(.+)$')
+  _SIZEOF_RE = re.compile(r'^.*sizeof\(([a-zA-Z0-9_]*)\).*$')
+
+  def __init__(self, in_file):
+    self._line = None
+    self._in_file = in_file
+
+  def _NextLine(self):
+    try:
+      self._line = self._in_file.next()
+    except StopIteration:
+      self._line = None
+
+  def Parse(self):
+    """Parse everything in a structures file.
+
+    Returns:
+      Lists of objects and a type-map as described in the class documentation.
+      Returns these in the following order: types, constants, structs, defines,
+      typemap.
+    """
+
+    self._NextLine()
+    types = []
+    constants = []
+    structs = []
+    defines = []
+    typemap = {}
+    while self._line:
+      if self._BEGIN_TYPES_RE.search(self._line):
+        types += self._ParseTypes(typemap)
+      elif self._BEGIN_CONSTANTS_RE.search(self._line):
+        constants += self._ParseConstants(types, typemap)
+      elif self._BEGIN_STRUCTURES_RE.search(self._line):
+        structs += self._ParseStructures(self._STRUCTURE_SECTION_RE, typemap)
+      elif self._BEGIN_UNIONS_RE.search(self._line):
+        structs += self._ParseStructures(self._UNION_SECTION_RE, typemap)
+      elif self._BEGIN_DEFINES_RE.search(self._line):
+        defines += self._ParseDefines()
+      else:
+        print 'Invalid file format: %s' % self._line
+        break
+      self._NextLine()
+    # Empty structs not handled by the extractor.
+    self._AddEmptyStruct('TPMU_SYM_DETAILS', True, structs, typemap)
+    # Defines which are used in TPM 2.0 Part 2 but not defined there.
+    defines.append(Define(
+        'MAX_CAP_DATA', '(MAX_CAP_BUFFER-sizeof(TPM_CAP)-sizeof(UINT32))'))
+    defines.append(Define(
+        'MAX_CAP_ALGS', '(TPM_ALG_LAST - TPM_ALG_FIRST + 1)'))
+    defines.append(Define(
+        'MAX_CAP_HANDLES', '(MAX_CAP_DATA/sizeof(TPM_HANDLE))'))
+    defines.append(Define(
+        'MAX_CAP_CC', '((TPM_CC_LAST - TPM_CC_FIRST) + 1)'))
+    defines.append(Define(
+        'MAX_TPM_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))'))
+    defines.append(Define(
+        'MAX_PCR_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PCR_SELECT))'))
+    defines.append(Define(
+        'MAX_ECC_CURVES', '(MAX_CAP_DATA/sizeof(TPM_ECC_CURVE))'))
+    defines.append(Define('HASH_COUNT', '3'))
+    return types, constants, structs, defines, typemap
+
+  def _AddEmptyStruct(self, name, is_union, structs, typemap):
+    """Adds an empty Structure object to |structs| and |typemap|."""
+    s = Structure(name, is_union)
+    structs.append(s)
+    typemap[name] = s
+    return
+
+  def _ParseTypes(self, typemap):
+    """Parses a typedefs section.
+
+    The current line should be _BEGIN_TYPES and the method will stop parsing
+    when an _END line is found.
+
+    Args:
+      typemap: A dictionary to which parsed types are added.
+
+    Returns:
+      A list of Typedef objects.
+    """
+    types = []
+    self._NextLine()
+    while not self._END_RE.search(self._line):
+      match = self._OLD_TYPE_RE.search(self._line)
+      if not match:
+        print 'Invalid old type: %s' % self._line
+        return types
+      old_type = match.group(1)
+      self._NextLine()
+      match = self._NEW_TYPE_RE.search(self._line)
+      if not match:
+        print 'Invalid new type: %s' % self._line
+        return types
+      new_type = match.group(1)
+      t = Typedef(old_type, new_type)
+      types.append(t)
+      typemap[new_type] = t
+      self._NextLine()
+    return types
+
+  def _ParseConstants(self, types, typemap):
+    """Parses a constants section.
+
+    The current line should be _BEGIN_CONSTANTS and the method will stop parsing
+    when an _END line is found.
+
+    Args:
+      types: A typedef will be appended for each constant group.
+      typemap: A dictionary to which parsed types are added.
+
+    Returns:
+      A list of Constant objects.
+    """
+    constants = []
+    self._NextLine()
+    while not self._END_RE.search(self._line):
+      match = self._CONSTANTS_SECTION_RE.search(self._line)
+      if not match:
+        print 'Invalid constants section: %s' % self._line
+        return constants
+      constant_typename = match.group(1)
+      self._NextLine()
+      match = self._TYPE_RE.search(self._line)
+      if not match:
+        print 'Invalid constants type: %s' % self._line
+        return constants
+      constant_type = match.group(1)
+      # Create a typedef for the constant group name (e.g. TPM_RC).
+      typedef = Typedef(constant_type, constant_typename)
+      typemap[constant_typename] = typedef
+      types.append(typedef)
+      self._NextLine()
+      match = self._NAME_RE.search(self._line)
+      if not match:
+        print 'Invalid constant name: %s' % self._line
+        return constants
+      while match:
+        name = match.group(1)
+        self._NextLine()
+        match = self._VALUE_RE.search(self._line)
+        if not match:
+          print 'Invalid constant value: %s' % self._line
+          return constants
+        value = match.group(1)
+        constants.append(Constant(constant_typename, name, value))
+        self._NextLine()
+        match = self._NAME_RE.search(self._line)
+    return constants
+
+  def _ParseStructures(self, section_re, typemap):
+    """Parses structures / unions.
+
+    The current line should be _BEGIN_STRUCTURES or _BEGIN_UNIONS and the method
+    will stop parsing when an _END line is found.
+
+    Args:
+      section_re: The regular expression to use for matching section tokens.
+      typemap: A dictionary to which parsed types are added.
+
+    Returns:
+      A list of Structure objects.
+    """
+    structures = []
+    is_union = section_re == self._UNION_SECTION_RE
+    self._NextLine()
+    while not self._END_RE.search(self._line):
+      match = section_re.search(self._line)
+      if not match:
+        print 'Invalid structure section: %s' % self._line
+        return structures
+      current_structure = Structure(match.group(1), is_union)
+      self._NextLine()
+      match = self._TYPE_RE.search(self._line)
+      if not match:
+        print 'Invalid field type: %s' % self._line
+        return structures
+      while match:
+        field_type = match.group(1)
+        self._NextLine()
+        match = self._NAME_RE.search(self._line)
+        if not match:
+          print 'Invalid field name: %s' % self._line
+          return structures
+        field_name = match.group(1)
+        # If the field name includes 'sizeof(SOME_TYPE)', record the dependency
+        # on SOME_TYPE.
+        match = self._SIZEOF_RE.search(field_name)
+        if match:
+          current_structure.AddDependency(match.group(1))
+        # Manually change unfortunate names.
+        if field_name == 'xor':
+          field_name = 'xor_'
+        current_structure.AddField(field_type, field_name)
+        self._NextLine()
+        match = self._TYPE_RE.search(self._line)
+      structures.append(current_structure)
+      typemap[current_structure.name] = current_structure
+    return structures
+
+  def _ParseDefines(self):
+    """Parses preprocessor defines.
+
+    The current line should be _BEGIN_DEFINES and the method will stop parsing
+    when an _END line is found.
+
+    Returns:
+      A list of Define objects.
+    """
+    defines = []
+    self._NextLine()
+    while not self._END_RE.search(self._line):
+      match = self._NAME_RE.search(self._line)
+      if not match:
+        print 'Invalid name: %s' % self._line
+        return defines
+      name = match.group(1)
+      self._NextLine()
+      match = self._VALUE_RE.search(self._line)
+      if not match:
+        print 'Invalid value: %s' % self._line
+        return defines
+      value = match.group(1)
+      defines.append(Define(name, value))
+      self._NextLine()
+    return defines
+
+
+class Command(object):
+  """Represents a TPM command."""
+
+  def __init__(self, name):
+    self.name = name
+    self.command_code = ''
+    self.request_args = None
+    self.response_args = None
+
+  def OutputDeclarations(self, out_file):
+    self._OutputCallbackSignature(out_file)
+    self._OutputMethodSignature(out_file)
+
+  def _OutputMethodSignature(self, out_file):
+    args = self._ArgList(self.request_args)
+    if args:
+      args += ','
+    args += '\n      const %sResponse& callback' % self._MethodName()
+    out_file.write('  void %s(%s);\n' % (self._MethodName(), args))
+
+  def _OutputCallbackSignature(self, out_file):
+    args = self._ArgList(self.response_args)
+    if args:
+      args = ',' + args
+    args = '\n      TPM_RC response_code' + args
+    out_file.write('  typedef base::Callback<void(%s)> %sResponse;\n' %
+                   (args, self._MethodName()))
+
+  def _MethodName(self):
+    if not self.name.startswith('TPM2_'):
+      return self.name
+    return self.name[5:]
+
+  def _ArgList(self, args):
+    if args:
+      arg_list = ['%s %s' % (a['type'], a['name']) for a in args]
+      return '\n      ' + ',\n      '.join(arg_list)
+    return ''
+
+
+class CommandParser(object):
+  """Command definition parser.
+
+  The input text file is extracted from the PDF file containing the TPM
+  command specification from the Trusted Computing Group. The syntax
+  of the text file is defined by extract_commands.sh.
+  """
+
+  # Regular expressions to pull relevant bits from annotated lines.
+  _INPUT_START_RE = re.compile(r'^_INPUT_START\s+(\w+)$')
+  _OUTPUT_START_RE = re.compile(r'^_OUTPUT_START\s+(\w+)$')
+  _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
+  _NAME_RE = re.compile(r'^_NAME\s+(\w+)$')
+  # Pull the command code from a comment like: _COMMENT TPM_CC_Startup {NV}.
+  _COMMENT_CC_RE = re.compile(r'^_COMMENT\s+(TPM_CC_\w+).*$')
+  _COMMENT_RE = re.compile(r'^_COMMENT\s+(.*)')
+  # Args which are handled internally by the generated method.
+  _INTERNAL_ARGS = ('tag', 'Tag', 'commandSize', 'commandCode', 'responseSize',
+                    'responseCode')
+
+  def __init__(self, in_file):
+    self._line = None
+    self._in_file = in_file
+
+  def _NextLine(self):
+    try:
+      self._line = self._in_file.next()
+    except StopIteration:
+      self._line = None
+
+  def Parse(self):
+    """Parses everything in a commands file.
+
+    Returns:
+      A list of extracted Command objects.
+    """
+
+    commands = []
+    self._NextLine()
+    if self._line != '_BEGIN\n':
+      print 'Invalid format for first line: %s\n' % self._line
+      return commands
+    self._NextLine()
+
+    while self._line != '_END\n':
+      cmd = self._ParseCommand()
+      if not cmd:
+        break
+      commands.append(cmd)
+    return commands
+
+  def _ParseCommand(self):
+    """Parses inputs and outputs for a single TPM command."""
+    match = self._INPUT_START_RE.search(self._line)
+    if not match:
+      print 'Cannot match command input from line: %s\n' % self._line
+      return None
+    name = match.group(1)
+    cmd = Command(name)
+    self._NextLine()
+    cmd.request_args = self._ParseCommandArgs(cmd)
+    match = self._OUTPUT_START_RE.search(self._line)
+    if not match or match.group(1) != name:
+      print 'Cannot match command output from line: %s\n' % self._line
+      return None
+    self._NextLine()
+    cmd.response_args = self._ParseCommandArgs(cmd)
+    if not cmd.command_code:
+      print 'Command code not found for %s' % name
+      return None
+    return cmd
+
+  def _ParseCommandArgs(self, cmd):
+    """Parses a set of arguments."""
+    args = []
+    command_code = None
+    match = self._TYPE_RE.search(self._line)
+    while match:
+      arg_type = match.group(1)
+      self._NextLine()
+      match = self._NAME_RE.search(self._line)
+      if not match:
+        print 'Cannot match argument name from line: %s\n' % self._line
+        break
+      arg_name = match.group(1)
+      self._NextLine()
+      match = self._COMMENT_CC_RE.search(self._line)
+      if match:
+        cmd.command_code = match.group(1)
+      match = self._COMMENT_RE.search(self._line)
+      if match:
+        description = match.group(1)
+        self._NextLine()
+      else:
+        description = ''
+      if arg_name not in self._INTERNAL_ARGS:
+        args.append({'type': arg_type,
+                     'name': arg_name,
+                     'command_code': command_code,
+                     'description': description})
+      match = self._TYPE_RE.search(self._line)
+    return args
+
+
+def GenerateHeader(types, constants, structs, defines, typemap, commands):
+  """Generates a header file with declarations for all given generator objects.
+
+  Args:
+    types: A list of Typedef objects.
+    constants: A list of Constant objects.
+    structs: A list of Structure objects.
+    defines: A list of Define objects.
+    typemap: A dict mapping type names to the corresponding object.
+    commands: A list of Command objects.
+  """
+  out_file = open(_OUTPUT_FILE_H, 'w')
+  out_file.write(_COPYRIGHT_HEADER)
+  guard_name = 'TRUNKS_%s_' % _OUTPUT_FILE_H.upper().replace('.', '_')
+  out_file.write(_HEADER_FILE_GUARD_HEADER % {'name': guard_name})
+  out_file.write(_HEADER_FILE_INCLUDES)
+  out_file.write(_NAMESPACE_BEGIN)
+  # These types are built-in or defined by <stdint.h>; they serve as base cases
+  # when defining type dependencies.
+  defined_types = set(['uint8_t', 'int8_t', 'int', 'uint16_t', 'int16_t',
+                       'uint32_t', 'int32_t', 'uint64_t', 'int64_t'])
+  # Generate defines.  These must be generated before any other code.
+  for define in defines:
+    define.Output(out_file)
+  out_file.write('\n')
+  # Generate typedefs.  These are declared before structs because they are not
+  # likely to depend on structs and when they do a simple forward declaration
+  # for the struct can be generated.  This improves the readability of the
+  # generated code.
+  for typedef in types:
+    typedef.Output(out_file, defined_types, typemap)
+  out_file.write('\n')
+  # Generate constant definitions.  Again, generated before structs to improve
+  # readability.
+  for constant in constants:
+    constant.Output(out_file, defined_types, typemap)
+  out_file.write('\n')
+  # Generate structs.  All non-struct dependencies should be already declared.
+  for struct in structs:
+    struct.Output(out_file, defined_types, typemap)
+  # Generate a declaration for a 'Tpm' class, which includes one method for
+  # every TPM 2.0 command.
+  out_file.write(_CLASS_BEGIN)
+  for command in commands:
+    command.OutputDeclarations(out_file)
+  out_file.write(_CLASS_END)
+  out_file.write(_NAMESPACE_END)
+  out_file.write(_HEADER_FILE_GUARD_FOOTER % {'name': guard_name})
+  out_file.close()
+
+
+def GenerateImplementation(types, structs, typemap, commands):
+  """Generates implementation code for each command.
+
+  Args:
+    types: A list of Typedef objects.
+    structs: A list of Structure objects.
+    typemap: A dict mapping type names to the corresponding object.
+    commands: A list of Command objects.
+  """
+  out_file = open(_OUTPUT_FILE_CC, 'w')
+  out_file.write(_COPYRIGHT_HEADER)
+  out_file.write(_LOCAL_INCLUDE % {'filename': _OUTPUT_FILE_H})
+  out_file.write(_NAMESPACE_BEGIN)
+  # TODO(dkrahn): Generate implementation of the 'Tpm' class.
+  _ = types, structs, typemap, commands
+  out_file.write(_NAMESPACE_END)
+  out_file.close()
+
+
+def main():
+  parser = argparse.ArgumentParser(description='TPM 2.0 code generator')
+  parser.add_argument('structures_file')
+  parser.add_argument('commands_file')
+  args = parser.parse_args()
+  structure_parser = StructureParser(open(args.structures_file))
+  types, constants, structs, defines, typemap = structure_parser.Parse()
+  command_parser = CommandParser(open(args.commands_file))
+  commands = command_parser.Parse()
+  GenerateHeader(types, constants, structs, defines, typemap, commands)
+  GenerateImplementation(types, structs, typemap, commands)
+  print 'Processed %d commands.' % len(commands)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/trunks/generator/generator_test.py b/trunks/generator/generator_test.py
new file mode 100755
index 0000000..79a8d38
--- /dev/null
+++ b/trunks/generator/generator_test.py
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+
+# Copyright (c) 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.
+
+"""Unit tests for the TPM 2.0 code generator."""
+
+import StringIO
+import unittest
+
+import generator
+
+
+class TestGenerators(unittest.TestCase):
+  """Test generator classes."""
+
+  def testTypedef(self):
+    """Test generation of typedefs and dependencies."""
+    typedef = generator.Typedef('int', 'INT')
+    defined_types = set(['int'])
+    typemap = {}
+    out_file = StringIO.StringIO()
+    # Expect this to just write the typedef.
+    typedef.OutputForward(out_file, defined_types, typemap)
+    # Expect this to know it has already been written.
+    typedef.Output(out_file, defined_types, typemap)
+    self.assertEqual(out_file.getvalue(), 'typedef int INT;\n')
+    self.assertIn('INT', defined_types)
+    typedef2 = generator.Typedef('TYPE1', 'TYPE2')
+    typemap = {'TYPE1': generator.Structure('TYPE1', False)}
+    defined_types = set([])
+    out_file2 = StringIO.StringIO()
+    # Expect this to write first TYPE1 forward then TYPE2 typedef.
+    typedef2.Output(out_file2, defined_types, typemap)
+    output_re = r'struct TYPE1;\s+typedef TYPE1 TYPE2;\s+'
+    self.assertRegexpMatches(out_file2.getvalue(), output_re)
+    self.assertIn('TYPE2', defined_types)
+    out_file.close()
+    out_file2.close()
+
+  def testConstant(self):
+    """Test generation of constant definitions and type dependencies."""
+    constant = generator.Constant('INT', 'test', '1')
+    typemap = {'INT': generator.Structure('INT', False)}
+    defined_types = set([])
+    out_file = StringIO.StringIO()
+    constant.Output(out_file, defined_types, typemap)
+    output_re = r'struct INT;\s+const INT test = 1;\s+'
+    self.assertRegexpMatches(out_file.getvalue(), output_re)
+    out_file.close()
+
+  def testStructure(self):
+    """Test generation of structure declarations and field dependencies."""
+    struct = generator.Structure('STRUCT', False)
+    struct.AddField('int', 'i')
+    struct.AddDependency('DEPEND')
+    union = generator.Structure('UNION', True)
+    union.AddField('STRUCT', 'inner')
+    depend = generator.Structure('DEPEND', False)
+    defined_types = set(['int'])
+    out_file = StringIO.StringIO()
+    typemap = {'STRUCT': struct, 'DEPEND': depend}
+    # Only output |union|, this will test the dependency logic.
+    union.OutputForward(out_file, defined_types, typemap)
+    union.OutputForward(out_file, defined_types, typemap)
+    union.Output(out_file, defined_types, typemap)
+    output_re = r'union UNION;\s+struct DEPEND {\s+};\s+'
+    output_re += r'struct STRUCT {\s+int i;\s+};\s+'
+    output_re += r'union UNION {\s+STRUCT inner;\s+};\s+'
+    self.assertRegexpMatches(out_file.getvalue(), output_re)
+    for t in ('STRUCT', 'DEPEND', 'UNION'):
+      self.assertIn(t, defined_types)
+    out_file.close()
+
+  def testDefine(self):
+    """Test generation of preprocessor defines."""
+    define = generator.Define('name', 'value')
+    out_file = StringIO.StringIO()
+    define.Output(out_file)
+    output_re = r'#if !defined\(name\)\s+#define name value\s+#endif\s+'
+    self.assertRegexpMatches(out_file.getvalue(), output_re)
+    out_file.close()
+
+  def _MakeArg(self, arg_type, arg_name):
+    return {'type': arg_type,
+            'name': arg_name,
+            'command_code': None,
+            'description': None}
+
+  def testCommand(self):
+    """Test generation of command methods and callbacks."""
+    command = generator.Command('TPM2_Test')
+    command.request_args = [self._MakeArg('int', 'input')]
+    command.response_args = [self._MakeArg('BYTE', 'output[sizeof(TEST)]')]
+    out_file = StringIO.StringIO()
+    command.OutputDeclarations(out_file)
+    output_re = r'\s*typedef base::Callback<void\(\s*TPM_RC response_code,'
+    output_re += r'\s+BYTE output\[sizeof\(TEST\)\]\)> TestResponse;'
+    output_re += r'\s+void Test\(\s*int input,'
+    output_re += r'\s+const TestResponse& callback\s*\);\s+'
+    self.assertRegexpMatches(out_file.getvalue(), output_re)
+    out_file.close()
+
+
+class TestParsers(unittest.TestCase):
+  """Test parser classes."""
+
+  FAKE_TYPEDEF = '_BEGIN_TYPES\n_OLD_TYPE type1\n_NEW_TYPE type2\n_END\n'
+  FAKE_CONSTANT = ('_BEGIN_CONSTANTS\n_CONSTANTS (base_type) const_type\n'
+                   '_TYPE base_type\n_NAME const_name\n_VALUE const_value\n'
+                   '_END\n')
+  FAKE_STRUCTURE = ('_BEGIN_STRUCTURES\n_STRUCTURE struct_type\n'
+                    '_TYPE field_type\n'
+                    '_NAME field_name[sizeof(depend_type)]\n_END\n')
+  FAKE_DEFINE = '_BEGIN_DEFINES\n_NAME define_name\n_VALUE define_value\n_END'
+  FAKE_COMMAND = ('_BEGIN\n_INPUT_START TPM2_Test\n'
+                  '_TYPE UINT32\n_NAME commandSize\n'
+                  '_TYPE TPM_CC\n_NAME commandCode\n_COMMENT TPM_CC_Test\n'
+                  '_TYPE UINT16\n_NAME input\n'
+                  '_OUTPUT_START TPM2_Test\n_END\n')
+
+  def testStructureParserWithBadData(self):
+    """Test the structure parser with invalid data."""
+    input_data = 'bad_data'
+    in_file = StringIO.StringIO(input_data)
+    parser = generator.StructureParser(in_file)
+    types, constants, structs, defines, typemap = parser.Parse()
+    self.assertIsNotNone(types)
+    self.assertIsNotNone(constants)
+    self.assertIsNotNone(structs)
+    self.assertIsNotNone(defines)
+    self.assertIsNotNone(typemap)
+
+  def testStructureParser(self):
+    """Test the structure parser with valid data."""
+    input_data = (self.FAKE_TYPEDEF + self.FAKE_CONSTANT + self.FAKE_STRUCTURE +
+                  self.FAKE_DEFINE)
+    in_file = StringIO.StringIO(input_data)
+    parser = generator.StructureParser(in_file)
+    types, constants, structs, defines, typemap = parser.Parse()
+    # Be flexible on these counts because the parser may add special cases.
+    self.assertGreaterEqual(len(types), 2)
+    self.assertGreaterEqual(len(constants), 1)
+    self.assertGreaterEqual(len(structs), 1)
+    self.assertGreaterEqual(len(defines), 1)
+    self.assertGreaterEqual(len(typemap), 3)
+    self.assertEqual(types[0].old_type, 'type1')
+    self.assertEqual(types[0].new_type, 'type2')
+    self.assertEqual(types[1].old_type, 'base_type')
+    self.assertEqual(types[1].new_type, 'const_type')
+    self.assertEqual(constants[0].const_type, 'const_type')
+    self.assertEqual(constants[0].name, 'const_name')
+    self.assertEqual(constants[0].value, 'const_value')
+    self.assertEqual(structs[0].name, 'struct_type')
+    self.assertEqual(structs[0].is_union, False)
+    self.assertEqual(len(structs[0].fields), 1)
+    self.assertEqual(structs[0].fields[0][0], 'field_type')
+    self.assertEqual(structs[0].fields[0][1], 'field_name[sizeof(depend_type)]')
+    self.assertEqual(len(structs[0].depends_on), 1)
+    self.assertEqual(structs[0].depends_on[0], 'depend_type')
+    self.assertEqual(defines[0].name, 'define_name')
+    self.assertEqual(defines[0].value, 'define_value')
+
+  def testCommandParserWithBadData(self):
+    """Test the command parser with invalid data."""
+    input_data = 'bad_data'
+    in_file = StringIO.StringIO(input_data)
+    parser = generator.CommandParser(in_file)
+    commands = parser.Parse()
+    self.assertIsNotNone(commands)
+
+  def testCommandParser(self):
+    """Test the command parser with valid data."""
+    input_data = self.FAKE_COMMAND
+    in_file = StringIO.StringIO(input_data)
+    parser = generator.CommandParser(in_file)
+    commands = parser.Parse()
+    self.assertEqual(len(commands), 1)
+    self.assertEqual(commands[0].name, 'TPM2_Test')
+    self.assertEqual(commands[0].command_code, 'TPM_CC_Test')
+    # We expect the 'commandSize' and 'commandCode' args to be filtered out.
+    self.assertEqual(len(commands[0].request_args), 1)
+    self.assertEqual(commands[0].request_args[0]['type'], 'UINT16')
+    self.assertEqual(commands[0].request_args[0]['name'], 'input')
+    self.assertIsNotNone(commands[0].response_args)
+    self.assertFalse(commands[0].response_args)
+
+
+if __name__ == '__main__':
+  unittest.main()