1# Copyright 2014 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""A code generator for TPM 2.0 commands.
6
7The command generator takes as input a list of command objects generated by
8parsing the TCG specification and outputs valid C code to marshal command
9input and output structures, and also generates functions ParseHandleBuffer
10and CommandDispatcher defined by the TCG TPM2.0 Library Specification.
11
12"""
13
14from __future__ import print_function
15
16import re
17from subprocess import call
18
19from structure_generator import COPYRIGHT_HEADER
20from structure_generator import Field
21
22_HEADER_FILE_GUARD_HEADER = """
23#ifndef TPM2_%(name)s_FP_H_
24#define TPM2_%(name)s_FP_H_
25"""
26_HEADER_FILE_GUARD_FOOTER = """
27#endif  // TPM2_%(name)s_FP_H
28"""
29_HEADER_FILE_INCLUDES = """
30#include "tpm_generated.h"
31"""
32_IMPLEMENTATION_FILE_INCLUDES = """
33#include "MemoryLib_fp.h"
34#include "%(command_name)s_fp.h"
35"""
36_COMMAND_DISPATCHER_INCLUDES = '#include "%(command_name)s_fp.h"\n'
37_COMMAND_DISPATCHER_START = """
38#include "Implementation.h"
39#include "CommandDispatcher_fp.h"
40
41TPM_RC CommandDispatcher(
42    TPMI_ST_COMMAND_TAG tag,
43    TPM_CC command_code,
44    INT32 *request_parameter_buffer_size,
45    BYTE *request_parameter_buffer_start,
46    TPM_HANDLE request_handles[],
47    UINT32 *response_handle_buffer_size,
48    UINT32 *response_parameter_buffer_size) {
49  BYTE *request_parameter_buffer = request_parameter_buffer_start;
50  switch(command_code) {"""
51_COMMAND_DISPATCHER_CASE = """
52#ifdef %(command_code)s
53    case %(command_code)s:
54      return Exec_%(command_name)s(tag, &request_parameter_buffer,
55          request_parameter_buffer_size, request_handles,
56          response_handle_buffer_size, response_parameter_buffer_size);
57#endif"""
58_COMMAND_DISPATCHER_END = """
59    default:
60      return TPM_RC_COMMAND_CODE;
61  }
62}"""
63_HANDLE_PROCESS_START = """
64#include "tpm_generated.h"
65#include "HandleProcess_fp.h"
66#include "Implementation.h"
67#include "TPM_Types.h"
68
69TPM_RC ParseHandleBuffer(
70    TPM_CC command_code,
71    BYTE **request_handle_buffer_start,
72    INT32 *request_buffer_remaining_size,
73    TPM_HANDLE request_handles[],
74    UINT32 *num_request_handles) {
75  TPM_RC result = TPM_RC_SUCCESS;
76  *num_request_handles = 0;
77  switch(command_code) {
78"""
79_HANDLE_PROCESS_CASE_START = """
80#ifdef %(command_code)s
81    case %(command_code)s:"""
82_HANDLE_PROCESS_CASE_UNMARSHAL = """
83      result = %(handle_type)s_Unmarshal(
84          (%(handle_type)s*)&request_handles[*num_request_handles],
85          request_handle_buffer_start,
86          request_buffer_remaining_size);"""
87_HANDLE_PROCESS_CASE_UNMARSHAL_FLAG = """
88      result = %(handle_type)s_Unmarshal(
89          (%(handle_type)s*)&request_handles[*num_request_handles],
90          request_handle_buffer_start,
91          request_buffer_remaining_size,
92          %(flag_val)s);"""
93_HANDLE_PROCESS_CASE_CHECK = """
94      if (result != TPM_RC_SUCCESS) {
95        return result;
96      }
97      ++(*num_request_handles);"""
98_HANDLE_PROCESS_CASE_END = """
99      return TPM_RC_SUCCESS;
100#endif"""
101_HANDLE_PROCESS_END = """
102    default:
103      return TPM_RC_COMMAND_CODE;
104  }
105}"""
106_GET_COMMAND_CODE_STRING_HEADER = """
107#ifndef TPM2_GET_COMMAND_CODE_STRING_FP_H_
108#define TPM2_GET_COMMAND_CODE_STRING_FP_H_
109
110#include "TPM_Types.h"
111
112const char* GetCommandCodeString(TPM_CC command_code);
113
114#endif  // TPM2_GET_COMMAND_CODE_STRING_FP_H_"""
115_GET_COMMAND_CODE_STRING_START = """
116#include "GetCommandCodeString_fp.h"
117
118const char* GetCommandCodeString(TPM_CC command_code) {
119  switch(command_code) {"""
120_GET_COMMAND_CODE_STRING_CASE = """
121#ifdef TPM_CC_%(command_name)s
122  case TPM_CC_%(command_name)s:
123      return "%(command_name)s";
124#endif"""
125_GET_COMMAND_CODE_STRING_END = """
126    default:
127      return "Unknown command";
128  }
129}"""
130
131
132class Command(object):
133  """Represents a TPM command.
134
135  Attributes:
136    name: The command name (e.g. 'TPM2_Startup').
137    command_code: The name of the command code constant (e.g. TPM2_CC_Startup).
138    request_args: A list to hold command input arguments. Each element is a dict
139        and has these keys:
140            'type': The argument type.
141            'name': The argument name.
142            'command_code': The optional value of the command code constant.
143            'description': Optional descriptive text for the argument.
144            'has_conditional': String literal 'TRUE' or 'FALSE' indicating
145                whether 'type' is allowed to have a conditional value.
146    response_args: A list identical in form to request_args but to hold command
147        output arguments.
148  """
149
150  _HANDLE_RE = re.compile(r'TPMI_.H_.*')
151  _STRUCT_DECL_START = """
152typedef struct {"""
153  _STRUCT_DECL_FIELD = """
154  %(type)s %(name)s;"""
155  _STRUCT_DECL_END = """
156} %(command_name)s_%(direction)s;
157"""
158  _FUNCTION_DECL_IN_OUT = """
159// Executes %(command_name)s with request handles and parameters from
160// |in| and computes response handles and parameters to |out|.
161TPM_RC TPM2_%(command_name)s(
162    %(command_name)s_In *in,
163    %(command_name)s_Out *out);
164
165// Initializes handle fields in |target| from |request_handles|. Unmarshals
166// parameter fields in |target| from |buffer|.
167TPM_RC %(command_name)s_In_Unmarshal(
168    %(command_name)s_In *target,
169    TPM_HANDLE request_handles[],
170    BYTE **buffer,
171    INT32 *size);
172
173// Marshals response handles and parameters from |source| to |buffer|. Computes
174// and marshals the size of the parameter area (parameter_size) if |tag| ==
175// TPM_ST_SESSIONS. Returns size of (parameter area + handle area) in bytes.
176// Return value does not include parameter_size field.
177UINT16 %(command_name)s_Out_Marshal(
178    %(command_name)s_Out *source,
179    TPMI_ST_COMMAND_TAG tag,
180    BYTE **buffer,
181    INT32 *size);
182"""
183  _FUNCTION_DECL_IN = """
184// Executes %(command_name)s with request handles and parameters from |in|.
185TPM_RC TPM2_%(command_name)s(
186    %(command_name)s_In *in);
187
188// Initializes handle fields in |target| from |request_handles|. Unmarshals
189// parameter fields in |target| from |buffer|.
190TPM_RC %(command_name)s_In_Unmarshal(
191    %(command_name)s_In *target,
192    TPM_HANDLE request_handles[],
193    BYTE **buffer,
194    INT32 *size);
195"""
196  _FUNCTION_DECL_OUT = """
197// Executes %(command_name)s and computes response handles and parameters
198// to |out|.
199TPM_RC TPM2_%(command_name)s(
200    %(command_name)s_Out *out);
201
202// Marshals response handles and parameters from |source| to |buffer|. Computes
203// and marshals the size of the parameter area (parameter_size) if |tag| ==
204// TPM_ST_SESSIONS. Returns size of (parameter area + handle area) in bytes.
205// Does not include parameter_size field.
206UINT16 %(command_name)s_Out_Marshal(
207    %(command_name)s_Out *source,
208    TPMI_ST_COMMAND_TAG tag,
209    BYTE **buffer,
210    INT32 *size);
211"""
212  _EXEC_DECL = """
213// Unmarshals any request parameters starting at |request_parameter_buffer|.
214// Executes command. Marshals any response handles and parameters to the
215// global response buffer and computes |*response_handle_buffer_size| and
216// |*response_parameter_buffer_size|. If |tag| == TPM_ST_SESSIONS, marshals
217// parameter_size indicating the size of the parameter area. parameter_size
218// field is located between the handle area and parameter area.
219TPM_RC Exec_%(command_name)s(
220    TPMI_ST_COMMAND_TAG tag,
221    BYTE **request_parameter_buffer,
222    INT32 *request_parameter_buffer_size,
223    TPM_HANDLE request_handles[],
224    UINT32 *response_handle_buffer_size,
225    UINT32 *response_parameter_buffer_size);
226"""
227  _EXEC_COMMAND_IMPL_START = """
228TPM_RC Exec_%(command_name)s(
229    TPMI_ST_COMMAND_TAG tag,
230    BYTE **request_parameter_buffer,
231    INT32 *request_parameter_buffer_size,
232    TPM_HANDLE request_handles[],
233    UINT32 *response_handle_buffer_size,
234    UINT32 *response_parameter_buffer_size) {
235  TPM_RC result = TPM_RC_SUCCESS;"""
236  _EXEC_COMMAND_IMPL_IN_OUT = """
237  %(command_name)s_In in;
238  %(command_name)s_Out out;
239#ifdef %(command_code)s
240  BYTE *response_buffer;
241  INT32 response_buffer_size;
242  UINT16 bytes_marshalled;
243  UINT16 num_response_handles = %(num_response_handles)s;
244#endif
245  *response_handle_buffer_size = 0;
246  *response_parameter_buffer_size = 0;
247  // Unmarshal request parameters to input structure.
248  result = %(command_name)s_In_Unmarshal(&in, request_handles,
249      request_parameter_buffer, request_parameter_buffer_size);
250  if (result != TPM_RC_SUCCESS) {
251    return result;
252  }
253  // Execute command.
254  result = TPM2_%(command_name)s(&in, &out);
255  if (result != TPM_RC_SUCCESS) {
256    return result;
257  }
258  // Marshal output structure to global response buffer.
259#ifdef %(command_code)s
260  response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
261  response_buffer_size = MAX_RESPONSE_SIZE - 10;
262  bytes_marshalled = %(command_name)s_Out_Marshal(
263      &out, tag, &response_buffer, &response_buffer_size);
264  *response_handle_buffer_size = num_response_handles*sizeof(TPM_HANDLE);
265  *response_parameter_buffer_size =
266      bytes_marshalled - *response_handle_buffer_size;
267  return TPM_RC_SUCCESS;
268#endif
269  return TPM_RC_COMMAND_CODE;
270}
271"""
272  _EXEC_COMMAND_IMPL_IN = """
273  %(command_name)s_In in;
274#ifdef %(command_code)s
275  BYTE *response_buffer;
276  INT32 response_buffer_size;
277#endif
278  *response_handle_buffer_size = 0;
279  *response_parameter_buffer_size = 0;
280  // Unmarshal request parameters to input structure.
281  result = %(command_name)s_In_Unmarshal(&in, request_handles,
282      request_parameter_buffer, request_parameter_buffer_size);
283  if (result != TPM_RC_SUCCESS) {
284    return result;
285  }
286  // Execute command.
287  result = TPM2_%(command_name)s(&in);
288  if (result != TPM_RC_SUCCESS) {
289    return result;
290  }
291#ifdef %(command_code)s
292  response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
293  response_buffer_size = MAX_RESPONSE_SIZE - 10;
294  // Add parameter_size field, always equal to 0 here.
295  if (tag == TPM_ST_SESSIONS) {
296    UINT32_Marshal(response_parameter_buffer_size, &response_buffer,
297        &response_buffer_size);
298  }
299  return TPM_RC_SUCCESS;
300#endif
301  return TPM_RC_COMMAND_CODE;
302}
303"""
304  _EXEC_COMMAND_IMPL_OUT = """
305  %(command_name)s_Out out;
306#ifdef %(command_code)s
307  BYTE *response_buffer;
308  INT32 response_buffer_size;
309  UINT16 bytes_marshalled;
310  UINT16 num_response_handles = %(num_response_handles)s;
311#endif
312  *response_handle_buffer_size = 0;
313  *response_parameter_buffer_size = 0;
314  // Execute command.
315  result = TPM2_%(command_name)s(&out);
316  if (result != TPM_RC_SUCCESS) {
317    return result;
318  }
319  // Marshal output structure containing response handles and parameters to
320  // response buffer.
321#ifdef %(command_code)s
322  response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
323  response_buffer_size = MAX_RESPONSE_SIZE - 10;
324  bytes_marshalled = %(command_name)s_Out_Marshal(
325      &out, tag, &response_buffer, &response_buffer_size);
326  *response_handle_buffer_size = num_response_handles*sizeof(TPM_HANDLE);
327  *response_parameter_buffer_size =
328      bytes_marshalled - *response_handle_buffer_size;
329  return TPM_RC_SUCCESS;
330#endif
331  return TPM_RC_COMMAND_CODE;
332}
333"""
334  _UNMARSHAL_COMMAND_START = """
335TPM_RC %(command_name)s_In_Unmarshal(
336    %(command_name)s_In *target,
337    TPM_HANDLE request_handles[],
338    BYTE **buffer,
339    INT32 *size) {
340  TPM_RC result = TPM_RC_SUCCESS;"""
341  _MARSHAL_COMMAND_START = """
342UINT16 %(command_name)s_Out_Marshal(
343    %(command_name)s_Out *source,
344    TPMI_ST_COMMAND_TAG tag,
345    BYTE **buffer,
346    INT32 *size) {
347  UINT16 total_size = 0;
348  UINT32 parameter_size = 0;
349  BYTE *parameter_size_location;
350  INT32 parameter_size_size = sizeof(UINT32);
351  UINT32 num_response_handles = %(num_response_handles)s;"""
352  _UNMARSHAL_END = """
353  if ((result == TPM_RC_SUCCESS) && *size) {
354    result = TPM_RC_SIZE;
355  }
356  return result;
357}
358"""
359  _MARSHAL_END = """
360  // Compute actual parameter_size. Don't add result to total_size.
361  if (tag == TPM_ST_SESSIONS) {
362    parameter_size = total_size - num_response_handles*sizeof(TPM_HANDLE);
363    UINT32_Marshal(
364        &parameter_size, &parameter_size_location, &parameter_size_size);
365  }
366  return total_size;
367}
368"""
369  _SET_COMMAND_HANDLE = """
370  target->%(field_name)s = request_handles[%(num)s];"""
371  _PARAMETERSIZE_CHECK = """
372  // Add parameter_size=0 to indicate size of the parameter area. Will be
373  // replaced later by computed parameter_size.
374  if (tag == TPM_ST_SESSIONS) {
375    parameter_size_location = *buffer;
376    // Don't add to total_size, but increment *buffer and decrement *size.
377    UINT32_Marshal(&parameter_size, buffer, size);
378  }"""
379
380  def __init__(self, name):
381    """Initializes a Command instance.
382
383    Initially the request_args and response_args attributes are not set.
384
385    Args:
386      name: The command name (e.g. 'TPM2_Startup').
387    """
388    self.name = name
389    self.request_args = None
390    self.response_args = None
391    if name.startswith('TPM2_'):
392      self.command_code = name.replace('TPM2_', 'TPM_CC_')
393    else:
394      self.command_code = ''
395
396  def __str__(self):
397    s = ['%s:' % self.name,]
398    if self.request_args:
399      s.append(' req:')
400      for r in self.request_args:
401        s.append('  %s: %s' % (r['type'], r['name']))
402    if self.response_args:
403      s.append(' resp:')
404      for r in self.response_args:
405        s.append('  %s: %s' % (r['type'], r['name']))
406    s.append('')
407    return '\n'.join(s)
408
409  def OutputMarshalFunction(self, out_file, typemap):
410    """Generates a marshal function for the command output structure.
411
412    Args:
413      out_file: File to be written to opened by the caller.
414      typemap: A dict mapping type names to the corresponding object.
415          Generated by structure_generator.
416    """
417    if not self.response_args:
418      return
419    # Categorize arguments as either handles or parameters.
420    handles, parameters = self._SplitArgs(self.response_args)
421    out_file.write(self._MARSHAL_COMMAND_START % {
422        'command_name': self.MethodName(),
423        'num_response_handles': self._GetNumberOfResponseHandles()})
424    if handles:
425      out_file.write('\n  // Marshal response handles.')
426    for handle in handles:
427      typemap[handle['type']].OutputMarshalCall(
428          out_file, Field(handle['type'],
429                          handle['name'],
430                          conditional_value=handle['has_conditional']))
431    out_file.write(self._PARAMETERSIZE_CHECK)
432    if parameters:
433      out_file.write('\n  // Marshal response parameters.')
434    for parameter in parameters:
435      typemap[parameter['type']].OutputMarshalCall(
436          out_file, Field(parameter['type'], parameter['name'],
437                          conditional_value=parameter['has_conditional']))
438    out_file.write(self._MARSHAL_END)
439
440  def OutputUnmarshalFunction(self, out_file, typemap):
441    """Generates a unmarshal function for the command input structure.
442
443    Args:
444      out_file: File to be written to opened by the caller.
445      typemap: A dict mapping type names to the corresponding object.
446          Generated by structure_generator.
447    """
448    if not self.request_args:
449      return
450    # Categorize arguments as either handles or parameters.
451    handles, parameters = self._SplitArgs(self.request_args)
452    out_file.write(self._UNMARSHAL_COMMAND_START % {
453        'command_name': self.MethodName()})
454    if handles:
455      out_file.write('\n  // Get request handles from request_handles array.')
456    for index, handle in enumerate(handles):
457      out_file.write(self._SET_COMMAND_HANDLE % {'field_name': handle['name'],
458                                                 'num': index})
459    if parameters:
460      out_file.write('\n  // Unmarshal request parameters.')
461    for parameter in parameters:
462      typemap[parameter['type']].OutputUnmarshalCall(
463          out_file, Field(parameter['type'],
464                          parameter['name'],
465                          conditional_value=parameter['has_conditional']))
466    out_file.write(self._UNMARSHAL_END)
467
468  def OutputExecFunction(self, out_file):
469    """Generates an exec function for the command.
470
471    Args:
472      out_file: File to be written to opened by the caller.
473    """
474    out_file.write(
475        self._EXEC_COMMAND_IMPL_START % {'command_name': self.MethodName()})
476    if self.request_args and self.response_args:
477      out_file.write(self._EXEC_COMMAND_IMPL_IN_OUT % {
478          'command_name': self.MethodName(),
479          'command_code': self.command_code,
480          'num_response_handles': self._GetNumberOfResponseHandles()})
481    elif self.request_args:
482      out_file.write(self._EXEC_COMMAND_IMPL_IN % {
483          'command_name': self.MethodName(),
484          'command_code': self.command_code})
485    elif self.response_args:
486      out_file.write(self._EXEC_COMMAND_IMPL_OUT % {
487          'command_name': self.MethodName(),
488          'command_code': self.command_code,
489          'num_response_handles': self._GetNumberOfResponseHandles()})
490
491  def OutputDecl(self, out_file):
492    """Generates a TPM object declaration."""
493    if self.request_args:
494      out_file.write(self._STRUCT_DECL_START)
495      for arg in self.request_args:
496        out_file.write(self._STRUCT_DECL_FIELD % {'type': arg['type'],
497                                                  'name': arg['name']})
498      out_file.write(self._STRUCT_DECL_END % {'command_name': self.MethodName(),
499                                              'direction': 'In'})
500    if self.response_args:
501      out_file.write(self._STRUCT_DECL_START)
502      for arg in self.response_args:
503        out_file.write(self._STRUCT_DECL_FIELD % {'type': arg['type'],
504                                                  'name': arg['name']})
505      out_file.write(self._STRUCT_DECL_END % {'command_name': self.MethodName(),
506                                              'direction': 'Out'})
507    if len(self.response_args) and len(self.request_args):
508      out_file.write(
509          self._FUNCTION_DECL_IN_OUT % {'command_name': self.MethodName()})
510    elif self.response_args:
511      out_file.write(
512          self._FUNCTION_DECL_OUT % {'command_name': self.MethodName()})
513    elif self.request_args:
514      out_file.write(
515          self._FUNCTION_DECL_IN % {'command_name': self.MethodName()})
516    out_file.write(self._EXEC_DECL % {'command_name': self.MethodName()})
517
518  def _GetNumberOfRequestHandles(self):
519    """Returns the number of input handles for this command."""
520    return len(self._SplitArgs(self.request_args)[0])
521
522  def _GetNumberOfResponseHandles(self):
523    """Returns the number of output handles for this command."""
524    return len(self._SplitArgs(self.response_args)[0])
525
526  def MethodName(self):
527    """Creates an appropriate generated method name for the command.
528
529    We use the command name without the TPM2_ prefix.
530
531    Returns:
532      The method name.
533    """
534    if not self.name.startswith('TPM2_'):
535      return self.name
536    return self.name[5:]
537
538  def GetRequestHandles(self):
539    """Returns a list of input handles for this command."""
540    return self._SplitArgs(self.request_args)[0]
541
542  def _SplitArgs(self, args):
543    """Splits a list of args into handles and parameters."""
544    always_params = {
545        'TPM_CC_FlushContext': 'TPMI_DH_CONTEXT',
546        'TPM_CC_Hash': 'TPMI_RH_HIERARCHY',
547        'TPM_CC_LoadExternal': 'TPMI_RH_HIERARCHY',
548        'TPM_CC_SequenceComplete': 'TPMI_RH_HIERARCHY',
549    }
550    handles = []
551    parameters = []
552    always_handle = set(['TPM_HANDLE'])
553    # Handle types that appear as command parameters.
554    always_parameter = set(['TPMI_RH_ENABLES', 'TPMI_DH_PERSISTENT'])
555    if self.command_code in always_params:
556      always_parameter.add(always_params[self.command_code])
557    for arg in args:
558      if (arg['type'] in always_handle or
559          (self._HANDLE_RE.search(arg['type']) and
560           arg['type'] not in always_parameter)):
561        handles.append(arg)
562      else:
563        parameters.append(arg)
564    return handles, parameters
565
566
567def _OutputCommandDispatcher(commands):
568  """Generates implementation file for CommandDispatcher function.
569
570  Args:
571    commands: A list of Command objects.
572  """
573  with open('CommandDispatcher.c', 'w') as out_file:
574    out_file.write(COPYRIGHT_HEADER)
575    for command in commands:
576      out_file.write(_COMMAND_DISPATCHER_INCLUDES %
577                     {'command_name': command.MethodName()})
578    out_file.write(_COMMAND_DISPATCHER_START)
579    for command in commands:
580      command_code = 'TPM_CC_' + command.MethodName()
581      out_file.write(_COMMAND_DISPATCHER_CASE %
582                     {'command_code': command_code,
583                      'command_name': command.MethodName()})
584    out_file.write(_COMMAND_DISPATCHER_END)
585  call(['clang-format', '-i', '-style=Chromium', 'CommandDispatcher.c'])
586
587
588def _OutputHandleProcess(commands, typemap):
589  """Generates implementation file for ParseHandleBuffer function.
590
591  Args:
592    commands: A list of Command objects.
593    typemap: A dict mapping type names to the corresponding object.
594        Generated by structure_generator.
595  """
596  with open('HandleProcess.c', 'w') as out_file:
597    out_file.write(COPYRIGHT_HEADER)
598    out_file.write(_HANDLE_PROCESS_START)
599    for command in commands:
600      command_code = 'TPM_CC_' + command.MethodName()
601      out_file.write(_HANDLE_PROCESS_CASE_START %
602                     {'command_code': command_code})
603      for handle in command.GetRequestHandles():
604        if typemap[handle['type']].HasConditional():
605          out_file.write(_HANDLE_PROCESS_CASE_UNMARSHAL_FLAG %
606                         {'handle_type': handle['type'],
607                          'flag_val': handle['has_conditional']})
608        else:
609          out_file.write(_HANDLE_PROCESS_CASE_UNMARSHAL %
610                         {'handle_type': handle['type']})
611        out_file.write(_HANDLE_PROCESS_CASE_CHECK)
612      out_file.write(_HANDLE_PROCESS_CASE_END)
613    out_file.write(_HANDLE_PROCESS_END)
614  call(['clang-format', '-i', '-style=Chromium', 'HandleProcess.c'])
615
616
617def _OutputGetCommandCodeString(commands):
618  """Generates header and implementation files for GetCommandCodeString.
619
620  Args:
621    commands: A list of Command objects.
622  """
623  with open('GetCommandCodeString_fp.h', 'w') as out_file:
624    out_file.write(COPYRIGHT_HEADER)
625    out_file.write(_GET_COMMAND_CODE_STRING_HEADER)
626  call(['clang-format', '-i', '-style=Chromium', 'GetCommandCodeString_fp.h'])
627  with open('GetCommandCodeString.c', 'w') as out_file:
628    out_file.write(COPYRIGHT_HEADER)
629    out_file.write(_GET_COMMAND_CODE_STRING_START)
630    for command in commands:
631      out_file.write(_GET_COMMAND_CODE_STRING_CASE %
632                     {'command_name': command.MethodName()})
633    out_file.write(_GET_COMMAND_CODE_STRING_END)
634  call(['clang-format', '-i', '-style=Chromium', 'GetCommandCodeString.c'])
635
636
637def GenerateHeader(commands):
638  """Generates a header file with declarations for all given generator objects.
639
640  Args:
641    commands: A list of Command objects.
642  """
643  for command in commands:
644    command_header_file = command.MethodName()+'_fp.h'
645    with open(command_header_file, 'w') as out_file:
646      out_file.write(COPYRIGHT_HEADER)
647      out_file.write(
648          _HEADER_FILE_GUARD_HEADER % {'name': command.MethodName().upper()})
649      out_file.write(_HEADER_FILE_INCLUDES)
650      command.OutputDecl(out_file)
651      out_file.write(
652          _HEADER_FILE_GUARD_FOOTER % {'name': command.MethodName().upper()})
653    call(['clang-format', '-i', '-style=Chromium', command_header_file])
654
655
656def GenerateImplementation(commands, typemap):
657  """Generates implementation code for each command.
658
659  Args:
660    commands: A list of Command objects.
661    typemap: A dict mapping type names to the corresponding object.
662        Generated by structure_generator.
663  """
664  for command in commands:
665    marshal_command_file = 'Marshal_'+command.MethodName()+'.c'
666    with open(marshal_command_file, 'w') as out_file:
667      out_file.write(COPYRIGHT_HEADER)
668      out_file.write(_IMPLEMENTATION_FILE_INCLUDES %
669                     {'command_name': command.MethodName()})
670      command.OutputMarshalFunction(out_file, typemap)
671      command.OutputUnmarshalFunction(out_file, typemap)
672      command.OutputExecFunction(out_file)
673    call(['clang-format', '-i', '-style=Chromium', marshal_command_file])
674  _OutputHandleProcess(commands, typemap)
675  _OutputCommandDispatcher(commands)
676  _OutputGetCommandCodeString(commands)
677