| Index: tools/nixysa/nixysa/npapi_generator.py
|
| ===================================================================
|
| --- tools/nixysa/nixysa/npapi_generator.py (revision 0)
|
| +++ tools/nixysa/nixysa/npapi_generator.py (revision 0)
|
| @@ -0,0 +1,2386 @@
|
| +#!/usr/bin/python2.4
|
| +#
|
| +# Copyright 2008 Google Inc.
|
| +#
|
| +# Licensed under the Apache License, Version 2.0 (the "License");
|
| +# you may not use this file except in compliance with the License.
|
| +# You may obtain a copy of the License at
|
| +#
|
| +# http://www.apache.org/licenses/LICENSE-2.0
|
| +#
|
| +# Unless required by applicable law or agreed to in writing, software
|
| +# distributed under the License is distributed on an "AS IS" BASIS,
|
| +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +# See the License for the specific language governing permissions and
|
| +# limitations under the License.
|
| +
|
| +"""NPAPI glue generator.
|
| +
|
| +This module implements the generator for NPAPI glue code.
|
| +
|
| +For each class, the generator will create two NPObject classes:
|
| + - one for the class instances, exposing all the member functions and
|
| + properties, that wraps C++ instances. This one is created by the binding
|
| + model module - this is called the 'instance object'
|
| + - one for all the static members, like static functions and properties, but
|
| + also inner types. Only one instance of this one will be created. This one
|
| + is common to all the binding models, and is defined in static_object.h
|
| + (glue::globals::NPAPIObject) - this is called the 'static object'
|
| +
|
| +For namespaces, one of the second type is created as well (containing global
|
| +functions and properties, and inner namespaces/classes).
|
| +
|
| +That way if the IDL contains something like:
|
| +
|
| + namespace A {
|
| + class B {
|
| + static void C();
|
| + };
|
| + }
|
| +
|
| +then one can access C in JavaScript through plugin.A.B.C();
|
| +
|
| +The tricky part in this is that for namespaces, the definition of all the
|
| +members spans across multiple namespace definitions, possibly across multiple
|
| +files, but only one NPObject should exist, gathering all the members from all
|
| +the namespace definitions - that means the glue has to be generated for all the
|
| +definitions at once, generating the glue for each file separately will not
|
| +work. By convention, the NPAPI glue for a namespace will be defined in the
|
| +first file encountered that has a part of the namespace definition.
|
| +
|
| +Because of that, the code generation happens in 2 passes. The first one
|
| +generates the code for all the definitions except the namespaces, and gather
|
| +all the data for the namespace generation. Then the second pass generates the
|
| +code for the namespaces.
|
| +"""
|
| +
|
| +import string
|
| +import cpp_utils
|
| +import globals_binding
|
| +import idl_parser
|
| +import naming
|
| +import npapi_utils
|
| +import pod_binding
|
| +import syntax_tree
|
| +
|
| +
|
| +# default includes to add to the generated glue files
|
| +
|
| +_cpp_includes = [('plugin_main.h', False)]
|
| +
|
| +_header_includes = [('string.h', True),
|
| + ('string', True),
|
| + ('npapi.h', True),
|
| + ('npruntime.h', True),
|
| + ('common.h', False),
|
| + ('static_object.h', False)]
|
| +
|
| +
|
| +# glue templates and helper strings
|
| +
|
| +_enumerate_static_property_entries = """
|
| + memcpy(output, static_property_ids,
|
| + NUM_STATIC_PROPERTY_IDS * sizeof(NPIdentifier));
|
| + output += NUM_STATIC_PROPERTY_IDS;
|
| +"""
|
| +
|
| +_enumerate_static_method_entries = """
|
| + memcpy(output, static_method_ids,
|
| + NUM_STATIC_METHOD_IDS * sizeof(NPIdentifier));
|
| + output += NUM_STATIC_METHOD_IDS;
|
| +"""
|
| +
|
| +_enumerate_namespace_entries = """
|
| + memcpy(output, namespace_ids,
|
| + NUM_NAMESPACE_IDS * sizeof(NPIdentifier));
|
| + output += NUM_NAMESPACE_IDS;
|
| +"""
|
| +
|
| +_enumerate_property_entries = """
|
| + memcpy(output, property_ids,
|
| + NUM_PROPERTY_IDS * sizeof(NPIdentifier));
|
| + output += NUM_PROPERTY_IDS;
|
| +"""
|
| +
|
| +_enumerate_method_entries = """
|
| + memcpy(output, method_ids,
|
| + NUM_METHOD_IDS * sizeof(NPIdentifier));
|
| + output += NUM_METHOD_IDS;
|
| +"""
|
| +
|
| +_class_glue_header_static = """
|
| +void InitializeGlue(NPP npp);
|
| +NPClass *GetStaticNPClass(void);
|
| +glue::globals::NPAPIObject *CreateRawStaticNPObject(NPP npp);
|
| +void RegisterObjectBases(glue::globals::NPAPIObject *namespace_object,
|
| + glue::globals::NPAPIObject *root_object);
|
| +glue::globals::NPAPIObject *GetStaticNPObject(
|
| + glue::globals::NPAPIObject *root_object);
|
| +void StaticEnumeratePropertyHelper(NPIdentifier *output);
|
| +uint32_t GetStaticPropertyCount();
|
| +bool StaticInvoke(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result,
|
| + const char **error_handle);
|
| +bool StaticGetProperty(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + NPVariant *variant,
|
| + const char **error_handle);
|
| +bool StaticSetProperty(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *variant,
|
| + const char **error_handle);
|
| +"""
|
| +
|
| +_class_glue_header_member = """
|
| +NPClass *GetNPClass(void);
|
| +bool Invoke(${ClassMutableParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result,
|
| + const char **error_handle);
|
| +bool GetProperty(${ClassParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + NPVariant *variant,
|
| + const char **error_handle);
|
| +bool SetProperty(${ClassMutableParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *variant,
|
| + const char **error_handle);
|
| +bool EnumeratePropertyEntries(NPObject *header,
|
| + NPIdentifier **value,
|
| + uint32_t *count);
|
| +void EnumeratePropertyEntriesHelper(NPIdentifier *output);
|
| +uint32_t GetPropertyCount();
|
| +
|
| +${BindingGlueHeader}
|
| +"""
|
| +
|
| +_class_glue_header_template = string.Template(_class_glue_header_static +
|
| + _class_glue_header_member)
|
| +
|
| +_class_glue_cpp_common_head_static = """
|
| +static bool StaticHasMethod(NPObject *header, NPIdentifier name);
|
| +static bool StaticInvokeEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result);
|
| +static bool StaticInvokeDefault(NPObject *header,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result);
|
| +static bool StaticHasProperty(NPObject *header, NPIdentifier name);
|
| +static bool StaticGetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + NPVariant *variant);
|
| +static bool StaticSetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *variant);
|
| +static bool StaticEnumeratePropertyEntries(NPObject *header,
|
| + NPIdentifier **value,
|
| + uint32_t *count);
|
| +void StaticEnumeratePropertyHelper(NPIdentifier *output);
|
| +uint32_t GetStaticPropertyCount();
|
| +
|
| +static NPClass static_npclass = {
|
| + NP_CLASS_STRUCT_VERSION,
|
| + glue::globals::Allocate,
|
| + glue::globals::Deallocate,
|
| + 0,
|
| + StaticHasMethod,
|
| + StaticInvokeEntry,
|
| + StaticInvokeDefault,
|
| + StaticHasProperty,
|
| + StaticGetPropertyEntry,
|
| + StaticSetPropertyEntry,
|
| + 0,
|
| + StaticEnumeratePropertyEntries,
|
| +};
|
| +
|
| +NPClass *GetStaticNPClass(void)
|
| +{
|
| + return &static_npclass;
|
| +}
|
| +
|
| +${StaticPropertyTable}
|
| +${StaticMethodTable}
|
| +${NamespaceTable}
|
| +
|
| +uint32_t GetStaticPropertyCount() {
|
| + return ${StaticPropertyCount} + ${StaticMethodCount} + ${NamespaceCount};
|
| +}
|
| +
|
| +static bool StaticEnumeratePropertyEntries(NPObject *header,
|
| + NPIdentifier **value,
|
| + uint32_t *count) {
|
| + *count = 0;
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticEnumeratePropertyEntries", prof);
|
| + ${AddStaticPropertyCount}
|
| + ${AddStaticMethodCount}
|
| + ${AddNamespaceCount}
|
| + if (*count) {
|
| + GLUE_PROFILE_START(npp, "memalloc");
|
| + *value = static_cast<NPIdentifier *>(
|
| + NPN_MemAlloc(*count * sizeof(NPIdentifier)));
|
| + GLUE_PROFILE_STOP(npp, "memalloc");
|
| + StaticEnumeratePropertyHelper(*value);
|
| + } else {
|
| + *value = NULL;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +// This is broken out into a separate function so that the plugin object can
|
| +// call it on the global namespace without extra memory allocation.
|
| +// The caller is responsible for making sure there's sufficient space in output.
|
| +void StaticEnumeratePropertyHelper(NPIdentifier *output) {
|
| + ${EnumerateStaticPropertyEntries}
|
| + ${EnumerateStaticMethodEntries}
|
| + ${EnumerateNamespaceEntries}
|
| +}
|
| +
|
| +static void InitializeStaticIds(NPP npp) {
|
| + ${StaticPropertyInit}
|
| + ${StaticMethodInit}
|
| + ${NamespaceInit}
|
| + ${#InitNamespaceGlues}
|
| +}
|
| +
|
| +glue::globals::NPAPIObject *CreateRawStaticNPObject(NPP npp) {
|
| + GLUE_PROFILE_START(npp, "createobject");
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(
|
| + NPN_CreateObject(npp, &static_npclass));
|
| + GLUE_PROFILE_STOP(npp, "createobject");
|
| + ${#CreateNamespaces}
|
| + return object;
|
| +}
|
| +
|
| +void RegisterObjectBases(glue::globals::NPAPIObject *namespace_object,
|
| + glue::globals::NPAPIObject *root_object) {
|
| + ${#RegisterBases}
|
| +}
|
| +
|
| +${#GetStaticObjects}
|
| +
|
| +bool StaticInvokeDefault(NPObject *header,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result) {
|
| + const char *error=NULL;
|
| + const char **error_handle = &error;
|
| + bool success = true;
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticInvokeDefault", prof);
|
| + ${#StaticInvokeDefaultCode}
|
| + // Skip out early on the profiling, so as not to count error callback time.
|
| + GLUE_SCOPED_PROFILE_STOP(prof);
|
| + if (!success && error) {
|
| + glue::globals::SetLastError(npp, error);
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +static bool StaticInvokeEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result) {
|
| + // Chrome transforms InvokeDefault into Invoke with null parameter:
|
| + // http://code.google.com/p/chromium/issues/detail?id=5110
|
| + if (name == NULL)
|
| + return StaticInvokeDefault(header, args, argCount, result);
|
| + const char *error=NULL;
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_PROFILE_START(npp, std::string("${Class}::StaticInvokeEntry(") +
|
| + (id.text() ? id.text() : "") + ")");
|
| + bool success = StaticInvoke(object, npp, name, args, argCount, result,
|
| + &error);
|
| + GLUE_PROFILE_STOP(npp, std::string("${Class}::StaticInvokeEntry(") +
|
| + (id.text() ? id.text() : "") + ")");
|
| + if (!success && error) {
|
| + glue::globals::SetLastError(npp, error);
|
| + }
|
| + return success;
|
| +}
|
| +
|
| +static bool StaticGetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + NPVariant *variant) {
|
| + const char *error=NULL;
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_PROFILE_START(npp, std::string("${Class}::StaticGetPropertyEntry(") +
|
| + (id.text() ? id.text() : "") + ")");
|
| + bool success = StaticGetProperty(object, npp, name, variant, &error);
|
| + GLUE_PROFILE_STOP(npp, std::string("${Class}::StaticGetPropertyEntry(") +
|
| + (id.text() ? id.text() : "") + ")");
|
| + if (!success && error) {
|
| + glue::globals::SetLastError(npp, error);
|
| + }
|
| + return success;
|
| +}
|
| +
|
| +static bool StaticSetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *variant) {
|
| + const char *error=NULL;
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_PROFILE_START(npp, std::string("${Class}::StaticSetPropertyEntry(") +
|
| + (id.text() ? id.text() : "") + ")");
|
| + bool success = StaticSetProperty(object, npp, name, variant, &error);
|
| + GLUE_PROFILE_STOP(npp, std::string("${Class}::StaticSetPropertyEntry(") +
|
| + (id.text() ? id.text() : "") + ")");
|
| + if (!success && error) {
|
| + glue::globals::SetLastError(npp, error);
|
| + }
|
| + return success;
|
| +}
|
| +
|
| +"""
|
| +
|
| +_class_glue_cpp_common_head_member = """
|
| +static NPObject *Allocate(NPP npp, NPClass *theClass);
|
| +static void Deallocate(NPObject *header);
|
| +static bool HasMethod(NPObject *header, NPIdentifier name);
|
| +static bool InvokeEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result);
|
| +static bool HasProperty(NPObject *header, NPIdentifier name);
|
| +static bool GetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + NPVariant *variant);
|
| +static bool SetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *variant);
|
| +bool EnumeratePropertyEntries(NPObject *header,
|
| + NPIdentifier **value,
|
| + uint32_t *count);
|
| +void EnumeratePropertyEntriesHelper(NPIdentifier *output);
|
| +uint32_t GetPropertyCount();
|
| +static uint32_t GetLocalPropertyCount();
|
| +
|
| +
|
| +
|
| +static NPClass npclass = {
|
| + NP_CLASS_STRUCT_VERSION,
|
| + Allocate,
|
| + Deallocate,
|
| + 0,
|
| + HasMethod,
|
| + InvokeEntry,
|
| + 0,
|
| + HasProperty,
|
| + GetPropertyEntry,
|
| + SetPropertyEntry,
|
| + 0,
|
| + EnumeratePropertyEntries
|
| +};
|
| +
|
| +NPClass *GetNPClass(void)
|
| +{
|
| + return &npclass;
|
| +}
|
| +
|
| +${PropertyTable}
|
| +${MethodTable}
|
| +
|
| +uint32_t GetPropertyCount() {
|
| + return GetLocalPropertyCount() + ${BaseGetPropertyCount};
|
| +}
|
| +
|
| +static uint32_t GetLocalPropertyCount() {
|
| + return ${PropertyCount} + ${MethodCount};
|
| +}
|
| +
|
| +bool EnumeratePropertyEntries(NPObject *header,
|
| + NPIdentifier **value,
|
| + uint32_t *count) {
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_PROFILE_START(npp, "${Class}::EnumeratePropertyEntries");
|
| + *count = GetPropertyCount();
|
| + GLUE_PROFILE_START(npp, "memalloc");
|
| + *value = static_cast<NPIdentifier *>(
|
| + NPN_MemAlloc(*count * sizeof(NPIdentifier)));
|
| + GLUE_PROFILE_STOP(npp, "memalloc");
|
| + EnumeratePropertyEntriesHelper(*value);
|
| + GLUE_PROFILE_STOP(npp, "${Class}::EnumeratePropertyEntries");
|
| + return true;
|
| +}
|
| +
|
| +// This is broken out into a separate function so that derived classes can
|
| +// call it as well without extra memory allocation.
|
| +// The caller is responsible for making sure there's sufficient space in output.
|
| +void EnumeratePropertyEntriesHelper(NPIdentifier *output) {
|
| + ${EnumeratePropertyEntries}
|
| + ${EnumerateMethodEntries}
|
| + ${EnumeratePropertyEntriesHelperBaseCall}
|
| +}
|
| +
|
| +static void InitializeMemberIds(NPP npp) {
|
| + ${PropertyInit}
|
| + ${MethodInit}
|
| +}
|
| +
|
| +static void InitializeIds(NPP npp) {
|
| + InitializeMemberIds(npp);
|
| + InitializeStaticIds(npp);
|
| +}
|
| +
|
| +static bool InvokeEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result) {
|
| + const char *error=NULL;
|
| + const char **error_handle = &error;
|
| + DebugScopedId id(name); // debug helper
|
| + bool success = true;
|
| + ${DispatchFunctionHeader}
|
| + // Profile is a bit late, but it makes npp lookup easier.
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::InvokeEntry(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + if (!success) return false;
|
| + bool ret = Invoke(${Object}, npp, name, args, argCount, result, error_handle);
|
| + GLUE_SCOPED_PROFILE_STOP(prof);
|
| + if (!ret && error) {
|
| + glue::globals::SetLastError(npp, error);
|
| + return false;
|
| + }
|
| + return ret;
|
| +}
|
| +
|
| +static bool GetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + NPVariant *variant) {
|
| + const char *error=NULL;
|
| + const char **error_handle = &error;
|
| + DebugScopedId id(name); // debug helper
|
| + bool success = true;
|
| + ${DispatchFunctionHeader}
|
| + // Profile is a bit late, but it makes npp lookup easier.
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::GetPropertyEntry(") +
|
| + (id.text() ? id.text() : "") + ")", prof);
|
| + if (!success) return false; // A rare error case.
|
| + bool ret = GetProperty(${ObjectNonMutable}, npp, name, variant, error_handle);
|
| + GLUE_SCOPED_PROFILE_STOP(prof);
|
| + if (!ret && error) {
|
| + glue::globals::SetLastError(npp, error);
|
| + return false;
|
| + }
|
| + return ret;
|
| +}
|
| +
|
| +static bool SetPropertyEntry(NPObject *header,
|
| + NPIdentifier name,
|
| + const NPVariant *variant) {
|
| + const char *error=NULL;
|
| + const char **error_handle = &error;
|
| + DebugScopedId id(name); // debug helper
|
| + bool success = true;
|
| + ${DispatchFunctionHeader}
|
| + // Profile is a bit late, but it makes npp lookup easier.
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::SetPropertyEntry(") +
|
| + (id.text() ? id.text() : "") + ")", prof);
|
| + if (!success) return false; // A rare error case.
|
| + bool ret = SetProperty(${Object}, npp, name, variant, error_handle);
|
| + GLUE_SCOPED_PROFILE_STOP(prof);
|
| + if (!ret && error) {
|
| + glue::globals::SetLastError(npp, error);
|
| + return false;
|
| + }
|
| + return ret;
|
| +}
|
| +
|
| +${BindingGlueCpp}
|
| +"""
|
| +
|
| +_class_glue_cpp_base_member = """
|
| +bool Invoke(${ClassMutableParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result,
|
| + const char **error_handle) {
|
| + DebugScopedId id(name); // debug helper
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::Invoke(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + bool success = true;
|
| + ${#InvokeCode}
|
| + return ${BaseClassNamespace}::Invoke(object, npp, name, args, argCount,
|
| + result, error_handle);
|
| +}
|
| +
|
| +bool GetProperty(${ClassParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + NPVariant *variant,
|
| + const char **error_handle) {
|
| + DebugScopedId id(name); // debug helper
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::GetProperty(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${#GetPropertyCode}
|
| + return ${BaseClassNamespace}::GetProperty(object, npp, name, variant,
|
| + error_handle);
|
| +}
|
| +
|
| +bool SetProperty(${ClassMutableParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *variant,
|
| + const char **error_handle) {
|
| + DebugScopedId id(name); // debug helper
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::SetProperty(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${#SetPropertyCode}
|
| + return ${BaseClassNamespace}::SetProperty(object, npp, name, variant,
|
| + error_handle);
|
| +}
|
| +
|
| +static bool HasMethod(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::HasMethod(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${MethodCheck}
|
| + return ${BaseClassNamespace}::GetNPClass()->hasMethod(header, name);
|
| +}
|
| +
|
| +static bool HasProperty(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::HasProperty(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${PropertyCheck}
|
| + return ${BaseClassNamespace}::GetNPClass()->hasProperty(header, name);
|
| +}
|
| +"""
|
| +
|
| +_class_glue_cpp_base_static = """
|
| +bool StaticInvoke(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result,
|
| + const char **error_handle) {
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticInvoke", prof);
|
| + bool success = true;
|
| + ${#StaticInvokeCode}
|
| + return ${BaseClassNamespace}::StaticInvoke(
|
| + object->base(), npp, name, args, argCount, result, error_handle);
|
| +}
|
| +
|
| +bool StaticGetProperty(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + NPVariant *variant,
|
| + const char **error_handle) {
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticGetProperty", prof);
|
| + bool success = true;
|
| + ${#StaticGetPropertyCode}
|
| + if (glue::globals::GetProperty(object, name, variant)) return true;
|
| + return ${BaseClassNamespace}::StaticGetProperty(
|
| + object->base(), npp, name, variant, error_handle);
|
| +}
|
| +
|
| +bool StaticSetProperty(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *variant,
|
| + const char **error_handle) {
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticSetProperty", prof);
|
| + bool success = true;
|
| + ${#StaticSetPropertyCode}
|
| + if (glue::globals::SetProperty(object, name, variant)) return true;
|
| + return ${BaseClassNamespace}::StaticSetProperty(
|
| + object->base(), npp, name, variant, error_handle);
|
| +}
|
| +
|
| +static bool StaticHasMethod(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::StaticHasMethod(") +
|
| + (id.text() ? id.text() : "") + ")", prof);
|
| + ${StaticMethodCheck}
|
| + GLUE_SCOPED_PROFILE(npp, "hasmethod", prof1);
|
| + return NPN_HasMethod(npp, object->base(), name);
|
| +}
|
| +
|
| +static bool StaticHasProperty(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::StaticHasProperty(") +
|
| + (id.text() ? id.text() : "") + ")", prof);
|
| + ${StaticPropertyCheck}
|
| + bool success = glue::globals::HasProperty(header, name);
|
| + if (success) {
|
| + return success;
|
| + }
|
| + GLUE_SCOPED_PROFILE(npp, "hasproperty", prof1);
|
| + return NPN_HasProperty(npp, object->base(), name);
|
| +}
|
| +
|
| +"""
|
| +_class_glue_cpp_no_base_member = """
|
| +bool Invoke(${ClassMutableParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result,
|
| + const char **error_handle) {
|
| + DebugScopedId id(name); // debug helper
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::Invoke(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + bool success = true;
|
| + ${#InvokeCode}
|
| + if (!*error_handle) {
|
| + *error_handle =
|
| + "Method not found; perhaps it doesn't take that number of arguments?";
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool GetProperty(${ClassParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + NPVariant *variant,
|
| + const char **error_handle) {
|
| + DebugScopedId id(name); // debug helper
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::GetProperty(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${#GetPropertyCode}
|
| + if (!*error_handle) {
|
| + *error_handle = "Property not found.";
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool SetProperty(${ClassMutableParamType} object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *variant,
|
| + const char **error_handle) {
|
| + DebugScopedId id(name); // debug helper
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::SetProperty(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${#SetPropertyCode}
|
| + if (!*error_handle) {
|
| + *error_handle = "Property not found.";
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +static bool HasMethod(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::HasMethod(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${MethodCheck}
|
| + return false;
|
| +}
|
| +
|
| +static bool HasProperty(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::HasProperty(") + (id.text() ?
|
| + id.text() : "") + ")", prof);
|
| + ${PropertyCheck}
|
| + return false;
|
| +}
|
| +"""
|
| +
|
| +_class_glue_cpp_no_base_static = """
|
| +bool StaticInvoke(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *args,
|
| + uint32_t argCount,
|
| + NPVariant *result,
|
| + const char **error_handle) {
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticInvoke", prof);
|
| + bool success = true;
|
| + ${#StaticInvokeCode}
|
| + return false;
|
| +}
|
| +
|
| +bool StaticGetProperty(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + NPVariant *variant,
|
| + const char **error_handle) {
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticGetProperty", prof);
|
| + bool success = true;
|
| + ${#StaticGetPropertyCode}
|
| + success = glue::globals::GetProperty(object, name, variant);
|
| + return success;
|
| +}
|
| +
|
| +bool StaticSetProperty(glue::globals::NPAPIObject *object,
|
| + NPP npp,
|
| + NPIdentifier name,
|
| + const NPVariant *variant,
|
| + const char **error_handle) {
|
| + GLUE_SCOPED_PROFILE(npp, "${Class}::StaticSetProperty", prof);
|
| + bool success = true;
|
| + ${#StaticSetPropertyCode}
|
| + if (glue::globals::SetProperty(object, name, variant)) return true;
|
| + return false;
|
| +}
|
| +
|
| +static bool StaticHasMethod(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::StaticHasMethod(") +
|
| + (id.text() ? id.text() : "") + ")", prof);
|
| + ${StaticMethodCheck}
|
| + return false;
|
| +}
|
| +
|
| +static bool StaticHasProperty(NPObject *header, NPIdentifier name) {
|
| + DebugScopedId id(name); // debug helper
|
| + glue::globals::NPAPIObject *object =
|
| + static_cast<glue::globals::NPAPIObject *>(header);
|
| + NPP npp = object->npp();
|
| + GLUE_SCOPED_PROFILE(npp, std::string("${Class}::StaticHasProperty(") +
|
| + (id.text() ? id.text() : "") + ")", prof);
|
| + ${StaticPropertyCheck}
|
| + return glue::globals::HasProperty(header, name);
|
| +}
|
| +"""
|
| +
|
| +_namespace_glue_cpp_tail = """
|
| +void InitializeGlue(NPP npp) {
|
| + InitializeStaticIds(npp);
|
| +}
|
| +"""
|
| +
|
| +_class_glue_cpp_base_template = string.Template(''.join([
|
| + _class_glue_cpp_common_head_static,
|
| + _class_glue_cpp_common_head_member,
|
| + _class_glue_cpp_base_static,
|
| + _class_glue_cpp_base_member]))
|
| +
|
| +_class_glue_cpp_no_base_template = string.Template(''.join([
|
| + _class_glue_cpp_common_head_static,
|
| + _class_glue_cpp_common_head_member,
|
| + _class_glue_cpp_no_base_static,
|
| + _class_glue_cpp_no_base_member]))
|
| +
|
| +_namespace_glue_header = _class_glue_header_static
|
| +
|
| +_namespace_glue_cpp_template = string.Template(''.join([
|
| + _class_glue_cpp_common_head_static,
|
| + _class_glue_cpp_no_base_static,
|
| + _namespace_glue_cpp_tail]))
|
| +
|
| +_callback_glue_cpp_template = string.Template("""
|
| +${RunCallback} {
|
| +${StartException}
|
| + const char *error=NULL;
|
| + const char **error_handle = &error;
|
| + bool success = true;
|
| + NPVariant args[${ArgCount}];
|
| + NPVariant result;
|
| + NULL_TO_NPVARIANT(result);
|
| + ${ParamsToVariantsPre}
|
| + if (success) {
|
| + ${ParamsToVariantsPost}
|
| + if (async && NPCallback::SupportsAsync()) {
|
| + NPCallback* callback = NPCallback::Create(npp);
|
| + if (callback) {
|
| + callback->Set(npobject, args, ${ArgCount});
|
| + callback->CallAsync();
|
| + NPN_ReleaseObject(callback);
|
| + success = true;
|
| + } else {
|
| + success = false;
|
| + }
|
| + } else {
|
| + GLUE_PROFILE_START(npp, "invokeDefault");
|
| + success = NPN_InvokeDefault(npp,
|
| + npobject,
|
| + args,
|
| + ${ArgCount},
|
| + &result);
|
| + GLUE_PROFILE_STOP(npp, "invokeDefault");
|
| + if (success) {
|
| + GLUE_PROFILE_START(npp, "NPN_ReleaseVariantValue");
|
| + NPN_ReleaseVariantValue(&result);
|
| + GLUE_PROFILE_STOP(npp, "NPN_ReleaseVariantValue");
|
| + }
|
| + }
|
| + }
|
| + for (int i = 0; i != ${ArgCount}; ++i) {
|
| + NPN_ReleaseVariantValue(&args[i]);
|
| + }
|
| + ${ReturnEval}
|
| + return ${ReturnValue};
|
| +${EndException}
|
| +}
|
| +""")
|
| +
|
| +_callback_no_param_glue_cpp_template = string.Template("""
|
| +${RunCallback} {
|
| +${StartException}
|
| + const char *error=NULL;
|
| + const char **error_handle = &error;
|
| + bool success = true;
|
| + NPVariant result;
|
| + NULL_TO_NPVARIANT(result);
|
| + if (success) {
|
| + if (async && NPCallback::SupportsAsync()) {
|
| + NPCallback* callback = NPCallback::Create(npp);
|
| + if (callback) {
|
| + callback->Set(npobject, NULL, 0);
|
| + callback->CallAsync();
|
| + NPN_ReleaseObject(callback);
|
| + success = true;
|
| + } else {
|
| + success = false;
|
| + }
|
| + } else {
|
| + GLUE_PROFILE_START(npp, "invokeDefault");
|
| + success = NPN_InvokeDefault(npp,
|
| + npobject,
|
| + NULL,
|
| + 0,
|
| + &result);
|
| + GLUE_PROFILE_STOP(npp, "invokeDefault");
|
| + if (success) {
|
| + GLUE_PROFILE_START(npp, "NPN_ReleaseVariantValue");
|
| + NPN_ReleaseVariantValue(&result);
|
| + GLUE_PROFILE_STOP(npp, "NPN_ReleaseVariantValue");
|
| + }
|
| + }
|
| + }
|
| + ${ReturnEval}
|
| + return ${ReturnValue};
|
| +${EndException}
|
| +}
|
| +""")
|
| +
|
| +
|
| +_initialize_glue_template = string.Template(
|
| + '${Namespace}::InitializeGlue(npp);')
|
| +
|
| +_create_namespace_template = string.Template("""
|
| +object->SetNamespaceObject(${PROPERTY},
|
| + ${Namespace}::CreateRawStaticNPObject(npp));""")
|
| +
|
| +_register_base_template = string.Template("""
|
| +{
|
| + glue::globals::NPAPIObject *object =
|
| + namespace_object->GetNamespaceObjectByIndex(${PROPERTY});
|
| + object->set_base(${BaseClassNamespace}::GetStaticNPObject(root_object));
|
| + ${Namespace}::RegisterObjectBases(object, root_object);
|
| +}""")
|
| +
|
| +_register_no_base_template = string.Template("""
|
| +{
|
| + glue::globals::NPAPIObject *object =
|
| + namespace_object->GetNamespaceObjectByIndex(${PROPERTY});
|
| + ${Namespace}::RegisterObjectBases(object, root_object);
|
| +}""")
|
| +
|
| +_get_ns_object_template = string.Template("""
|
| +namespace ${Namespace} {
|
| +glue::globals::NPAPIObject *GetStaticNPObject(
|
| + glue::globals::NPAPIObject *root_object) {
|
| + glue::globals::NPAPIObject *parent =
|
| + ${ParentNamespace}::GetStaticNPObject(root_object);
|
| + return parent->GetNamespaceObjectByIndex(${PROPERTY});
|
| +}
|
| +} // namespace ${Namespace}""")
|
| +
|
| +_globals_glue_header_tail = """
|
| +glue::globals::NPAPIObject *CreateStaticNPObject(NPP npp);
|
| +"""
|
| +
|
| +_globals_glue_cpp_tail = """
|
| +glue::globals::NPAPIObject *GetStaticNPObject(
|
| + glue::globals::NPAPIObject *root_object) {
|
| + return root_object;
|
| +}
|
| +
|
| +glue::globals::NPAPIObject *CreateStaticNPObject(NPP npp) {
|
| + glue::globals::NPAPIObject *root_object = CreateRawStaticNPObject(npp);
|
| + RegisterObjectBases(root_object, root_object);
|
| + return root_object;
|
| +}
|
| +"""
|
| +
|
| +# code pieces templates
|
| +
|
| +_method_invoke_template = string.Template("""
|
| + if (name == ${table}[${method_id}] && argCount == ${argCount}) do {
|
| + bool success = true;
|
| + ${code}
|
| + } while(false);""")
|
| +
|
| +_method_default_invoke_template = string.Template("""
|
| + if (argCount == ${argCount}) do {
|
| + bool success = true;
|
| + ${code}
|
| + } while(false);""")
|
| +
|
| +_property_template = string.Template("""
|
| + if (name == ${table}[${property_id}]) do {
|
| + bool success = true;
|
| + ${code}
|
| + } while(false);""")
|
| +
|
| +_failure_test_string = ' if (!success) break;'
|
| +
|
| +_exception_context_start_template = string.Template(
|
| + """#define ${exception_macro_name} "${type} '${name}'" """)
|
| +
|
| +_exception_context_end_template = string.Template(
|
| + """#undef ${exception_macro_name}""")
|
| +
|
| +_exception_macro_name = 'NPAPI_GLUE_EXCEPTION_CONTEXT'
|
| +
|
| +def GenExceptionContext(exception_macro_name, type, name):
|
| + """Create code to define the context for exception error messages.
|
| +
|
| + Args:
|
| + exception_macro_name: the name to use for the macro
|
| + type: the type of access that name represents (field, parameter, etc.)
|
| + name: the name of the variable
|
| +
|
| + Returns:
|
| + a tuple of 2 strings; the first #defines the text to stick in the
|
| + exception, and the second #undefs the string to clean up the namespace.
|
| + """
|
| + start = _exception_context_start_template.substitute(type=type,
|
| + name=name,
|
| + exception_macro_name=
|
| + exception_macro_name)
|
| + end = _exception_context_end_template.substitute(exception_macro_name=
|
| + exception_macro_name)
|
| + return (start, end)
|
| +
|
| +def GenEndExceptionContext(exception_macro_name):
|
| + """Create code to clean up the context definition for exception error
|
| + messages.
|
| +
|
| + Args:
|
| + exception_macro_name: the name to use for the macro
|
| +
|
| + Returns:
|
| + the string to #undef the macro
|
| + """
|
| +
|
| +def GetGlueHeader(idl_file):
|
| + """Gets the name of the glue header file.
|
| +
|
| + Args:
|
| + idl_file: an idl_parser.File, the source IDL file.
|
| +
|
| + Returns:
|
| + the name of the header file.
|
| + """
|
| + if 'npapi_header' in idl_file.__dict__:
|
| + return idl_file.npapi_header
|
| + else:
|
| + return idl_file.basename + '_glue.h'
|
| +
|
| +
|
| +def GetGlueCpp(idl_file):
|
| + """Gets the name of the glue implementation file.
|
| +
|
| + Args:
|
| + idl_file: an idl_parser.File, the source IDL file.
|
| +
|
| + Returns:
|
| + the name of the implementation file.
|
| + """
|
| + if 'npapi_cpp' in idl_file.__dict__:
|
| + return idl_file.npapi_cpp
|
| + else:
|
| + return idl_file.basename + '_glue.cc'
|
| +
|
| +
|
| +class MethodWithoutReturnType(Exception):
|
| + """Raised when finding a function without return type."""
|
| +
|
| + def __init__(self, obj):
|
| + Exception.__init__(self)
|
| + self.object = obj
|
| +
|
| +
|
| +def GenNamespaceCode(context):
|
| + """Generates the code for namespace glue.
|
| +
|
| + This function generates the necessary code to initialize the
|
| + globals::NPAPIObject instance with the inner namespace objects.
|
| +
|
| + Args:
|
| + context: the NpapiGenerator.CodeGenContext for generating the glue.
|
| +
|
| + Returns:
|
| + a dict is generated by npapi_utils.MakeIdTableDict, and contains the
|
| + substitution strings for the namespace ids.
|
| + """
|
| + namespace_ids = []
|
| + if context.namespace_list:
|
| + context.namespace_create_section.EmitCode(
|
| + 'object->AllocateNamespaceObjects(NUM_NAMESPACE_IDS);')
|
| + context.namespace_create_section.EmitCode(
|
| + 'object->set_names(namespace_ids);')
|
| + for ns_obj in context.namespace_list:
|
| + id_enum = 'SCOPE_%s' % naming.Normalize(ns_obj.name, naming.Upper)
|
| + namespace_ids.append((id_enum, '"%s"' % ns_obj.name))
|
| + full_namespace = npapi_utils.GetGlueFullNamespace(ns_obj)
|
| + context.namespace_init_section.EmitCode(
|
| + _initialize_glue_template.substitute(Namespace=full_namespace))
|
| + context.namespace_create_section.EmitCode(
|
| + _create_namespace_template.substitute(PROPERTY=id_enum,
|
| + Namespace=full_namespace))
|
| + if ns_obj.defn_type == 'Class' and ns_obj.base_type:
|
| + base_class_namespace = npapi_utils.GetGlueFullNamespace(
|
| + ns_obj.base_type.GetFinalType())
|
| + context.namespace_register_base_section.EmitCode(
|
| + _register_base_template.substitute(
|
| + PROPERTY=id_enum,
|
| + BaseClassNamespace=base_class_namespace,
|
| + Namespace=full_namespace))
|
| + else:
|
| + context.namespace_register_base_section.EmitCode(
|
| + _register_no_base_template.substitute(PROPERTY=id_enum,
|
| + Namespace=full_namespace))
|
| +
|
| + context.namespace_get_static_object_section.EmitCode(
|
| + _get_ns_object_template.substitute(
|
| + Namespace=npapi_utils.GetGlueNamespace(ns_obj.GetFinalType()),
|
| + ParentNamespace=npapi_utils.GetGlueFullNamespace(
|
| + ns_obj.parent.GetFinalType()),
|
| + PROPERTY=id_enum))
|
| + return npapi_utils.MakeIdTableDict(namespace_ids, 'namespace')
|
| +
|
| +
|
| +def MakePodType(name):
|
| + """Creates a pod type with reasonable attributes.
|
| +
|
| + This function is used to be able to generate parameters that are not directly
|
| + referenced in the IDL
|
| +
|
| + Args:
|
| + name: the name of the pod type.
|
| +
|
| + Returns:
|
| + a Definition for the type.
|
| + """
|
| + source_file = idl_parser.File('<internal>')
|
| + source_file.header = None
|
| + source_file.npapi_cpp = None
|
| + source_file.npapi_header = None
|
| + source = idl_parser.SourceLocation(source_file, 0)
|
| + attributes = {'binding_model': 'pod'}
|
| + type_defn = syntax_tree.Typename(source, attributes, name)
|
| + type_defn.binding_model = pod_binding
|
| + type_defn.podtype = 'variant'
|
| + return type_defn
|
| +
|
| +
|
| +class NpapiGenerator(object):
|
| + """Main generator class."""
|
| +
|
| + def __init__(self, output_dir):
|
| + """Inits a NpapiGenerator instance.
|
| +
|
| + Args:
|
| + output_dir: the output directory for generated files.
|
| + """
|
| + self._output_dir = output_dir
|
| + self._namespace_map = {}
|
| + self._finalize_functions = []
|
| + # TODO: instead of passing a raw void *, it would be better to define a
|
| + # PluginInstance class. Needs a fair amount of refactoring in the C++ code.
|
| + self._plugin_data_type = MakePodType('void *')
|
| +
|
| + class CodeGenContext(object):
|
| + """Code generation context.
|
| +
|
| + This class gathers all the data that needs to be passed around in code
|
| + generation functions.
|
| +
|
| + Note: the section fields of this class are generated programatically.
|
| +
|
| + Attributes:
|
| + type: the container type (can be a Class or a Namespace).
|
| + binding_model: the binding model for the containing type.
|
| + is_namespace: whether or not the container is a namespace.
|
| + scope: current code generation scope, to generate properly qualified type
|
| + references.
|
| + header_section: the current code section in the header file.
|
| + cpp_section: the current code section in the implementation file.
|
| + static_prop_ids: the list of (enum_name, JS name) for properties in the
|
| + static object for the container type.
|
| + static_method_ids: the list of (enum_name, JS name) for methods in the
|
| + static object for the container type.
|
| + namespace_list: the list of inner namespace and classes of the container
|
| + type (to generate the static object)
|
| + prop_ids: the list of (enum_name, JS name) for properties in the
|
| + instance object for the container type.
|
| + method_ids: the list of (enum_name, JS name) for methods in the
|
| + instance object for the container type.
|
| + namespace_init_section: a section where the initialization code for the
|
| + namespaces in the static object will go.
|
| + namespace_create_section: a section where the globals::NPAPIObject
|
| + creation code will go.
|
| + namespace_register_base_section: a section where the class bases get
|
| + registered into their corresponding globals::NPAPIObject.
|
| + namespace_get_static_object_section: a section where the
|
| + GetStaticNPObject functions get defined.
|
| + static_invoke_section: a section where the Invoke implementation for the
|
| + static object will go (for static functions).
|
| + static_invoke_default_section: a section where the InvokeDefault
|
| + implementation for the static object will go (for constructors).
|
| + static_get_prop_section: a section where the GetProperty implementation
|
| + for the static object will go (for static members, enum values, and
|
| + inner namespaces).
|
| + static_set_prop_section: a section where the SetProperty implementation
|
| + for the static object will go (for static members).
|
| + invoke_section: a section where the Invoke implementation for the
|
| + instance object will go (for non-static methods).
|
| + get_prop_section: a section where the GetProperty implementation for the
|
| + instance object will go (for non-static members).
|
| + set_prop_section: a section where the SetProperty implementation for the
|
| + instance object will go (for non-static members).
|
| + """
|
| +
|
| + _sections = [('namespace_init_section', 'InitNamespaceGlues'),
|
| + ('namespace_create_section', 'CreateNamespaces'),
|
| + ('namespace_register_base_section', 'RegisterBases'),
|
| + ('namespace_get_static_object_section', 'GetStaticObjects'),
|
| + ('static_invoke_section', 'StaticInvokeCode'),
|
| + ('static_invoke_default_section', 'StaticInvokeDefaultCode'),
|
| + ('static_get_prop_section', 'StaticGetPropertyCode'),
|
| + ('static_set_prop_section', 'StaticSetPropertyCode')]
|
| +
|
| + _class_sections = [('invoke_section', 'InvokeCode'),
|
| + ('get_prop_section', 'GetPropertyCode'),
|
| + ('set_prop_section', 'SetPropertyCode')]
|
| +
|
| + def __init__(self, type_defn, scope, header_section, cpp_section,
|
| + share_context):
|
| + """Inits a CodeGenContext.
|
| +
|
| + Args:
|
| + type_defn: the container type.
|
| + scope: current code generation scope, to generate properly qualified
|
| + type references.
|
| + header_section: the current code section in the header file.
|
| + cpp_section: the current code section in the implementation file.
|
| + share_context: share the definition sections and the id lists with that
|
| + context (can be None) - used when encountering namespaces defined
|
| + previously.
|
| + """
|
| + self.type_defn = type_defn
|
| + self.binding_model = type_defn.binding_model or globals_binding
|
| + self.is_namespace = type_defn.defn_type == 'Namespace'
|
| + self.scope = scope
|
| + self.header_section = header_section
|
| + self.cpp_section = cpp_section
|
| + if self.is_namespace:
|
| + all_sections = self._sections
|
| + else:
|
| + all_sections = self._sections + self._class_sections
|
| + if share_context:
|
| + self.static_prop_ids = share_context.static_prop_ids
|
| + self.static_method_ids = share_context.static_method_ids
|
| + self.namespace_list = share_context.namespace_list
|
| + if not share_context.is_namespace:
|
| + self.prop_ids = share_context.prop_ids
|
| + self.method_ids = share_context.method_ids
|
| + # programmatically copy fields
|
| + for field_name, section_name in all_sections:
|
| + setattr(self, field_name, getattr(share_context, field_name))
|
| + else:
|
| + self.static_prop_ids = []
|
| + self.static_method_ids = []
|
| + self.namespace_list = []
|
| + if not self.is_namespace:
|
| + self.prop_ids = []
|
| + self.method_ids = []
|
| + # programmatically create fields
|
| + for field_name, section_name in all_sections:
|
| + setattr(self, field_name,
|
| + cpp_section.CreateUnlinkedSection(section_name))
|
| + getattr(self, field_name).needed_glue = cpp_section.needed_glue
|
| +
|
| + def GetParamInputStrings(self, scope, param_list):
|
| + """Gets the code to retrieve parameters from an array of NPVariants.
|
| +
|
| + Args:
|
| + scope: the code generation scope.
|
| + param_list: a list of Function.Param.
|
| +
|
| + Returns:
|
| + a 3-uple. The first element is a list of strings that contains the code
|
| + to retrieve the parameter values. The second element is a list of
|
| + expressions to access each of the parameters. The third element is the set
|
| + of all the types whose glue header is needed.
|
| + """
|
| + strings = []
|
| + param_names = []
|
| + needed_glue = set()
|
| + for i in range(len(param_list)):
|
| + param = param_list[i]
|
| + needed_glue.add(param.type_defn)
|
| + param_binding = param.type_defn.binding_model
|
| + start_exception, end_exception = GenExceptionContext(
|
| + _exception_macro_name, "parameter",
|
| + naming.Normalize(param.name, naming.Java))
|
| + code, param_access = param_binding.NpapiFromNPVariant(
|
| + scope, param.type_defn, 'args[%d]' % i, 'param_%s' % param.name,
|
| + 'success', _exception_macro_name, 'npp')
|
| + strings.append(start_exception)
|
| + strings.append(code)
|
| + strings.append(_failure_test_string)
|
| + strings.append(end_exception)
|
| + param_names.append(param_access)
|
| + return strings, param_names, needed_glue
|
| +
|
| + def GetReturnStrings(self, scope, type_defn, expression, result):
|
| + """Gets the code to set a return value into a NPVariant.
|
| +
|
| + Args:
|
| + scope: the code generation scope.
|
| + type_defn: the type of the return value.
|
| + expression: the expression that evaluates to the return value.
|
| + result: the expression that evaluates to a pointer to the NPVariant.
|
| +
|
| + Returns:
|
| + a 3-uple. The first element is the code to generate the
|
| + NPVariant-compatible value (that can fail). The second element is the
|
| + code to set the NPVariant. The third element is the set of all the types
|
| + whose glue header is needed.
|
| + """
|
| + binding_model = type_defn.binding_model
|
| + pre, post = binding_model.NpapiExprToNPVariant(scope, type_defn, 'retval',
|
| + expression, result,
|
| + 'success', 'npp')
|
| + return pre, post, set([type_defn])
|
| +
|
| + def GetVoidReturnStrings(self, type_defn, result):
|
| + """Gets the code to return a void value for a write-only member.
|
| +
|
| + Args:
|
| + type_defn: the type of the return value.
|
| + result: the expression that evaluates to a pointer to the NPVariant.
|
| +
|
| + Returns:
|
| + a 3-uple. The first element is empty, and is needed only to mimic the
|
| + return of GetReturnStrings. The second element is the code to set the
|
| + NPVariant. The third element is the set of all the types whose glue
|
| + header is needed.
|
| + """
|
| + post = "VOID_TO_NPVARIANT(*%s);\n" % result
|
| + return "", post, set([type_defn])
|
| +
|
| + def GenerateCppFunction(self, section, scope, function):
|
| + """Generates a function header.
|
| +
|
| + Args:
|
| + section: the code section to generate the function header into.
|
| + scope: the code generation scope.
|
| + function: the Function to generate.
|
| + """
|
| + prototype, unused_val = cpp_utils.GetFunctionPrototype(scope, function, '')
|
| + section.EmitCode(prototype + ';')
|
| +
|
| + def GetUserGlueMethodFunc(self, scope, type_defn, method):
|
| + """Creates a definition for the user glue function for a non-static method.
|
| +
|
| + Args:
|
| + scope: the code generation scope.
|
| + type_defn: the type of the method container.
|
| + method: the method for which to create the user glue function.
|
| +
|
| + Returns:
|
| + a syntax_tree.Function for the user glue function.
|
| + """
|
| + glue_function = syntax_tree.Function(method.source, [],
|
| + 'userglue_method_%s' % method.name,
|
| + None, [])
|
| + glue_function.type_defn = method.type_defn
|
| + glue_function.parent = scope
|
| + this_param = syntax_tree.Function.Param(type_defn.name, '_this')
|
| + this_param.type_defn = type_defn
|
| + this_param.mutable = True
|
| + glue_function.params = [this_param] + method.params
|
| + return glue_function
|
| +
|
| + def GetUserGlueStaticMethodFunc(self, scope, method):
|
| + """Creates a definition for the user glue function for a static function.
|
| +
|
| + Args:
|
| + scope: the code generation scope.
|
| + method: the method for which to create the user glue function.
|
| +
|
| + Returns:
|
| + a syntax_tree.Function for the user glue function.
|
| + """
|
| + glue_function = syntax_tree.Function(method.source, [],
|
| + 'userglue_static_%s' % method.name,
|
| + None, [])
|
| + glue_function.type_defn = method.type_defn
|
| + glue_function.params = method.params[:]
|
| + glue_function.parent = scope
|
| + return glue_function
|
| +
|
| + def GetUserGlueConstructorFunc(self, scope, type_defn, method):
|
| + """Creates a definition for the user glue function for a constructor.
|
| +
|
| + Args:
|
| + scope: the code generation scope.
|
| + type_defn: the type of the method container.
|
| + method: the constructor for which to create the user glue function.
|
| +
|
| + Returns:
|
| + a syntax_tree.Function for the user glue function.
|
| + """
|
| + glue_function = syntax_tree.Function(method.source, [],
|
| + 'userglue_construct_%s' % method.name,
|
| + None, [])
|
| + glue_function.type_defn = type_defn
|
| + glue_function.params = method.params[:]
|
| + glue_function.parent = scope
|
| + return glue_function
|
| +
|
| + def GetUserGlueSetterFunc(self, scope, type_defn, field):
|
| + """Creates a definition for the user glue function for a setter method.
|
| +
|
| + For a field name 'myField' of type "FieldType" in an object of type
|
| + 'ObjectType', this creates a function like:
|
| + void userglue_setter_myField(ObjectType _this, FieldType param_myField)
|
| +
|
| + Args:
|
| + scope: the code generation scope.
|
| + type_defn: the type of the method container.
|
| + method: the method for which to create the user glue function.
|
| +
|
| + Returns:
|
| + a syntax_tree.Function for the user glue function.
|
| + """
|
| + glue_function = syntax_tree.Function(field.source, [],
|
| + 'userglue_setter_%s' % field.name,
|
| + None, [])
|
| + glue_function.type_defn = scope.LookUpTypeRecursive('void')
|
| + glue_function.parent = scope
|
| + this_param = syntax_tree.Function.Param(type_defn.name, '_this')
|
| + this_param.type_defn = type_defn
|
| + this_param.mutable = True
|
| + value_param = syntax_tree.Function.Param(type_defn.name, 'param_' +
|
| + field.name)
|
| + value_param.type_defn = field.type_defn
|
| + glue_function.params = [this_param, value_param]
|
| + return glue_function
|
| +
|
| + def GetUserGlueGetterFunc(self, scope, type_defn, field):
|
| + """Creates a definition for the user glue function for a getter method.
|
| +
|
| + For a field name 'myField' of type "FieldType" in an object of type
|
| + 'ObjectType', this creates a function like:
|
| + FieldType userglue_getter_myField(ObjectType _this)
|
| +
|
| + Args:
|
| + scope: the code generation scope.
|
| + type_defn: the type of the method container.
|
| + method: the method for which to create the user glue function.
|
| +
|
| + Returns:
|
| + a syntax_tree.Function for the user glue function.
|
| + """
|
| + glue_function = syntax_tree.Function(field.source, [],
|
| + 'userglue_getter_%s' % field.name,
|
| + None, [])
|
| + glue_function.type_defn = field.type_defn
|
| + glue_function.parent = scope
|
| + this_param = syntax_tree.Function.Param(type_defn.name, '_this')
|
| + this_param.type_defn = type_defn
|
| + this_param.mutable = True
|
| + glue_function.params = [this_param]
|
| + return glue_function
|
| +
|
| + def AddPluginDataParam(self, scope, func, param_exprs):
|
| + """Adds the plugin data parameter to a function and parameter list.
|
| +
|
| + Args:
|
| + scope: the scope for the parameter type.
|
| + func: the function to which we add a parameter.
|
| + param_exprs: the list of parameters exressions to which the plugin data
|
| + is added
|
| + """
|
| + scope = scope # silence gpylint
|
| + plugin_data_param = syntax_tree.Function.Param(
|
| + self._plugin_data_type.name, 'plugin_data')
|
| + plugin_data_param.type_defn = self._plugin_data_type
|
| + func.params.insert(0, plugin_data_param)
|
| + param_exprs.insert(0, 'npp->pdata')
|
| +
|
| + def EmitMemberCall(self, context, func):
|
| + """Emits the glue for a non-static member function call.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + func: the method to call.
|
| + """
|
| + scope = context.scope
|
| + type_defn = context.type_defn
|
| + binding_model = context.binding_model
|
| + section = context.invoke_section
|
| + id_enum = 'METHOD_%s' % naming.Normalize(func.name, naming.Upper)
|
| + name = '"%s"' % naming.Normalize(func.name, naming.Java)
|
| + context.method_ids.append((id_enum, name))
|
| + strings, param_exprs, needed_glue = self.GetParamInputStrings(scope,
|
| + func.params)
|
| + section.needed_glue.update(needed_glue)
|
| + if 'userglue' in func.attributes:
|
| + glue_func = self.GetUserGlueMethodFunc(scope, type_defn, func)
|
| + param_exprs.insert(0, 'object')
|
| + if 'plugin_data' in func.attributes:
|
| + self.AddPluginDataParam(context.scope, glue_func, param_exprs)
|
| + self.GenerateCppFunction(context.header_section, scope, glue_func)
|
| + expression = globals_binding.CppCallStaticMethod(scope, scope, glue_func,
|
| + param_exprs)
|
| + else:
|
| + expression = binding_model.CppCallMethod(scope, type_defn, 'object',
|
| + True, func, param_exprs)
|
| + pre, post, needed_glue = self.GetReturnStrings(scope, func.type_defn,
|
| + expression, 'result')
|
| + section.needed_glue.update(needed_glue)
|
| + strings += [pre, _failure_test_string, post, 'return true;']
|
| + self.EmitInvokeCode(section, 'method_ids', id_enum, len(func.params),
|
| + '\n'.join(strings))
|
| +
|
| + def EmitStaticCall(self, context, func):
|
| + """Emits the glue for a static function call.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + func: the function to call.
|
| + """
|
| + scope = context.scope
|
| + type_defn = context.type_defn
|
| + binding_model = context.binding_model
|
| + section = context.static_invoke_section
|
| + id_enum = 'STATIC_METHOD_%s' % naming.Normalize(func.name, naming.Upper)
|
| + name = '"%s"' % naming.Normalize(func.name, naming.Java)
|
| + context.static_method_ids.append((id_enum, name))
|
| +
|
| + strings, param_exprs, needed_glue = self.GetParamInputStrings(scope,
|
| + func.params)
|
| + section.needed_glue.update(needed_glue)
|
| + if 'userglue' in func.attributes:
|
| + glue_func = self.GetUserGlueStaticMethodFunc(scope, func)
|
| + if 'plugin_data' in func.attributes:
|
| + self.AddPluginDataParam(context.scope, glue_func, param_exprs)
|
| + self.GenerateCppFunction(context.header_section, scope, glue_func)
|
| + expression = globals_binding.CppCallStaticMethod(scope, scope, glue_func,
|
| + param_exprs)
|
| + else:
|
| + expression = binding_model.CppCallStaticMethod(scope, type_defn, func,
|
| + param_exprs)
|
| + pre, post, needed_glue = self.GetReturnStrings(scope, func.type_defn,
|
| + expression, 'result')
|
| + section.needed_glue.update(needed_glue)
|
| + strings += [pre, _failure_test_string, post, 'return true;']
|
| + self.EmitInvokeCode(section, 'static_method_ids', id_enum,
|
| + len(func.params), '\n'.join(strings))
|
| +
|
| + def EmitConstructorCall(self, context, func):
|
| + """Emits the glue for a constructor call.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + func: the constructor to call.
|
| + """
|
| + scope = context.scope
|
| + type_defn = context.type_defn
|
| + binding_model = context.binding_model
|
| + section = context.static_invoke_default_section
|
| + strings, param_exprs, needed_glue = self.GetParamInputStrings(scope,
|
| + func.params)
|
| + section.needed_glue.update(needed_glue)
|
| + if 'userglue' in func.attributes:
|
| + glue_func = self.GetUserGlueConstructorFunc(scope, type_defn, func)
|
| + if 'plugin_data' in func.attributes:
|
| + self.AddPluginDataParam(context.scope, glue_func, param_exprs)
|
| + self.GenerateCppFunction(context.header_section, scope, glue_func)
|
| + expression = globals_binding.CppCallStaticMethod(scope, scope, glue_func,
|
| + param_exprs)
|
| + else:
|
| + expression = binding_model.CppCallConstructor(scope, type_defn, func,
|
| + param_exprs)
|
| + pre, post, needed_glue = self.GetReturnStrings(scope, type_defn, expression,
|
| + 'result')
|
| + section.needed_glue.update(needed_glue)
|
| + strings += [pre, _failure_test_string, post, 'return true;']
|
| + self.EmitInvokeDefaultCode(section, len(func.params), '\n'.join(strings))
|
| +
|
| + def EmitMemberProp(self, context, field):
|
| + """Emits the glue for a non-static member field access.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + field: the field to access.
|
| + """
|
| + scope = context.scope
|
| + type_defn = context.type_defn
|
| + binding_model = context.binding_model
|
| + id_enum = 'PROPERTY_%s' % naming.Normalize(field.name, naming.Upper)
|
| + prop_name = '"%s"' % naming.Normalize(field.name, naming.Java)
|
| + context.prop_ids.append((id_enum, prop_name))
|
| + if 'getter' in field.attributes:
|
| + if 'userglue_getter' in field.attributes:
|
| + glue_func = self.GetUserGlueGetterFunc(scope, type_defn, field)
|
| + param_exprs = ['object']
|
| + if 'plugin_data' in field.attributes:
|
| + self.AddPluginDataParam(scope, glue_func, param_exprs)
|
| + self.GenerateCppFunction(context.header_section, scope, glue_func)
|
| + expression = globals_binding.CppCallStaticMethod(scope, scope,
|
| + glue_func, param_exprs)
|
| + else:
|
| + expression = binding_model.CppGetField(scope, type_defn, 'object',
|
| + field)
|
| + pre, post, needed_glue = self.GetReturnStrings(scope, field.type_defn,
|
| + expression, 'variant')
|
| + else:
|
| + # Return a void value for write-only members.
|
| + pre, post, needed_glue = self.GetVoidReturnStrings(field.type_defn,
|
| + 'variant')
|
| +
|
| + section = context.get_prop_section
|
| + section.needed_glue.update(needed_glue)
|
| + get_string = '\n'.join([pre, _failure_test_string, post, 'return true;'])
|
| + self.EmitPropertyCode(section, 'property_ids', id_enum, get_string)
|
| +
|
| + if 'setter' in field.attributes:
|
| + # TODO: Add a specific error for trying to set a read-only prop.
|
| + field_binding = field.type_defn.binding_model
|
| + start_exception, end_exception = GenExceptionContext(
|
| + _exception_macro_name, "field",
|
| + naming.Normalize(field.name, naming.Java))
|
| + code, param_expr = field_binding.NpapiFromNPVariant(
|
| + scope, field.type_defn, '(*variant)', 'param_%s' % field.name,
|
| + 'success', _exception_macro_name, 'npp')
|
| + section = context.set_prop_section
|
| + section.needed_glue.add(field.type_defn)
|
| + if 'userglue_setter' in field.attributes:
|
| + glue_func = self.GetUserGlueSetterFunc(scope, type_defn, field)
|
| + param_exprs = ['object', param_expr]
|
| + if 'plugin_data' in field.attributes:
|
| + self.AddPluginDataParam(scope, glue_func, param_exprs)
|
| + self.GenerateCppFunction(context.header_section, scope, glue_func)
|
| + expression = globals_binding.CppCallStaticMethod(scope, scope,
|
| + glue_func, param_exprs)
|
| + else:
|
| + expression = binding_model.CppSetField(scope, type_defn, 'object',
|
| + field, param_expr)
|
| + strings = [start_exception, code, _failure_test_string,
|
| + '%s;' % expression, 'return true;', end_exception]
|
| + self.EmitPropertyCode(section, 'property_ids', id_enum,
|
| + '\n'.join(strings))
|
| +
|
| + def EmitStaticMemberProp(self, context, field):
|
| + """Emits the glue for a static field access.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + field: the field to access.
|
| + """
|
| + scope = context.scope
|
| + type_defn = context.type_defn
|
| + binding_model = context.binding_model
|
| + id_enum = 'STATIC_PROPERTY_%s' % naming.Normalize(field.name, naming.Upper)
|
| + prop_name = '"%s"' % naming.Normalize(field.name, naming.Java)
|
| + context.static_prop_ids.append((id_enum, prop_name))
|
| + if 'getter' in field.attributes:
|
| + expression = binding_model.CppGetStatic(scope, type_defn, field)
|
| + pre, post, needed_glue = self.GetReturnStrings(scope, field.type_defn,
|
| + expression, 'variant')
|
| + else:
|
| + # Return a void value for write-only members.
|
| + pre, post, needed_glue = self.GetVoidReturnStrings(field.type_defn,
|
| + 'variant')
|
| + section = context.static_get_prop_section
|
| + section.needed_glue.update(needed_glue)
|
| + get_string = '\n'.join([pre, _failure_test_string, post, 'return true;'])
|
| + self.EmitPropertyCode(section, 'static_property_ids', id_enum,
|
| + get_string)
|
| +
|
| + if 'setter' in field.attributes:
|
| + # TODO: Add a specific error for trying to set a read-only prop.
|
| + field_binding = field.type_defn.binding_model
|
| + start_exception, end_exception = GenExceptionContext(
|
| + _exception_macro_name, "field",
|
| + naming.Normalize(field.name, naming.Java))
|
| + code, param_expr = field_binding.NpapiFromNPVariant(
|
| + scope, field.type_defn, '(*variant)', 'param_%s' % field.name,
|
| + 'success', _exception_macro_name, 'npp')
|
| + section = context.static_set_prop_section
|
| + section.needed_glue.add(field.type_defn)
|
| + expression = binding_model.CppSetStatic(scope, type_defn, field,
|
| + param_expr)
|
| + strings = [start_exception, code, _failure_test_string,
|
| + '%s;' % expression, 'return true;', end_exception]
|
| + self.EmitPropertyCode(section, 'static_property_ids', id_enum,
|
| + '\n'.join(strings))
|
| +
|
| + def EmitEnumValue(self, context, enum, enum_value):
|
| + """Emits the glue for an enum value access.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + enum: the enum definition.
|
| + enum_value: the enum value to access.
|
| + """
|
| + enum = enum # silence gpylint.
|
| + scope = context.scope
|
| + type_defn = context.type_defn
|
| + section = context.static_get_prop_section
|
| + name = naming.Normalize(enum_value.name, naming.Upper)
|
| + id_enum = 'ENUM_%s' % name
|
| + prop_name = '"%s"' % name
|
| + context.static_prop_ids.append((id_enum, prop_name))
|
| + strings = ['INT32_TO_NPVARIANT(%s::%s, *variant);' %
|
| + (cpp_utils.GetScopedName(scope, type_defn), enum_value.name),
|
| + 'return true;']
|
| + self.EmitPropertyCode(section, 'static_property_ids', id_enum,
|
| + '\n'.join(strings))
|
| +
|
| + def EmitInvokeCode(self, section, table, id_enum, arg_count, code):
|
| + """Emits glue code in an 'Invoke' dispatch function.
|
| +
|
| + Args:
|
| + section: the code section of the dispatch function.
|
| + table: the table in which the method identifier is defined.
|
| + id_enum: the method identifier enum.
|
| + arg_count: the number of arguments for the function.
|
| + code: the glue code.
|
| + """
|
| + section.EmitCode(_method_invoke_template.substitute(table=table,
|
| + method_id=id_enum,
|
| + argCount=arg_count,
|
| + code=code))
|
| +
|
| + def EmitInvokeDefaultCode(self, section, arg_count, code):
|
| + """Emits glue code in an 'InvokeDefault' dispatch function.
|
| +
|
| + Args:
|
| + section: the code section of the dispatch function.
|
| + arg_count: the number of arguments for the function.
|
| + code: the glue code.
|
| + """
|
| + section.EmitCode(_method_default_invoke_template.substitute(
|
| + argCount=arg_count, code=code))
|
| +
|
| + def EmitPropertyCode(self, section, table, id_enum, code):
|
| + """Emits glue code in a 'GetProperty' or 'SetProperty' dispatch function.
|
| +
|
| + Args:
|
| + section: the code section of the dispatch function.
|
| + table: the table in which the property identifier is defined.
|
| + id_enum: the property identifier enum.
|
| + code: the glue code.
|
| + """
|
| + section.EmitCode(_property_template.substitute(table=table,
|
| + property_id=id_enum,
|
| + code=code))
|
| +
|
| + def Variable(self, context, obj):
|
| + """Emits the glue code for a Variable definition.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + obj: the Variable definition.
|
| + """
|
| + if 'private' in obj.attributes or 'protected' in obj.attributes:
|
| + return
|
| + if 'static' in obj.attributes or context.is_namespace:
|
| + self.EmitStaticMemberProp(context, obj)
|
| + else:
|
| + self.EmitMemberProp(context, obj)
|
| +
|
| + def Enum(self, context, obj):
|
| + """Emits the glue code for an Enum definition.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + obj: the Enum definition.
|
| + """
|
| + if 'private' in obj.attributes or 'protected' in obj.attributes:
|
| + return
|
| + for value in obj.values:
|
| + self.EmitEnumValue(context, obj, value)
|
| +
|
| + def Function(self, context, obj):
|
| + """Emits the glue code for a Function definition.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + obj: the Function definition.
|
| +
|
| + Raises:
|
| + MethodWithoutReturnType: a non-constructor function doesn't have a return
|
| + type.
|
| + """
|
| + if 'private' in obj.attributes or 'protected' in obj.attributes:
|
| + return
|
| + if 'static' in obj.attributes or context.is_namespace:
|
| + self.EmitStaticCall(context, obj)
|
| + else:
|
| + if not obj.type_defn:
|
| + if obj.name == context.type_defn.name:
|
| + # constructor
|
| + self.EmitConstructorCall(context, obj)
|
| + elif obj.name == '~' + context.type_defn.name:
|
| + # destructor (ignore)
|
| + return
|
| + else:
|
| + # method without return type: error
|
| + raise MethodWithoutReturnType(obj)
|
| + else:
|
| + self.EmitMemberCall(context, obj)
|
| +
|
| + def Callback(self, context, obj):
|
| + """Emits the glue code for a Callback definition.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + obj: the Callback definition.
|
| + """
|
| + if 'private' in obj.attributes or 'protected' in obj.attributes:
|
| + return
|
| +
|
| + binding_model = obj.binding_model
|
| + namespace_name = npapi_utils.GetGlueNamespace(obj)
|
| +
|
| + scope = syntax_tree.Namespace(None, [], namespace_name, [])
|
| + scope.parent = context.scope
|
| +
|
| + context.header_section.PushNamespace(namespace_name)
|
| + header_section = context.header_section.CreateSection(namespace_name)
|
| + header_section.needed_defn = context.header_section.needed_defn
|
| + context.header_section.PopNamespace()
|
| +
|
| + context.cpp_section.PushNamespace(namespace_name)
|
| + cpp_section = context.cpp_section.CreateSection(namespace_name)
|
| + cpp_section.needed_glue = context.cpp_section.needed_glue
|
| + context.cpp_section.PopNamespace()
|
| +
|
| + param_to_variant_pre = []
|
| + param_to_variant_post = []
|
| + param_strings = []
|
| + for i in xrange(len(obj.params)):
|
| + p = obj.params[i]
|
| + param_string, unused_val = cpp_utils.GetFunctionParamPrototype(scope, p)
|
| + header_section.needed_defn.add(p.type_defn)
|
| + cpp_section.needed_glue.add(p.type_defn)
|
| + param_strings += [param_string]
|
| + bm = p.type_defn.binding_model
|
| + pre, post = bm.NpapiExprToNPVariant(scope, p.type_defn, 'var_' + p.name,
|
| + p.name, '(args + %d)' % i, 'success',
|
| + 'npp')
|
| + param_to_variant_pre.append(pre)
|
| + param_to_variant_post.append(post)
|
| +
|
| + if param_strings:
|
| + param_strings = [''] + param_strings
|
| +
|
| + return_type = obj.type_defn
|
| + header_section.needed_defn.add(return_type)
|
| + cpp_section.needed_glue.add(return_type)
|
| + bm = return_type.binding_model
|
| + return_type_string, unused_val = bm.CppReturnValueString(scope,
|
| + return_type)
|
| + run_callback = ('%s RunCallback(NPP npp, NPObject *npobject, bool async%s)'
|
| + % (return_type_string, ', '.join(param_strings)))
|
| +
|
| + return_eval, return_value = bm.NpapiFromNPVariant(scope, return_type,
|
| + 'result', 'retval',
|
| + 'success',
|
| + _exception_macro_name,
|
| + 'npp')
|
| + start_exception, end_exception = GenExceptionContext(
|
| + _exception_macro_name, "callback return value", "<no name>")
|
| + subst_dict = {'RunCallback': run_callback,
|
| + 'ArgCount': str(len(obj.params)),
|
| + 'ParamsToVariantsPre': '\n'.join(param_to_variant_pre),
|
| + 'ParamsToVariantsPost': '\n'.join(param_to_variant_post),
|
| + 'ReturnEval': return_eval,
|
| + 'ReturnValue': return_value,
|
| + 'StartException': start_exception,
|
| + 'EndException': end_exception}
|
| + if obj.params:
|
| + glue_template = _callback_glue_cpp_template
|
| + else:
|
| + glue_template = _callback_no_param_glue_cpp_template
|
| + cpp_section.EmitCode(glue_template.substitute(subst_dict))
|
| + cpp_section.EmitCode(binding_model.NpapiBindingGlueCpp(scope, obj))
|
| + header_section.EmitCode(binding_model.NpapiBindingGlueHeader(scope, obj))
|
| +
|
| + def GetDictForEnumerations(self, context, has_base):
|
| + """Creates a dictionary used to fill in the gaps in the property
|
| + enumeration functions. Note that this dictionary will in some cases cause
|
| + the insertion of the string ${BaseClassNamespace}, so it must be used
|
| + *before* the dictionary that fills in that macro. This only happens when
|
| + the context is a derived class.
|
| +
|
| + Args:
|
| + context: the code generation context
|
| + has_base: whether this is a class that has a base class
|
| +
|
| + Returns:
|
| + a dictionary containing definitions for the code generation templates
|
| + """
|
| + dict = {}
|
| + if not context.is_namespace:
|
| + if context.prop_ids:
|
| + dict.update({
|
| + 'PropertyCount': 'NUM_PROPERTY_IDS',
|
| + 'EnumeratePropertyEntries': _enumerate_property_entries,
|
| + })
|
| + else:
|
| + dict.update({
|
| + 'PropertyCount': '0',
|
| + 'EnumeratePropertyEntries': '',
|
| + })
|
| + if context.method_ids:
|
| + dict.update({
|
| + 'MethodCount': 'NUM_METHOD_IDS',
|
| + 'EnumerateMethodEntries': _enumerate_method_entries,
|
| + })
|
| + else:
|
| + dict.update({
|
| + 'MethodCount': '0',
|
| + 'EnumerateMethodEntries': '',
|
| + })
|
| + if has_base:
|
| + dict.update({
|
| + 'BaseGetPropertyCount': '${BaseClassNamespace}::GetPropertyCount()',
|
| + 'EnumeratePropertyEntriesHelperBaseCall':
|
| + """${BaseClassNamespace}::EnumeratePropertyEntriesHelper(
|
| + output);\n""",
|
| + })
|
| + else:
|
| + dict.update({
|
| + 'BaseGetPropertyCount': '0',
|
| + 'EnumeratePropertyEntriesHelperBaseCall': '',
|
| + })
|
| +
|
| + if context.static_prop_ids:
|
| + dict.update({
|
| + 'AddStaticPropertyCount': '*count += NUM_STATIC_PROPERTY_IDS;',
|
| + 'EnumerateStaticPropertyEntries': _enumerate_static_property_entries,
|
| + 'StaticPropertyCount': 'NUM_STATIC_PROPERTY_IDS',
|
| + })
|
| + else:
|
| + dict.update({
|
| + 'AddStaticPropertyCount': '',
|
| + 'EnumerateStaticPropertyEntries': '',
|
| + 'StaticPropertyCount': '0',
|
| + })
|
| + if context.static_method_ids:
|
| + dict.update({
|
| + 'AddStaticMethodCount': '*count += NUM_STATIC_METHOD_IDS;',
|
| + 'EnumerateStaticMethodEntries': _enumerate_static_method_entries,
|
| + 'StaticMethodCount': 'NUM_STATIC_METHOD_IDS',
|
| + })
|
| + else:
|
| + dict.update({
|
| + 'AddStaticMethodCount': '',
|
| + 'EnumerateStaticMethodEntries': '',
|
| + 'StaticMethodCount': '0',
|
| + })
|
| + if context.namespace_list:
|
| + dict.update({
|
| + 'AddNamespaceCount': '*count += NUM_NAMESPACE_IDS;',
|
| + 'EnumerateNamespaceEntries': _enumerate_namespace_entries,
|
| + 'NamespaceCount': 'NUM_NAMESPACE_IDS',
|
| + })
|
| + else :
|
| + dict.update({
|
| + 'AddNamespaceCount': '',
|
| + 'EnumerateNamespaceEntries': '',
|
| + 'NamespaceCount': '0',
|
| + })
|
| + return dict
|
| +
|
| + def Class(self, parent_context, obj):
|
| + """Emits the glue code for a Class definition.
|
| +
|
| + Args:
|
| + parent_context: the code generation context.
|
| + obj: the Class definition.
|
| + """
|
| + if 'private' in obj.attributes or 'protected' in obj.attributes:
|
| + return
|
| +
|
| + binding_model = obj.binding_model
|
| +
|
| + namespace_name = npapi_utils.GetGlueNamespace(obj)
|
| + parent_context.namespace_list.append(obj)
|
| +
|
| + scope = syntax_tree.Namespace(None, [], namespace_name, [])
|
| + scope.parent = parent_context.scope
|
| +
|
| + parent_context.header_section.PushNamespace(namespace_name)
|
| + header_section = parent_context.header_section.CreateSection(namespace_name)
|
| + header_section.needed_defn = parent_context.header_section.needed_defn
|
| + parent_context.header_section.PopNamespace()
|
| +
|
| + parent_context.cpp_section.PushNamespace(namespace_name)
|
| + cpp_section = parent_context.cpp_section.CreateSection(namespace_name)
|
| + cpp_section.needed_glue = parent_context.cpp_section.needed_glue
|
| + parent_context.cpp_section.PopNamespace()
|
| +
|
| + context = self.CodeGenContext(obj, scope, header_section, cpp_section, None)
|
| + header_section.needed_defn.add(obj)
|
| + cpp_section.needed_glue.add(obj)
|
| +
|
| + self.GenerateList(context, obj.defn_list)
|
| +
|
| + class_name_list = naming.SplitWords(obj.name)
|
| + class_capitalized = naming.Capitalized(class_name_list)
|
| + class_param_type, unused_need_defn = binding_model.CppParameterString(scope,
|
| + obj)
|
| + class_mutable_param_type, unused_need_defn = (
|
| + binding_model.CppMutableParameterString(scope, obj))
|
| + binding_glue_header = binding_model.NpapiBindingGlueHeader(scope, obj)
|
| + binding_glue_cpp = binding_model.NpapiBindingGlueCpp(scope, obj)
|
| + function_header, object_access = binding_model.NpapiDispatchFunctionHeader(
|
| + scope, obj, 'object', 'npp', 'success')
|
| + object_non_mutable = binding_model.CppMutableToNonMutable(scope, obj,
|
| + object_access)
|
| + static_dict = {'Class': class_capitalized,
|
| + 'ClassParamType': class_param_type,
|
| + 'ClassMutableParamType': class_mutable_param_type,
|
| + 'Object': object_access,
|
| + 'ObjectNonMutable': object_non_mutable,
|
| + 'BindingGlueCpp': binding_glue_cpp,
|
| + 'BindingGlueHeader': binding_glue_header,
|
| + 'DispatchFunctionHeader': function_header}
|
| +
|
| + enum_dict = self.GetDictForEnumerations(context, obj.base_type)
|
| + if obj.base_type:
|
| + parent_context.cpp_section.needed_glue.add(obj.base_type)
|
| + static_dict['BaseClassNamespace'] = npapi_utils.GetGlueFullNamespace(
|
| + obj.base_type.GetFinalType())
|
| + cpp_template = _class_glue_cpp_base_template.safe_substitute(enum_dict)
|
| + else:
|
| + cpp_template = _class_glue_cpp_no_base_template.safe_substitute(enum_dict)
|
| +
|
| + cpp_template = string.Template(cpp_template).safe_substitute(static_dict)
|
| +
|
| + header_section.EmitCode(
|
| + _class_glue_header_template.safe_substitute(static_dict))
|
| +
|
| + namespace_id_dict = GenNamespaceCode(context)
|
| + parent_context.cpp_section.needed_glue.update(context.namespace_list)
|
| + substitution_dict = {}
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.method_ids, 'method'))
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.static_method_ids, 'static_method'))
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.prop_ids, 'property'))
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.static_prop_ids, 'static_property'))
|
| + substitution_dict.update(namespace_id_dict)
|
| +
|
| + cpp_section.EmitTemplate(string.Template(cpp_template).safe_substitute(
|
| + substitution_dict))
|
| +
|
| + def Verbatim(self, context, obj):
|
| + """Emits the glue code for a Verbatim definition.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + obj: the Verbatim definition.
|
| + """
|
| + if 'verbatim' in obj.attributes:
|
| + if obj.attributes['verbatim'] == 'cpp_glue':
|
| + context.cpp_section.EmitCode(obj.text)
|
| + elif obj.attributes['verbatim'] == 'header_glue':
|
| + context.header_section.EmitCode(obj.text)
|
| +
|
| + def Namespace(self, parent_context, obj):
|
| + """Emits the glue code for a Namespace definition.
|
| +
|
| + Since a namespace can be defined through several Namespace definitions,
|
| + this function doesn't generate all the glue for the namespace until all the
|
| + namespaces definitions have been processed (second pass).
|
| +
|
| + Args:
|
| + parent_context: the code generation context.
|
| + obj: the Namespace definition.
|
| + """
|
| + namespace_name = npapi_utils.GetGlueNamespace(obj)
|
| + # namespaces that span across multiple files are different objects
|
| + # we keep definitions inside the namespace separate, but all the 'static'
|
| + # glue needs to be gathered. So we create a code generation context that
|
| + # will be re-used when a different part of the namespace will be
|
| + # encountered
|
| + # all the different namespaces share the same scope member, so use that as
|
| + # a key into a dict that maps the context
|
| + if obj.scope in self._namespace_map:
|
| + old_context = self._namespace_map[obj.scope]
|
| +
|
| + parent_context.header_section.PushNamespace(namespace_name)
|
| + header_section = parent_context.header_section.CreateSection(
|
| + namespace_name)
|
| + header_section.needed_defn = parent_context.header_section.needed_defn
|
| + parent_context.header_section.PopNamespace()
|
| +
|
| + parent_context.cpp_section.PushNamespace(namespace_name)
|
| + cpp_section = parent_context.cpp_section.CreateSection(namespace_name)
|
| + cpp_section.needed_glue = parent_context.cpp_section.needed_glue
|
| + parent_context.cpp_section.PopNamespace()
|
| +
|
| + context = self.CodeGenContext(old_context.type_defn, old_context.scope,
|
| + header_section, cpp_section, old_context)
|
| + else:
|
| + parent_context.namespace_list.append(obj)
|
| +
|
| + scope = syntax_tree.Namespace(None, [], namespace_name, [])
|
| + scope.parent = parent_context.scope
|
| +
|
| + parent_context.header_section.PushNamespace(namespace_name)
|
| + header_section = parent_context.header_section.CreateSection(
|
| + namespace_name)
|
| + header_section.needed_defn = parent_context.header_section.needed_defn
|
| + parent_context.header_section.PopNamespace()
|
| +
|
| + parent_context.cpp_section.PushNamespace(namespace_name)
|
| + cpp_section = parent_context.cpp_section.CreateSection(namespace_name)
|
| + cpp_section.needed_glue = parent_context.cpp_section.needed_glue
|
| + parent_context.cpp_section.PopNamespace()
|
| +
|
| + context = self.CodeGenContext(obj, scope, header_section,
|
| + cpp_section, None)
|
| + self._namespace_map[obj.scope] = context
|
| +
|
| + def _Finalize():
|
| + # This part can only be finalized after all files have been processed,
|
| + # because later files can still add definitions to the namespace.
|
| + # So do this work in a function that will get called at the end.
|
| + namespace_id_dict = GenNamespaceCode(context)
|
| + parent_context.cpp_section.needed_glue.update(context.namespace_list)
|
| +
|
| + substitution_dict = {}
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.static_method_ids, 'static_method'))
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.static_prop_ids, 'static_property'))
|
| + substitution_dict.update(namespace_id_dict)
|
| +
|
| + header_section.EmitCode(_namespace_glue_header)
|
| +
|
| + enum_dict = self.GetDictForEnumerations(context, False)
|
| + temp_string = _namespace_glue_cpp_template.safe_substitute(enum_dict)
|
| + temp_template = string.Template(temp_string)
|
| +
|
| + cpp_section.EmitTemplate(temp_template.safe_substitute(
|
| + substitution_dict))
|
| +
|
| + self._finalize_functions.append(_Finalize)
|
| +
|
| + context.cpp_section.needed_glue.add(obj)
|
| + self.GenerateList(context, obj.defn_list)
|
| +
|
| + def Typedef(self, context, obj):
|
| + """Emits the glue code for a Typedef definition.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + obj: the Typedef definition.
|
| + """
|
| + # TODO: implement this.
|
| + pass
|
| +
|
| + def Typename(self, context, obj):
|
| + """Emits the glue code for a Typename definition.
|
| +
|
| + Typename being unknown types, no glue is generated for them.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + obj: the Typename definition.
|
| + """
|
| + pass
|
| +
|
| + def GenerateList(self, context, defn_list):
|
| + """Emits the glue code for a list of definitions.
|
| +
|
| + Args:
|
| + context: the code generation context.
|
| + defn_list: the definition list.
|
| + """
|
| + for obj in defn_list:
|
| + if 'nojs' in obj.attributes:
|
| + continue
|
| + if 'include' in obj.attributes:
|
| + context.header_section.needed_defn.add(obj)
|
| + func = getattr(self, obj.defn_type)
|
| + func(context, obj)
|
| +
|
| + def CreateGlueWriters(self, idl_file):
|
| + """Creates CppFileWriter instances for glue header and implementation.
|
| +
|
| + Args:
|
| + idl_file: an idl_parser.File for the source file.
|
| +
|
| + Returns:
|
| + a pair of CppFileWriter, the first being the glue header writer, the
|
| + second one being the glue implementation writer.
|
| + """
|
| + cpp_writer = cpp_utils.CppFileWriter(
|
| + '%s/%s' % (self._output_dir, GetGlueCpp(idl_file)), False)
|
| + for include, system in _cpp_includes:
|
| + cpp_writer.AddInclude(include, system)
|
| + cpp_writer.AddInclude(GetGlueHeader(idl_file), False)
|
| +
|
| + header_writer = cpp_utils.CppFileWriter(
|
| + '%s/%s' % (self._output_dir, GetGlueHeader(idl_file)), True)
|
| + for include, system in _header_includes:
|
| + header_writer.AddInclude(include, system)
|
| + return header_writer, cpp_writer
|
| +
|
| + def CreateGlueSection(self, writer):
|
| + """Utility function to create a 'glue' section in a writer.
|
| +
|
| + This function will create a new section inside a 'glue' namespace.
|
| +
|
| + Args:
|
| + writer: a CppFileWriter in which to create the section.
|
| +
|
| + Returns:
|
| + the created section.
|
| + """
|
| + writer.PushNamespace('glue')
|
| + section = writer.CreateSection('glue')
|
| + writer.PopNamespace()
|
| + return section
|
| +
|
| + def BeginFile(self, idl_file, parent_context, defn_list):
|
| + """Runs the pass 1 generation for an IDL file.
|
| +
|
| + Args:
|
| + idl_file: the source IDL file.
|
| + parent_context: the code generation context.
|
| + defn_list: the list of top-level definitions in the IDL file.
|
| +
|
| + Returns:
|
| + a 3-uple. The first element is the code generation context for that file.
|
| + The second element is the glue header writer. The third element is the
|
| + glue implementation writer.
|
| + """
|
| + header_writer, cpp_writer = self.CreateGlueWriters(idl_file)
|
| + header_writer.needed_defn = set()
|
| + cpp_writer.needed_glue = set()
|
| + header_section = self.CreateGlueSection(header_writer)
|
| + cpp_section = self.CreateGlueSection(cpp_writer)
|
| + header_section.needed_defn = header_writer.needed_defn
|
| + cpp_section.needed_glue = cpp_writer.needed_glue
|
| +
|
| + context = self.CodeGenContext(parent_context.type_defn,
|
| + parent_context.scope, header_section,
|
| + cpp_section, parent_context)
|
| +
|
| + self.GenerateList(context, defn_list)
|
| + return context, header_writer, cpp_writer
|
| +
|
| + def FinishFile(self, idl_file, context, header_writer, cpp_writer):
|
| + """Runs the pass 2 generation for an IDL file.
|
| +
|
| + Args:
|
| + idl_file: the source IDL file.
|
| + context: the code generation context for this file (returned by
|
| + BeginFile)
|
| + header_writer: the glue header writer (returned by BeginFile).
|
| + cpp_writer: the glue implementation writer (returned by BeginFile).
|
| +
|
| + Returns:
|
| + a list of CppFileWriter instances that contain the generated files.
|
| + """
|
| + context = context # silence gpylint
|
| + source_files = (type_defn.GetFinalType().source.file for type_defn in
|
| + cpp_writer.needed_glue)
|
| + cpp_needed_glue_includes = set(GetGlueHeader(source_file) for source_file
|
| + in source_files)
|
| + cpp_needed_glue_includes.add(GetGlueHeader(idl_file))
|
| +
|
| + for include_file in cpp_needed_glue_includes:
|
| + if include_file:
|
| + cpp_writer.AddInclude(include_file)
|
| +
|
| + for include_file in set(type_defn.GetDefinitionInclude() for type_defn
|
| + in header_writer.needed_defn):
|
| + if include_file:
|
| + header_writer.AddInclude(include_file)
|
| +
|
| + return [header_writer, cpp_writer]
|
| +
|
| + def BeginGlobals(self, idl_file, namespace):
|
| + """Runs the pass 1 generation for the global namespace.
|
| +
|
| + A separate files are written containing the global namespace glue.
|
| +
|
| + Args:
|
| + idl_file: an idl_file.File for the global namespace file.
|
| + namespace: the global namespace.
|
| +
|
| + Returns:
|
| + a 3-uple. The first element is the code generation context for that file.
|
| + The second element is the glue header writer. The third element is the
|
| + glue implementation writer.
|
| + """
|
| + scope = syntax_tree.Namespace(None, [], 'glue', [])
|
| + scope.parent = namespace
|
| +
|
| + header_writer, cpp_writer = self.CreateGlueWriters(idl_file)
|
| + header_writer.needed_defn = set()
|
| + cpp_writer.needed_glue = set()
|
| + header_section = self.CreateGlueSection(header_writer)
|
| + cpp_section = self.CreateGlueSection(cpp_writer)
|
| + header_section.needed_defn = header_writer.needed_defn
|
| + cpp_section.needed_glue = cpp_writer.needed_glue
|
| +
|
| + context = self.CodeGenContext(namespace, scope, header_section,
|
| + cpp_section, None)
|
| + return context, header_writer, cpp_writer
|
| +
|
| + def FinishGlobals(self, context, header_writer, cpp_writer):
|
| + """Runs the pass 2 generation for the global namespace.
|
| +
|
| + Args:
|
| + context: the code generation context for the global namespace (returned
|
| + by BeginGlobals).
|
| + header_writer: the glue header writer (returned by BeginGlobals).
|
| + cpp_writer: the glue implementation writer (returned by BeginGlobals).
|
| +
|
| + Returns:
|
| + a list of CppFileWriter instances that contain the generated files.
|
| + """
|
| + for f in self._finalize_functions:
|
| + f()
|
| + namespace_id_dict = GenNamespaceCode(context)
|
| +
|
| + substitution_dict = {}
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.static_method_ids, 'static_method'))
|
| + substitution_dict.update(npapi_utils.MakeIdTableDict(
|
| + context.static_prop_ids, 'static_property'))
|
| + substitution_dict.update(namespace_id_dict)
|
| +
|
| + context.header_section.EmitCode(_namespace_glue_header)
|
| +
|
| + enum_dict = self.GetDictForEnumerations(context, False)
|
| + temp_string = _namespace_glue_cpp_template.safe_substitute(enum_dict)
|
| + temp_template = string.Template(temp_string)
|
| +
|
| + context.cpp_section.EmitTemplate(
|
| + temp_template.safe_substitute(substitution_dict))
|
| +
|
| + context.header_section.EmitCode(_globals_glue_header_tail)
|
| + context.cpp_section.EmitCode(_globals_glue_cpp_tail)
|
| +
|
| + includes = set(GetGlueHeader(ns_obj.source.file) for ns_obj in
|
| + context.namespace_list)
|
| +
|
| + for include_file in includes:
|
| + if include_file is not None:
|
| + cpp_writer.AddInclude(include_file)
|
| +
|
| + return [header_writer, cpp_writer]
|
| +
|
| +
|
| +def ProcessFiles(output_dir, pairs, namespace):
|
| + """Generates the NPAPI glue for all input files.
|
| +
|
| + Args:
|
| + output_dir: the output directory.
|
| + pairs: a list of (idl_parser.File, syntax_tree.Definition list) describing
|
| + the list of top-level definitions in each source file.
|
| + namespace: a syntax_tree.Namespace for the global namespace.
|
| +
|
| + Returns:
|
| + a list of cpp_utils.CppFileWriter, one for each output glue header or
|
| + implementation file.
|
| + """
|
| + globals_file = idl_parser.File('<internal>')
|
| + globals_file.header = None
|
| + globals_file.basename = 'globals'
|
| + generator = NpapiGenerator(output_dir)
|
| +
|
| + # pass 1
|
| + global_context, global_header_writer, global_cpp_writer = (
|
| + generator.BeginGlobals(globals_file, namespace))
|
| + file_map = {}
|
| + for (idl_file, defn) in pairs:
|
| + context, header_writer, cpp_writer = generator.BeginFile(
|
| + idl_file, global_context, defn)
|
| + file_map[idl_file] = (context, header_writer, cpp_writer)
|
| +
|
| + # pass 2
|
| + writer_list = generator.FinishGlobals(global_context, global_header_writer,
|
| + global_cpp_writer)
|
| + for (idl_file, defn) in pairs:
|
| + context, header_writer, cpp_writer = file_map[idl_file]
|
| + writer_list += generator.FinishFile(idl_file, context, header_writer,
|
| + cpp_writer)
|
| + return writer_list
|
| +
|
| +
|
| +def main():
|
| + pass
|
| +
|
| +if __name__ == '__main__':
|
| + main()
|
|
|
| Property changes on: tools/nixysa/nixysa/npapi_generator.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|