15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" Generator for C style prototypes and definitions """
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import glob
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_log import ErrOut, InfoOut, WarnOut
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_node import IDLNode
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_ast import IDLAst
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_option import GetOption, Option, ParseOptions
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_parser import ParseFiles
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Option('cgen_debug', 'Debug generate.')
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CGenError(Exception):
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, msg):
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.value = msg
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return repr(self.value)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CommentLines(lines, tabs=0):
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Generate a C style comment block by prepending the block with '<tab>/*'
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # and adding a '<tab> *' per line.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tab = '  ' * tabs
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out = '%s/*' % tab + ('\n%s *' % tab).join(lines)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Add a terminating ' */' unless the last line is blank which would mean it
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # already has ' *'
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not lines[-1]:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out += '/\n'
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out += ' */\n'
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return out
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def Comment(node, prefix=None, tabs=0):
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Generate a comment block from the provided Comment node.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  comment = node.GetName()
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lines = comment.split('\n')
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # If an option prefix is provided, then prepend that to the comment
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # for this node.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if prefix:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prefix_lines = prefix.split('\n')
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If both the prefix and comment start with a blank line ('*') remove
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # the extra one.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if prefix_lines[0] == '*' and lines[0] == '*':
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines = prefix_lines + lines[1:]
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines = prefix_lines + lines;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CommentLines(lines, tabs)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetNodeComments(node, tabs=0):
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Generate a comment block joining all comment nodes which are children of
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # the provided node.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  comment_txt = ''
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for doc in node.GetListOf('Comment'):
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    comment_txt += Comment(doc, tabs=tabs)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return comment_txt
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CGen(object):
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TypeMap
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TypeMap modifies how an object is stored or passed, for example pointers
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # are passed as 'const' if they are 'in' parameters, and structures are
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # preceeded by the keyword 'struct' as well as using a pointer.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TypeMap = {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'Array': {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': 'const %s',
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s',
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s*',
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s',
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'return': '%s',
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'ref': '%s*'
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'Callspec': {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': '%s',
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s',
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s',
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s',
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': '%s'
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'Enum': {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': '%s',
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s*',
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s*',
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s',
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': '%s'
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'Interface': {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': 'const %s*',
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s*',
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s**',
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': '%s*',
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s*'
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'Struct': {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': 'const %s*',
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s*',
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s*',
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': ' %s*',
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'store': '%s',
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'ref': '%s*'
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'blob_t': {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': 'const %s',
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s',
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s',
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': '%s',
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s'
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'mem_t': {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': 'const %s',
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s',
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s',
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': '%s',
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s'
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    'mem_ptr_t': {
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      'in': 'const %s',
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      'inout': '%s',
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      'out': '%s',
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      'return': '%s',
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      'store': '%s'
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    },
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'str_t': {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': 'const %s',
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s',
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s',
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': 'const %s',
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s'
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'cstr_t': {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': '%s',
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s*',
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s*',
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': '%s',
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s'
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'TypeValue': {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'in': '%s',
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'constptr_in': 'const %s*',  # So we can use const* for PP_Var sometimes.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'inout': '%s*',
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'out': '%s*',
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'return': '%s',
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'store': '%s'
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # RemapName
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # A diction array of PPAPI types that are converted to language specific
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # types before being returned by by the C generator
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemapName = {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'blob_t': 'void**',
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'float_t': 'float',
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'double_t': 'double',
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'handle_t': 'int',
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'mem_t': 'void*',
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  'mem_ptr_t': 'void**',
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'str_t': 'char*',
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'cstr_t': 'const char*',
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  'interface_t' : 'const void*'
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  # Tell how to handle pointers to GL types.
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for gltype in ['GLbitfield', 'GLboolean', 'GLbyte', 'GLclampf',
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 'GLclampx', 'GLenum', 'GLfixed', 'GLfloat', 'GLint',
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 'GLintptr', 'GLshort', 'GLsizei', 'GLsizeiptr',
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 'GLubyte', 'GLuint', 'GLushort']:
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ptrtype = gltype + '_ptr_t'
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    TypeMap[ptrtype] = {
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'in': 'const %s',
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'inout': '%s',
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'out': '%s',
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'return': 'const %s',
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'store': '%s'
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RemapName[ptrtype] = '%s*' % gltype
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self):
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.dbg_depth = 0
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Debug Logging functions
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Log(self, txt):
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not GetOption('cgen_debug'): return
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tabs = '  ' * self.dbg_depth
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print '%s%s' % (tabs, txt)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def LogEnter(self, txt):
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if txt: self.Log(txt)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.dbg_depth += 1
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def LogExit(self, txt):
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.dbg_depth -= 1
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if txt: self.Log(txt)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetDefine(self, name, value):
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = '#define %s %s' % (name, value)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if len(out) > 80:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = '#define %s \\\n    %s' % (name, value)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%s\n' % out
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Interface strings
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetMacroHelper(self, node):
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    macro = node.GetProperty('macro')
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if macro: return macro
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = node.GetName()
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = name.upper()
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "%s_INTERFACE" % name
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetInterfaceMacro(self, node, version = None):
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = self.GetMacroHelper(node)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if version is None:
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return name
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%s_%s' % (name, str(version).replace('.', '_'))
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetInterfaceString(self, node, version = None):
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If an interface name is specified, use that
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = node.GetProperty('iname')
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not name:
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Otherwise, the interface name is the object's name
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # With '_Dev' replaced by '(Dev)' if it's a Dev interface.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = node.GetName()
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if name.endswith('_Dev'):
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name = '%s(Dev)' % name[:-4]
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if version is None:
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return name
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "%s;%s" % (name, version)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Return the array specification of the object.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetArraySpec(self, node):
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(node.cls == 'Array')
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fixed = node.GetProperty('FIXED')
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if fixed:
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return '[%s]' % fixed
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return '[]'
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # GetTypeName
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # For any valid 'typed' object such as Member or Typedef
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # the typenode object contains the typename
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # For a given node return the type name by passing mode.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetTypeName(self, node, release, prefix=''):
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('GetTypeName of %s rel=%s' % (node, release))
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # For Members, Params, and Typedefs get the type it refers to otherwise
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # the node in question is it's own type (struct, union etc...)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('Member', 'Param', 'Typedef'):
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typeref = node.GetType(release)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typeref = node
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if typeref is None:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.Error('No type at release %s.' % release)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise CGenError('No type for %s' % node)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If the type is a (BuiltIn) Type then return it's name
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # remapping as needed
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if typeref.IsA('Type'):
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = CGen.RemapName.get(typeref.GetName(), None)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if name is None: name = typeref.GetName()
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = '%s%s' % (prefix, name)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # For Interfaces, use the name + version
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif typeref.IsA('Interface'):
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rel = typeref.first_release[release]
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = 'struct %s%s' % (prefix, self.GetStructName(typeref, rel, True))
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # For structures, preceed with 'struct' or 'union' as appropriate
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif typeref.IsA('Struct'):
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if typeref.GetProperty('union'):
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name = 'union %s%s' % (prefix, typeref.GetName())
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name = 'struct %s%s' % (prefix, typeref.GetName())
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If it's an enum, or typedef then return the Enum's name
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif typeref.IsA('Enum', 'Typedef'):
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if not typeref.LastRelease(release):
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        first = node.first_release[release]
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        ver = '_' + node.GetVersion(first).replace('.','_')
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      else:
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        ver = ''
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # The enum may have skipped having a typedef, we need prefix with 'enum'.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if typeref.GetProperty('notypedef'):
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        name = 'enum %s%s%s' % (prefix, typeref.GetName(), ver)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        name = '%s%s%s' % (prefix, typeref.GetName(), ver)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise RuntimeError('Getting name of non-type %s.' % node)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('GetTypeName %s is %s' % (node, name))
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return name
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # GetRootType
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # For a given node return basic type of that object.  This is
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # either a 'Type', 'Callspec', or 'Array'
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetRootTypeMode(self, node, release, mode):
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('GetRootType of %s' % node)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If it has an array spec, then treat it as an array regardless of type
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.GetOneOf('Array'):
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rootType = 'Array'
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Or if it has a callspec, treat it as a function
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif node.GetOneOf('Callspec'):
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rootType, mode = self.GetRootTypeMode(node.GetType(release), release,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            'return')
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If it's a plain typedef, try that object's root type
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif node.IsA('Member', 'Param', 'Typedef'):
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rootType, mode = self.GetRootTypeMode(node.GetType(release),
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            release, mode)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If it's an Enum, then it's normal passing rules
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif node.IsA('Enum'):
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rootType = node.cls
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If it's an Interface or Struct, we may be passing by value
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif node.IsA('Interface', 'Struct'):
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if mode == 'return':
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if node.GetProperty('returnByValue'):
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rootType = 'TypeValue'
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rootType = node.cls
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if node.GetProperty('passByValue'):
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rootType = 'TypeValue'
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rootType = node.cls
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If it's an Basic Type, check if it's a special type
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif node.IsA('Type'):
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if node.GetName() in CGen.TypeMap:
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rootType = node.GetName()
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rootType = 'TypeValue'
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise RuntimeError('Getting root type of non-type %s.' % node)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('RootType is "%s"' % rootType)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rootType, mode
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetTypeByMode(self, node, release, mode):
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('GetTypeByMode of %s mode=%s release=%s' %
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (node, mode, release))
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = self.GetTypeName(node, release)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ntype, mode = self.GetRootTypeMode(node, release, mode)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = CGen.TypeMap[ntype][mode] % name
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('GetTypeByMode %s = %s' % (node, out))
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Get the passing mode of the object (in, out, inout).
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetParamMode(self, node):
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.Log('GetParamMode for %s' % node)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.GetProperty('in'): return 'in'
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.GetProperty('out'): return 'out'
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.GetProperty('inout'): return 'inout'
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if node.GetProperty('constptr_in'): return 'constptr_in'
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 'return'
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # GetComponents
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Returns the signature components of an object as a tuple of
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # (rtype, name, arrays, callspec) where:
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #   rtype - The store or return type of the object.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #   name - The name of the object.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #   arrays - A list of array dimensions as [] or [<fixed_num>].
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #   args -  None if not a function, otherwise a list of parameters.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetComponents(self, node, release, mode):
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('GetComponents mode %s for %s %s' % (mode, node, release))
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate passing type by modifying root type
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rtype = self.GetTypeByMode(node, release, mode)
40403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    # If this is an array output, change it from type* foo[] to type** foo.
40503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    # type* foo[] means an array of pointers to type, which is confusing.
40603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    arrayspec = [self.GetArraySpec(array) for array in node.GetListOf('Array')]
40703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if mode == 'out' and len(arrayspec) == 1 and arrayspec[0] == '[]':
40803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      rtype += '*'
40903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      del arrayspec[0]
41003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('Enum', 'Interface', 'Struct'):
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rname = node.GetName()
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rname = node.GetType(release).GetName()
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if rname in CGen.RemapName:
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rname = CGen.RemapName[rname]
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if '%' in rtype:
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rtype = rtype % rname
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = node.GetName()
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callnode = node.GetOneOf('Callspec')
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if callnode:
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callspec = []
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for param in callnode.GetListOf('Param'):
425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if not param.IsRelease(release):
426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          continue
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mode = self.GetParamMode(param)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ptype, pname, parray, pspec = self.GetComponents(param, release, mode)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callspec.append((ptype, pname, parray, pspec))
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callspec = None
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('GetComponents: %s, %s, %s, %s' %
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (rtype, name, arrayspec, callspec))
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (rtype, name, arrayspec, callspec)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Compose(self, rtype, name, arrayspec, callspec, prefix, func_as_ptr,
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              include_name, unsized_as_ptr):
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('Compose: %s %s' % (rtype, name))
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arrayspec = ''.join(arrayspec)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Switch unsized array to a ptr. NOTE: Only last element can be unsized.
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if unsized_as_ptr and arrayspec[-2:] == '[]':
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prefix +=  '*'
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      arrayspec=arrayspec[:-2]
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not include_name:
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = prefix + arrayspec
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name = prefix + name + arrayspec
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if callspec is None:
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = '%s %s' % (rtype, name)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params = []
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for ptype, pname, parray, pspec in callspec:
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        params.append(self.Compose(ptype, pname, parray, pspec, '', True,
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   include_name=True,
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   unsized_as_ptr=unsized_as_ptr))
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if func_as_ptr:
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        name = '(*%s)' % name
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if not params:
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        params = ['void']
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = '%s %s(%s)' % (rtype, name, ', '.join(params))
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('Exit Compose: %s' % out)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # GetSignature
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Returns the 'C' style signature of the object
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #  prefix - A prefix for the object's name
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #  func_as_ptr - Formats a function as a function pointer
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #  include_name - If true, include member name in the signature.
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  #                 If false, leave it out. In any case, prefix is always
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  #                 included.
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  #  include_version - if True, include version in the member name
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetSignature(self, node, release, mode, prefix='', func_as_ptr=True,
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   include_name=True, include_version=False):
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('GetSignature %s %s as func=%s' %
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (node, mode, func_as_ptr))
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rtype, name, arrayspec, callspec = self.GetComponents(node, release, mode)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if include_version:
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      name = self.GetStructName(node, release, True)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # If not a callspec (such as a struct) use a ptr instead of []
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsized_as_ptr = not callspec
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = self.Compose(rtype, name, arrayspec, callspec, prefix,
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       func_as_ptr, include_name, unsized_as_ptr)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('Exit GetSignature: %s' % out)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Define a Typedef.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def DefineTypedef(self, node, releases, prefix='', comment=False):
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __pychecker__ = 'unusednames=comment'
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    build_list = node.GetUniqueReleases(releases)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    out = 'typedef %s;\n' % self.GetSignature(node, build_list[-1], 'return',
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                              prefix, True,
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                              include_version=False)
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    # Version mangle any other versions
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for index, rel in enumerate(build_list[:-1]):
506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      out += '\n'
507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      out += 'typedef %s;\n' % self.GetSignature(node, rel, 'return',
508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 prefix, True,
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 include_version=True)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.Log('DefineTypedef: %s' % out)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Define an Enum.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def DefineEnum(self, node, releases, prefix='', comment=False):
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __pychecker__ = 'unusednames=comment,releases'
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('DefineEnum %s' % node)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = '%s%s' % (prefix, node.GetName())
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notypedef = node.GetProperty('notypedef')
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unnamed = node.GetProperty('unnamed')
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if unnamed:
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = 'enum {'
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif notypedef:
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = 'enum %s {' % name
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = 'typedef enum {'
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enumlist = []
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for child in node.GetListOf('EnumItem'):
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value = child.GetProperty('VALUE')
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      comment_txt = GetNodeComments(child, tabs=1)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if value:
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item_txt = '%s%s = %s' % (prefix, child.GetName(), value)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item_txt = '%s%s' % (prefix, child.GetName())
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enumlist.append('%s  %s' % (comment_txt, item_txt))
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('Exit DefineEnum')
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if unnamed or notypedef:
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = '%s\n%s\n};\n' % (out, ',\n'.join(enumlist))
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = '%s\n%s\n} %s;\n' % (out, ',\n'.join(enumlist), name)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def DefineMember(self, node, releases, prefix='', comment=False):
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __pychecker__ = 'unusednames=prefix,comment'
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    release = releases[0]
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('DefineMember %s' % node)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if node.GetProperty('ref'):
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out = '%s;' % self.GetSignature(node, release, 'ref', '', True)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else:
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out = '%s;' % self.GetSignature(node, release, 'store', '', True)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('Exit DefineMember')
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetStructName(self, node, release, include_version=False):
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suffix = ''
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if include_version:
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ver_num = node.GetVersion(release)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      suffix = ('_%s' % ver_num).replace('.', '_')
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return node.GetName() + suffix
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def DefineStructInternals(self, node, release,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            include_version=False, comment=True):
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    channel = node.GetProperty('FILE').release_map.GetChannel(release)
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if channel == 'dev':
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      channel_comment = ' /* dev */'
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else:
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      channel_comment = ''
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = ''
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.GetProperty('union'):
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      out += 'union %s {%s\n' % (
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          self.GetStructName(node, release, include_version), channel_comment)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      out += 'struct %s {%s\n' % (
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          self.GetStructName(node, release, include_version), channel_comment)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    channel = node.GetProperty('FILE').release_map.GetChannel(release)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate Member Functions
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    members = []
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for child in node.GetListOf('Member'):
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if channel == 'stable' and child.NodeIsDevOnly():
5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        continue
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      member = self.Define(child, [release], tabs=1, comment=comment)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not member:
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      members.append(member)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out += '%s\n};\n' % '\n'.join(members)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def DefineUnversionedInterface(self, node, rel):
5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    out = '\n'
5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if node.GetProperty('force_struct_namespace'):
5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      # Duplicate the definition to put it in struct namespace. This
5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      # attribute is only for legacy APIs like OpenGLES2 and new APIs
5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      # must not use this. See http://crbug.com/411799
5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      out += self.DefineStructInternals(node, rel,
5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        include_version=False, comment=True)
5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else:
6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      # Define an unversioned typedef for the most recent version
6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      out += 'typedef struct %s %s;\n' % (
6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        self.GetStructName(node, rel, include_version=True),
6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        self.GetStructName(node, rel, include_version=False))
6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return out
6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def DefineStruct(self, node, releases, prefix='', comment=False):
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __pychecker__ = 'unusednames=comment,prefix'
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('DefineStruct %s' % node)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = ''
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    build_list = node.GetUniqueReleases(releases)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    newest_stable = None
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    newest_dev = None
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for rel in build_list:
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      channel = node.GetProperty('FILE').release_map.GetChannel(rel)
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if channel == 'stable':
6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        newest_stable = rel
6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if channel == 'dev':
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        newest_dev = rel
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    last_rel = build_list[-1]
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # TODO(noelallen) : Bug 157017 finish multiversion support
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('Struct'):
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if len(build_list) != 1:
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        node.Error('Can not support multiple versions of node.')
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert len(build_list) == 1
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      # Build the most recent one versioned, with comments
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      out = self.DefineStructInternals(node, last_rel,
630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       include_version=False, comment=True)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if node.IsA('Interface'):
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Build the most recent one versioned, with comments
6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      out = self.DefineStructInternals(node, last_rel,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       include_version=True, comment=True)
6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if last_rel == newest_stable:
6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        out += self.DefineUnversionedInterface(node, last_rel)
6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
639a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      # Build the rest without comments and with the version number appended
640a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      for rel in build_list[0:-1]:
6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        channel = node.GetProperty('FILE').release_map.GetChannel(rel)
6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # Skip dev channel interface versions that are
6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        #   Not the newest version, and
6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        #   Don't have an equivalent stable version.
6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if channel == 'dev' and rel != newest_dev:
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          if not node.DevInterfaceMatchesStable(rel):
6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            continue
648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        out += '\n' + self.DefineStructInternals(node, rel,
649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                 include_version=True,
650a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                 comment=False)
6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if rel == newest_stable:
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          out += self.DefineUnversionedInterface(node, rel)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('Exit DefineStruct')
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return out
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Copyright and Comment
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Generate a comment or copyright block
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def Copyright(self, node, cpp_style=False):
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = node.GetName().split('\n')
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if cpp_style:
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return '//' + '\n//'.join(filter(lambda f: f != '', lines)) + '\n'
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return CommentLines(lines)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def Indent(self, data, tabs=0):
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Handles indentation and 80-column line wrapping."""
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tab = '  ' * tabs
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    lines = []
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for line in data.split('\n'):
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # Add indentation
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line = tab + line
67758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      space_break = line.rfind(' ', 0, 80)
678a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      if len(line) <= 80 or 'http://' in line:
67958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        # Ignore normal line and URLs permitted by the style guide.
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        lines.append(line.rstrip())
68158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      elif not '(' in line and space_break >= 0:
68258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        # Break long typedefs on nearest space.
68358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        lines.append(line[0:space_break])
68458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        lines.append('    ' + line[space_break + 1:])
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        left = line.rfind('(') + 1
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        args = line[left:].split(',')
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        orig_args = args
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        orig_left = left
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # Try to split on '(arg1)' or '(arg1, arg2)', not '()'
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        while args[0][0] == ')':
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          left = line.rfind('(', 0, left - 1) + 1
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if left == 0:  # No more parens, take the original option
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            args = orig_args
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            left = orig_left
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            break
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          args = line[left:].split(',')
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        line_max = 0
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for arg in args:
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if len(arg) > line_max: line_max = len(arg)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if left + line_max >= 80:
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          indent = '%s    ' % tab
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          args =  (',\n%s' % indent).join([arg.strip() for arg in args])
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          lines.append('%s\n%s%s' % (line[:left], indent, args))
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else:
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          indent = ' ' * (left - 1)
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          args =  (',\n%s' % indent).join(args)
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          lines.append('%s%s' % (line[:left], args))
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return '\n'.join(lines)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Define a top level object.
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Define(self, node, releases, tabs=0, prefix='', comment=False):
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this request does not match unique release, or if the release is not
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # available (possibly deprecated) then skip.
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unique = node.GetUniqueReleases(releases)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not unique or not node.InReleases(releases):
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ''
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogEnter('Define %s tab=%d prefix="%s"' % (node,tabs,prefix))
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    declmap = dict({
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'Enum': CGen.DefineEnum,
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'Function': CGen.DefineMember,
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'Interface': CGen.DefineStruct,
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'Member': CGen.DefineMember,
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'Struct': CGen.DefineStruct,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'Typedef': CGen.DefineTypedef
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    })
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = ''
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    func = declmap.get(node.cls, None)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not func:
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ErrOut.Log('Failed to define %s named %s' % (node.cls, node.GetName()))
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    define_txt = func(self, node, releases, prefix=prefix, comment=comment)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    comment_txt = GetNodeComments(node, tabs=0)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if comment_txt and comment:
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out += comment_txt
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out += define_txt
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    indented_out = self.Indent(out, tabs)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.LogExit('Exit Define')
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return indented_out
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Clean a string representing an object definition and return then string
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# as a single space delimited set of tokens.
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CleanString(instr):
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instr = instr.strip()
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instr = instr.split()
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ' '.join(instr)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Test a file, by comparing all it's objects, with their comments.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def TestFile(filenode):
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cgen = CGen()
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors = 0
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for node in filenode.GetChildren()[2:]:
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instr = node.GetOneOf('Comment')
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not instr: continue
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instr.Dump()
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instr = CleanString(instr.GetName())
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    outstr = cgen.Define(node, releases=['M14'])
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if GetOption('verbose'):
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print outstr + '\n'
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    outstr = CleanString(outstr)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if instr != outstr:
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ErrOut.Log('Failed match of\n>>%s<<\nto:\n>>%s<<\nFor:\n' %
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 (instr, outstr))
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      node.Dump(1, comments=True)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors += 1
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return errors
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Build and resolve the AST and compare each file individual.
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def TestFiles(filenames):
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not filenames:
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    idldir = os.path.split(sys.argv[0])[0]
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    idldir = os.path.join(idldir, 'test_cgen', '*.idl')
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filenames = glob.glob(idldir)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filenames = sorted(filenames)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ast = ParseFiles(filenames)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  total_errs = 0
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for filenode in ast.GetListOf('File'):
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errs = TestFile(filenode)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if errs:
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ErrOut.Log('%s test failed with %d error(s).' %
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (filenode.GetName(), errs))
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_errs += errs
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if total_errs:
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ErrOut.Log('Failed generator test.')
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoOut.Log('Passed generator test.')
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return total_errs
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def main(args):
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filenames = ParseOptions(args)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if GetOption('test'):
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TestFiles(filenames)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ast = ParseFiles(filenames)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cgen = CGen()
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for f in ast.GetListOf('File'):
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if f.GetProperty('ERRORS') > 0:
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print 'Skipping %s' % f.GetName()
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for node in f.GetChildren()[2:]:
815a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      print cgen.Define(node, ast.releases, comment=True, prefix='tst_')
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sys.exit(main(sys.argv[1:]))
820