You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by ns...@apache.org on 2016/09/25 16:43:13 UTC
[24/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add
possibility to distribute generators separately from thrift core,
and load them dynamically
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin.cc b/compiler/cpp/src/plugin/plugin.cc
deleted file mode 100644
index d969f50..0000000
--- a/compiler/cpp/src/plugin/plugin.cc
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#include "plugin/plugin.h"
-
-#ifdef _WIN32
-#include <fcntl.h>
-#include <io.h>
-#endif
-
-#include <cassert>
-#include <iostream>
-
-#include <boost/bind.hpp>
-#include <boost/range/adaptor/map.hpp>
-#include <boost/range/algorithm/for_each.hpp>
-#include <boost/smart_ptr.hpp>
-
-#include "generate/t_generator.h"
-#include "plugin/type_util.h"
-#include "thrift/protocol/TBinaryProtocol.h"
-#include "thrift/transport/TBufferTransports.h"
-#include "thrift/transport/TFDTransport.h"
-
-#include "plugin/plugin_types.h"
-
-namespace apache {
-namespace thrift {
-namespace plugin {
-
-using apache::thrift::protocol::TBinaryProtocol;
-using apache::thrift::transport::TFDTransport;
-using apache::thrift::transport::TFramedTransport;
-
-#define THRIFT_CONVERT_FORWARD(from_type) \
- template <> \
- typename ToType<from_type>::type* convert_forward<from_type>(const from_type& from)
-
-#define THRIFT_CONVERT_COMPLETE_DECL(from_type) \
- template <> \
- void convert(const from_type& from, ToType<from_type>::type* to)
-
-#define THRIFT_CONVERT_UNARY_DECL(from_type) \
- template <> \
- typename ToType<from_type>::type* convert<from_type>(const from_type& from)
-
-#define THRIFT_CONVERSION_DECL(from_type) \
- THRIFT_CONVERT_FORWARD(from_type); \
- THRIFT_CONVERT_COMPLETE_DECL(from_type); \
- THRIFT_CONVERT_UNARY_DECL(from_type)
-
-#define THRIFT_CONVERT_COMPLETE(from_type) \
- THRIFT_CONVERSION_DECL(from_type) { \
- ToType<from_type>::type* to = convert_forward(from); \
- convert(from, to); \
- return to; \
- } \
- THRIFT_CONVERT_COMPLETE_DECL(from_type)
-
-#define THRIFT_CONVERSION(from_type, ...) \
- THRIFT_CONVERT_FORWARD(from_type) { \
- (void)from; \
- return new ToType<from_type>::type(__VA_ARGS__); \
- } \
- THRIFT_CONVERT_COMPLETE(from_type)
-
-#define THRIFT_ASSIGN_DOC() \
- do { \
- if (from.__isset.doc) \
- to->set_doc(from.doc); \
- } while (0)
-
-#define THRIFT_ASSIGN_ANNOTATIONS() \
- THRIFT_ASSIGN_DOC(); \
- do { \
- if (from.__isset.annotations) \
- to->annotations_ = from.annotations; \
- } while (0)
-
-#define THRIFT_ASSIGN_METADATA() \
- do { \
- to->set_name(from.metadata.name); \
- if (from.metadata.__isset.doc) \
- to->set_doc(from.metadata.doc); \
- if (from.metadata.__isset.annotations) \
- to->annotations_ = from.metadata.annotations; \
- } while (0)
-
-::t_program* g_program = 0;
-
-template <typename C, typename S>
-struct TypeCache {
- C* operator[](const int64_t& k) {
- typename std::map<int64_t, C*>::iterator it = cache.find(k);
- if (it != cache.end()) {
- return it->second;
- } else {
- typename std::map<int64_t, S>::const_iterator cit = source->find(k);
- if (cit == source->end()) {
- throw ThriftPluginError("Type not found");
- }
- return (cache)[k] = convert_forward(cit->second);
- }
- }
-
- void compileAll() {
- boost::for_each(*source | boost::adaptors::map_keys,
- boost::bind(&TypeCache::compile, this, _1));
- }
-
- std::map<int64_t, S> const* source;
-
-protected:
- std::map<int64_t, C*> cache;
-
-private:
- void compile(const int64_t& k) {
- typename std::map<int64_t, S>::const_iterator cit = source->find(k);
- if (cit == source->end()) {
- throw ThriftPluginError("Type not found ");
- }
- convert(cit->second, (*this)[k]);
- }
-};
-std::map<int64_t, ::t_program*> g_program_cache;
-TypeCache< ::t_type, t_type> g_type_cache;
-TypeCache< ::t_const, t_const> g_const_cache;
-TypeCache< ::t_service, t_service> g_service_cache;
-
-void set_global_cache(const TypeRegistry& from) {
- g_type_cache.source = &from.types;
- g_const_cache.source = &from.constants;
- g_service_cache.source = &from.services;
-
- g_type_cache.compileAll();
- g_const_cache.compileAll();
- g_service_cache.compileAll();
-}
-
-template <typename T>
-T* resolve_type(int64_t name) {
- return reinterpret_cast<T*>(g_type_cache[name]);
-}
-
-::t_const* resolve_const(int64_t name) {
- return g_const_cache[name];
-}
-
-::t_service* resolve_service(int64_t name) {
- return g_service_cache[name];
-}
-
-THRIFT_CONVERT_FORWARD(t_base_type) {
-#define T_BASETYPE_CASE(type) \
- case t_base::TYPE_##type: \
- t = ::t_base_type::TYPE_##type; \
- break
-
- ::t_base_type::t_base t = ::t_base_type::TYPE_VOID;
- bool is_binary = false;
- switch (from.value) {
- T_BASETYPE_CASE(VOID);
- T_BASETYPE_CASE(STRING);
- T_BASETYPE_CASE(BOOL);
- T_BASETYPE_CASE(I8);
- T_BASETYPE_CASE(I16);
- T_BASETYPE_CASE(I32);
- T_BASETYPE_CASE(I64);
- T_BASETYPE_CASE(DOUBLE);
- case t_base::TYPE_BINARY:
- t = ::t_base_type::TYPE_STRING;
- is_binary = true;
- break;
- }
- ::t_base_type* to = new ::t_base_type(from.metadata.name, t);
- to->set_binary(is_binary);
- return to;
-#undef T_BASETYPE_CASE
-}
-THRIFT_CONVERT_COMPLETE(t_base_type) {
- THRIFT_ASSIGN_METADATA();
-}
-
-THRIFT_CONVERT_FORWARD(t_typedef) {
- ::t_typedef* to;
- if (from.forward) {
- to = new ::t_typedef(g_program_cache[from.metadata.program_id], from.symbolic, true);
- } else {
- to = new ::t_typedef(g_program_cache[from.metadata.program_id],
- resolve_type< ::t_type>(from.type), from.symbolic);
- }
- return to;
-}
-THRIFT_CONVERT_COMPLETE(t_typedef) {
- THRIFT_ASSIGN_METADATA();
-}
-THRIFT_CONVERSION(t_enum_value, from.name, from.value) {
- assert(to);
- THRIFT_ASSIGN_ANNOTATIONS();
-}
-THRIFT_CONVERSION(t_enum, g_program_cache[from.metadata.program_id]) {
- assert(to);
- THRIFT_ASSIGN_METADATA();
- boost::for_each(from.constants | boost::adaptors::transformed(convert<t_enum_value>),
- boost::bind(&::t_enum::append, to, _1));
-}
-THRIFT_CONVERSION(t_list, resolve_type< ::t_type>(from.elem_type)) {
- assert(to);
- THRIFT_ASSIGN_METADATA();
- if (from.__isset.cpp_name)
- to->set_cpp_name(from.cpp_name);
-}
-THRIFT_CONVERSION(t_set, resolve_type< ::t_type>(from.elem_type)) {
- assert(to);
- THRIFT_ASSIGN_METADATA();
- if (from.__isset.cpp_name)
- to->set_cpp_name(from.cpp_name);
-}
-THRIFT_CONVERSION(t_map,
- resolve_type< ::t_type>(from.key_type),
- resolve_type< ::t_type>(from.val_type)) {
- assert(to);
- THRIFT_ASSIGN_METADATA();
- if (from.__isset.cpp_name)
- to->set_cpp_name(from.cpp_name);
-}
-THRIFT_CONVERSION(t_const_value, ) {
-#define T_CONST_VALUE_CASE(type) \
- if (from.__isset.type##_val) \
- to->set_##type(from.type##_val)
-
- assert(to);
- if (from.__isset.map_val) {
- to->set_map();
- for (std::map<t_const_value, t_const_value>::const_iterator it = from.map_val.begin();
- it != from.map_val.end(); it++) {
- to->add_map(convert(it->first), convert(it->second));
- }
- } else if (from.__isset.list_val) {
- to->set_list();
- boost::for_each(from.list_val | boost::adaptors::transformed(&convert<t_const_value>),
- boost::bind(&::t_const_value::add_list, to, _1));
- } else
- T_CONST_VALUE_CASE(string);
- else T_CONST_VALUE_CASE(integer);
- else T_CONST_VALUE_CASE(double);
- else {
- T_CONST_VALUE_CASE(identifier);
- if (from.__isset.enum_val)
- to->set_enum(resolve_type< ::t_enum>(from.enum_val));
- }
-#undef T_CONST_VALUE_CASE
-}
-THRIFT_CONVERSION(t_field, resolve_type< ::t_type>(from.type), from.name, from.key) {
- assert(to);
- THRIFT_ASSIGN_ANNOTATIONS();
- to->set_reference(from.reference);
- to->set_req(static_cast< ::t_field::e_req>(from.req));
- if (from.__isset.value) {
- to->set_value(convert(from.value));
- }
-}
-THRIFT_CONVERSION(t_struct, g_program_cache[from.metadata.program_id]) {
- assert(to);
- THRIFT_ASSIGN_METADATA();
- to->set_union(from.is_union);
- to->set_xception(from.is_xception);
- boost::for_each(from.members | boost::adaptors::transformed(convert<t_field>),
- boost::bind(&::t_struct::append, to, _1));
-}
-THRIFT_CONVERSION(t_const,
- resolve_type< ::t_type>(from.type),
- from.name,
- convert<t_const_value>(from.value)) {
- assert(to);
- THRIFT_ASSIGN_DOC();
-}
-
-THRIFT_CONVERSION(t_function,
- resolve_type< ::t_type>(from.returntype),
- from.name,
- resolve_type< ::t_struct>(from.arglist),
- resolve_type< ::t_struct>(from.xceptions),
- from.is_oneway) {
- assert(to);
- THRIFT_ASSIGN_DOC();
-}
-
-THRIFT_CONVERSION(t_service, g_program_cache[from.metadata.program_id]) {
- assert(to);
- assert(from.metadata.program_id);
- assert(g_program_cache[from.metadata.program_id]);
- THRIFT_ASSIGN_METADATA();
-
- boost::for_each(from.functions | boost::adaptors::transformed(convert<t_function>),
- boost::bind(&::t_service::add_function, to, _1));
-
- if (from.__isset.extends_)
- to->set_extends(resolve_service(from.extends_));
-}
-
-THRIFT_CONVERT_FORWARD(t_type) {
-#define T_TYPE_CASE_FW_T(case, type) \
- if (from.__isset.case##_val) \
- return convert_forward<type>(from.case##_val)
-#define T_TYPE_CASE_FW(case) T_TYPE_CASE_FW_T(case, t_##case)
-
- T_TYPE_CASE_FW(base_type);
- T_TYPE_CASE_FW(typedef);
- T_TYPE_CASE_FW(enum);
- T_TYPE_CASE_FW(struct);
- T_TYPE_CASE_FW_T(xception, t_struct);
- T_TYPE_CASE_FW(list);
- T_TYPE_CASE_FW(set);
- T_TYPE_CASE_FW(map);
- T_TYPE_CASE_FW(service);
- throw ThriftPluginError("Invalid data: Type union has no value.");
-#undef T_TYPE_CASE_FW_T
-#undef T_TYPE_CASE_FW
-}
-THRIFT_CONVERT_COMPLETE(t_type) {
-#define T_TYPE_CASE_T(case, type) \
- else if (from.__isset.case##_val) \
- convert<type, ::type>(from.case##_val, reinterpret_cast< ::type*>(to))
-#define T_TYPE_CASE(case) T_TYPE_CASE_T(case, t_##case)
-
- if (false) {
- }
- T_TYPE_CASE(base_type);
- T_TYPE_CASE(typedef);
- T_TYPE_CASE(enum);
- T_TYPE_CASE(struct);
- T_TYPE_CASE_T(xception, t_struct);
- T_TYPE_CASE(list);
- T_TYPE_CASE(set);
- T_TYPE_CASE(map);
- T_TYPE_CASE(service);
- else {
- throw ThriftPluginError("Invalid data: Type union has no value.");
- }
-#undef T_TYPE_CASE_T
-#undef T_TYPE_CASE
-}
-
-THRIFT_CONVERSION(t_scope, ) {
- assert(to);
-#define T_SCOPE_RESOLVE(type, name, a) \
- for (std::vector<int64_t>::const_iterator it = from.name##s.begin(); it != from.name##s.end(); \
- it++) { \
- ::t_##type* t = resolve_##type a(*it); \
- to->add_##name(t->get_name(), t); \
- }
- T_SCOPE_RESOLVE(type, type, < ::t_type>);
- T_SCOPE_RESOLVE(const, constant, );
- T_SCOPE_RESOLVE(service, service, );
-#undef T_SCOPE_RESOLVE
-}
-
-THRIFT_CONVERT_FORWARD(t_program) {
- ::t_program* to = new ::t_program(from.path, from.name);
- for (std::vector<t_program>::const_iterator it = from.includes.begin(); it != from.includes.end();
- it++) {
- to->add_include(convert_forward(*it));
- }
- g_program_cache[from.program_id] = to;
- return to;
-}
-THRIFT_CONVERT_COMPLETE(t_program) {
- assert(to);
- g_program = to;
- convert<t_scope, ::t_scope>(from.scope, to->scope());
- THRIFT_ASSIGN_DOC();
-
- to->set_out_path(from.out_path, from.out_path_is_absolute);
-
- boost::for_each(from.typedefs | boost::adaptors::transformed(&resolve_type< ::t_typedef>),
- boost::bind(&::t_program::add_typedef, to, _1));
- boost::for_each(from.enums | boost::adaptors::transformed(&resolve_type< ::t_enum>),
- boost::bind(&::t_program::add_enum, to, _1));
- for (std::vector<int64_t>::const_iterator it = from.objects.begin(); it != from.objects.end();
- it++) {
- ::t_struct* t2 = resolve_type< ::t_struct>(*it);
- if (t2->is_xception()) {
- to->add_xception(t2);
- } else {
- to->add_struct(t2);
- }
- }
- boost::for_each(from.consts | boost::adaptors::transformed(&resolve_const),
- boost::bind(&::t_program::add_const, to, _1));
- boost::for_each(from.services | boost::adaptors::transformed(&resolve_service),
- boost::bind(&::t_program::add_service, to, _1));
-
- for (std::vector<t_program>::const_iterator it = from.includes.begin(); it != from.includes.end();
- it++) {
- convert(*it, g_program_cache[it->program_id]);
- }
- std::for_each(from.c_includes.begin(), from.c_includes.end(),
- boost::bind(&::t_program::add_c_include, to, _1));
- std::for_each(from.cpp_includes.begin(), from.cpp_includes.end(),
- boost::bind(&::t_program::add_cpp_include, to, _1));
- for (std::map<std::string, std::string>::const_iterator it = from.namespaces.begin();
- it != from.namespaces.end(); it++) {
- to->set_namespace(it->first, it->second);
- }
-
- to->set_include_prefix(from.include_prefix);
- to->set_namespace(from.namespace_);
-}
-
-int GeneratorPlugin::exec(int, char* []) {
-#ifdef _WIN32
- _setmode(fileno(stdin), _O_BINARY);
-#endif
- boost::shared_ptr<TFramedTransport> transport(
- new TFramedTransport(boost::make_shared<TFDTransport>(fileno(stdin))));
- TBinaryProtocol proto(transport);
- GeneratorInput input;
- try {
- input.read(&proto);
- } catch (std::exception& err) {
- std::cerr << "Error while receiving plugin data: " << err.what() << std::endl;
- return -1;
- }
- initGlobals();
- ::t_program* p = g_program = convert_forward(input.program);
- set_global_cache(input.type_registry);
- convert(input.program, p);
-
- int ret = generate(p, input.parsed_options);
- clearGlobals();
-
- return ret;
-}
-
-::t_const_value::t_const_value_type const_value_case(const t_const_value& v) {
- if (v.__isset.map_val)
- return ::t_const_value::CV_MAP;
- if (v.__isset.list_val)
- return ::t_const_value::CV_LIST;
- if (v.__isset.string_val)
- return ::t_const_value::CV_STRING;
- if (v.__isset.integer_val)
- return ::t_const_value::CV_INTEGER;
- if (v.__isset.double_val)
- return ::t_const_value::CV_DOUBLE;
- if (v.__isset.identifier_val)
- return ::t_const_value::CV_IDENTIFIER;
- if (v.__isset.enum_val)
- return ::t_const_value::CV_IDENTIFIER;
- throw ThriftPluginError("Unknown const value type");
-}
-
-bool t_const_value::operator<(const t_const_value& that) const {
- ::t_const_value::t_const_value_type t1 = const_value_case(*this);
- ::t_const_value::t_const_value_type t2 = const_value_case(that);
- if (t1 != t2)
- return t1 < t2;
- switch (t1) {
- case ::t_const_value::CV_INTEGER:
- return integer_val < that.integer_val;
- case ::t_const_value::CV_DOUBLE:
- return double_val < that.double_val;
- case ::t_const_value::CV_STRING:
- return string_val < that.string_val;
- case ::t_const_value::CV_MAP:
- if (that.map_val.empty())
- return false;
- else if (map_val.empty())
- return true;
- else
- return map_val.begin()->first < that.map_val.begin()->first;
- case ::t_const_value::CV_LIST:
- if (that.list_val.empty())
- return false;
- else if (list_val.empty())
- return true;
- else
- return list_val.front() < that.list_val.front();
- case ::t_const_value::CV_IDENTIFIER:
- return integer_val < that.integer_val;
- }
- throw ThriftPluginError("Unknown const value type");
-}
-}
-}
-}
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin.h b/compiler/cpp/src/plugin/plugin.h
deleted file mode 100644
index 705cd41..0000000
--- a/compiler/cpp/src/plugin/plugin.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_PLUGIN_PLUGIN_H
-#define T_PLUGIN_PLUGIN_H
-
-#include "thrift/Thrift.h"
-
-class t_program;
-
-namespace apache {
-namespace thrift {
-namespace plugin {
-
-struct ThriftPluginError : public apache::thrift::TException {
- ThriftPluginError(const std::string& msg) : apache::thrift::TException(msg) {}
-};
-
-class GeneratorPlugin {
-public:
- int exec(int argc, char* argv[]);
- virtual int generate(::t_program*, const std::map<std::string, std::string>&) = 0;
-};
-}
-}
-}
-
-#endif
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin.thrift
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin.thrift b/compiler/cpp/src/plugin/plugin.thrift
deleted file mode 100644
index a93873d..0000000
--- a/compiler/cpp/src/plugin/plugin.thrift
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-namespace as3 org.apache.thrift.plugin
-namespace cpp apache.thrift.plugin
-namespace csharp Thrift.Plugin
-namespace d thrift.plugin
-namespace delphi Thrift.Plugin
-namespace erl thrift.plugin
-namespace go thrift
-namespace haxe org.apache.thrift.plugin
-namespace hs Thrift.Plugin
-namespace java org.apache.thrift.plugin
-namespace ocaml Thrift
-namespace perl Thrift.Plugin
-namespace php thrift.plugin
-namespace py thrift.plugin
-namespace rb Thrift
-
-typedef i64 t_program_id
-typedef i64 t_type_id
-typedef i64 t_const_id
-typedef i64 t_service_id
-
-enum t_base {
- TYPE_VOID
- TYPE_STRING
- TYPE_BOOL
- TYPE_I8
- TYPE_I16
- TYPE_I32
- TYPE_I64
- TYPE_DOUBLE
- TYPE_BINARY
-}
-
-struct TypeMetadata {
- 1: required string name
- 2: required t_program_id program_id
- 99: optional map<string, string> annotations
- 100: optional string doc
-}
-
-struct t_base_type {
- 1: required TypeMetadata metadata
- 2: required t_base value
-}
-
-struct t_list {
- 1: required TypeMetadata metadata
- 2: optional string cpp_name
- 3: required t_type_id elem_type
-}
-
-struct t_set {
- 1: required TypeMetadata metadata
- 2: optional string cpp_name
- 3: required t_type_id elem_type
-}
-
-struct t_map {
- 1: required TypeMetadata metadata
- 2: optional string cpp_name
- 3: required t_type_id key_type
- 4: required t_type_id val_type
-}
-
-struct t_typedef {
- 1: required TypeMetadata metadata
- 2: required t_type_id type
- 3: required string symbolic
- 4: required bool forward
-}
-
-struct t_enum_value {
- 1: required string name
- 2: required i32 value
- 99: optional map<string, string> annotations
- 100: optional string doc
-}
-struct t_enum {
- 1: required TypeMetadata metadata
- 2: required list<t_enum_value> constants
-}
-
-enum Requiredness {
- T_REQUIRED = 0
- T_OPTIONAL = 1
- T_OPT_IN_REQ_OUT = 2
-}
-
-union t_const_value {
- 1: optional map<t_const_value, t_const_value> map_val
- 2: optional list<t_const_value> list_val
- 3: optional string string_val
- 4: optional i64 integer_val
- 5: optional double double_val
- 6: optional string identifier_val
- 7: optional t_type_id enum_val
-}
-struct t_const {
- 1: required string name
- 2: required t_type_id type
- 3: required t_const_value value
- 100: optional string doc
-}
-struct t_struct {
- 1: required TypeMetadata metadata
- 2: required list<t_field> members
- 3: required bool is_union
- 4: required bool is_xception
-}
-struct t_field {
- 1: required string name
- 2: required t_type_id type
- 3: required i32 key
- 4: required Requiredness req
- 5: optional t_const_value value
- 10: required bool reference
- 99: optional map<string, string> annotations
- 100: optional string doc
-}
-struct t_function {
- 1: required string name
- 2: required t_type_id returntype
- 3: required t_type_id arglist
- 4: required t_type_id xceptions
- 5: required bool is_oneway
- 100: optional string doc
-}
-struct t_service {
- 1: required TypeMetadata metadata
- 2: required list<t_function> functions
- 3: optional t_service_id extends_
-}
-union t_type {
- 1: optional t_base_type base_type_val
- 2: optional t_typedef typedef_val
- 3: optional t_enum enum_val
- 4: optional t_struct struct_val
- 5: optional t_struct xception_val
- 6: optional t_list list_val
- 7: optional t_set set_val
- 8: optional t_map map_val
- 9: optional t_service service_val
-}
-struct t_scope {
- 1: required list<t_type_id> types
- 2: required list<t_const_id> constants
- 3: required list<t_service_id> services
-}
-
-struct TypeRegistry {
- 1: required map<t_type_id, t_type> types
- 2: required map<t_const_id, t_const> constants
- 3: required map<t_service_id, t_service> services
-}
-
-struct t_program {
- 1: required string name
- 2: required t_program_id program_id
- 3: required string path
- 4: required string namespace_
- 5: required string out_path
- 6: required bool out_path_is_absolute
- 8: required list<t_program> includes
- 9: required string include_prefix
- 10: required t_scope scope
-
- 11: required list<t_type_id> typedefs
- 12: required list<t_type_id> enums
- 13: required list<t_const_id> consts
- 14: required list<t_type_id> objects
- 15: required list<t_service_id> services
-
- 16: required map<string, string> namespaces
- 17: required list<string> cpp_includes
- 18: required list<string> c_includes
- 100: optional string doc
-}
-
-struct GeneratorInput {
- 1: required t_program program
- 2: required TypeRegistry type_registry
- 3: required map<string, string> parsed_options
-}
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin_output.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin_output.cc b/compiler/cpp/src/plugin/plugin_output.cc
deleted file mode 100644
index 1ab015e..0000000
--- a/compiler/cpp/src/plugin/plugin_output.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifdef _WIN32
-#include <cstdio>
-#include <fcntl.h>
-#include <io.h>
-#include <iostream>
-#define THRIFT_POPEN(cmd) _popen(cmd, "wb")
-#define THRIFT_PCLOSE _pclose
-#else
-#define THRIFT_POPEN(cmd) popen(cmd, "w")
-#define THRIFT_PCLOSE pclose
-#endif
-
-#include "plugin/plugin_output.h"
-
-#include <boost/range/adaptor/map.hpp>
-#include <boost/range/algorithm/copy.hpp>
-#include <boost/range/algorithm/transform.hpp>
-#include <boost/smart_ptr.hpp>
-
-#include "generate/t_generator.h"
-#include "plugin/plugin.h"
-#include "plugin/type_util.h"
-#include "thrift/protocol/TBinaryProtocol.h"
-#include "thrift/transport/TBufferTransports.h"
-#include "thrift/transport/TFDTransport.h"
-
-#include "plugin/plugin_types.h"
-
-namespace plugin_output {
-
-template <typename From>
-typename apache::thrift::plugin::ToType<From>::type convert(From* from) {
- typename apache::thrift::plugin::ToType<From>::type to;
- convert(from, to);
- return to;
-}
-
-using apache::thrift::protocol::TBinaryProtocol;
-using apache::thrift::transport::TFDTransport;
-using apache::thrift::transport::TFramedTransport;
-
-using namespace apache::thrift;
-
-#define THRIFT_CONVERSION_N(from_type, to_type) \
- template <> \
- void convert<from_type, to_type>(from_type * from, to_type & to)
-#define THRIFT_CONVERSION(type) THRIFT_CONVERSION_N(::type, plugin::type)
-
-#define THRIFT_ASSIGN_N(from_name, to_name, prefix) \
- do { \
- if (from) \
- to.__set_##to_name(prefix(from->from_name)); \
- } while (0)
-
-#define THRIFT_ASSIGN(name) THRIFT_ASSIGN_N(get_##name(), name, )
-#define THRIFT_ASSIGN_CONVERT(type, from_name, to_name) \
- do { \
- if (from && from->from_name) { \
- to.__set_##to_name(convert(from->from_name)); \
- } \
- } while (0)
-
-#define THRIFT_ASSIGN_OPT(name) \
- do { \
- if (from->has_##name()) \
- THRIFT_ASSIGN(name); \
- } while (0)
-
-#define THRIFT_ASSIGN_LIST_N(type, from_name, to_name) \
- do { \
- if (from && !from->from_name.empty()) { \
- std::transform(from->from_name.begin(), \
- from->from_name.end(), \
- std::back_inserter(to.to_name), \
- convert< ::type>); \
- } \
- } while (0)
-
-#define THRIFT_ASSIGN_METADATA() convert(reinterpret_cast<t_type*>(from), to.metadata)
-
-// To avoid multiple instances of same type, t_type, t_const and t_service are stored in one place
-// and referenced by ID.
-template <typename T>
-struct TypeCache {
- typedef typename plugin::ToType<T>::type to_type;
- std::map<int64_t, to_type> cache;
-
- template <typename T2>
- int64_t store(T2* t) {
- intptr_t id = reinterpret_cast<intptr_t>(t);
- if (id) {
- typename std::map<int64_t, to_type>::iterator it = cache.find(id);
- if (it == cache.end()) {
- // HACK: fake resolve for recursive type
- cache.insert(std::make_pair(id, to_type()));
- // overwrite with true value
- cache[id] = convert(t);
- }
- }
- return static_cast<int64_t>(id);
- }
-
- void clear() { cache.clear(); }
-};
-
-template <typename T>
-int64_t store_type(T* t);
-
-#define T_STORE(type) \
- TypeCache<t_##type> type##_cache; \
- template <> \
- plugin::t_##type##_id store_type<t_##type>(t_##type * t) { \
- return type##_cache.store<t_##type>(t); \
- }
-T_STORE(type)
-T_STORE(const)
-T_STORE(service)
-#undef T_STORE
-
-#define THRIFT_ASSIGN_ID_N(t, from_name, to_name) \
- do { \
- if (from && from->from_name) \
- to.__set_##to_name(store_type<t>(from->from_name)); \
- } while (0)
-
-#define THRIFT_ASSIGN_ID(name) THRIFT_ASSIGN_ID_N(t_type, get_##name(), name)
-
-#define THRIFT_ASSIGN_LIST_ID(t, name) \
- do { \
- if (from && !from->get_##name##s().empty()) { \
- std::transform(from->get_##name##s().begin(), \
- from->get_##name##s().end(), \
- std::back_inserter(to.name##s), \
- &store_type<t>); \
- } \
- } while (0)
-
-THRIFT_CONVERSION_N(::t_type, plugin::TypeMetadata) {
- to.program_id = reinterpret_cast<int64_t>(from->get_program());
- THRIFT_ASSIGN_N(annotations_, annotations, );
- if (from->has_doc()) {
- to.__set_doc(from->get_doc());
- }
- THRIFT_ASSIGN(name);
-}
-
-THRIFT_CONVERSION(t_typedef) {
- THRIFT_ASSIGN_METADATA();
- THRIFT_ASSIGN_ID(type);
- THRIFT_ASSIGN(symbolic);
- THRIFT_ASSIGN_N(is_forward_typedef(), forward, );
-}
-
-THRIFT_CONVERSION(t_enum_value) {
- THRIFT_ASSIGN_OPT(doc);
- THRIFT_ASSIGN(name);
- THRIFT_ASSIGN(value);
-}
-
-THRIFT_CONVERSION(t_enum) {
- THRIFT_ASSIGN_METADATA();
- THRIFT_ASSIGN_LIST_N(t_enum_value, get_constants(), constants);
-}
-
-THRIFT_CONVERSION(t_const_value) {
- switch (from->get_type()) {
- case t_const_value::CV_INTEGER:
- THRIFT_ASSIGN_N(get_integer(), integer_val, );
- break;
- case t_const_value::CV_DOUBLE:
- THRIFT_ASSIGN_N(get_double(), double_val, );
- break;
- case t_const_value::CV_STRING:
- THRIFT_ASSIGN_N(get_string(), string_val, );
- break;
- case t_const_value::CV_IDENTIFIER:
- THRIFT_ASSIGN_ID_N(t_type, enum_, enum_val);
- THRIFT_ASSIGN_N(get_identifier(), identifier_val, );
- break;
- case t_const_value::CV_MAP:
- to.__isset.map_val = true;
- if (from && !from->get_map().empty()) {
- for (std::map< ::t_const_value*, ::t_const_value*>::const_iterator it
- = from->get_map().begin();
- it != from->get_map().end();
- it++) {
- to.map_val.insert(std::make_pair(convert(it->first), convert(it->second)));
- }
- }
- break;
- case t_const_value::CV_LIST:
- to.__isset.list_val = true;
- THRIFT_ASSIGN_LIST_N(t_const_value, get_list(), list_val);
- break;
- default:
- throw plugin::ThriftPluginError("const value has no value");
- }
-}
-THRIFT_CONVERSION(t_const) {
- THRIFT_ASSIGN_OPT(doc);
- THRIFT_ASSIGN(name);
- THRIFT_ASSIGN_ID(type);
- THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value);
-}
-THRIFT_CONVERSION(t_field) {
- THRIFT_ASSIGN_OPT(doc);
- THRIFT_ASSIGN(name);
- THRIFT_ASSIGN(key);
- THRIFT_ASSIGN_N(get_req(), req, (plugin::Requiredness::type));
- THRIFT_ASSIGN(reference);
- THRIFT_ASSIGN_ID(type);
- THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value);
-}
-THRIFT_CONVERSION(t_struct) {
- THRIFT_ASSIGN_METADATA();
- THRIFT_ASSIGN_LIST_N(t_field, get_members(), members);
- THRIFT_ASSIGN_N(is_union(), is_union, );
- THRIFT_ASSIGN_N(is_xception(), is_xception, );
-}
-THRIFT_CONVERSION(t_function) {
- THRIFT_ASSIGN_OPT(doc);
- THRIFT_ASSIGN(name);
- THRIFT_ASSIGN_ID(returntype);
- THRIFT_ASSIGN_N(is_oneway(), is_oneway, );
- THRIFT_ASSIGN_ID(arglist);
- THRIFT_ASSIGN_ID(xceptions);
-}
-
-THRIFT_CONVERSION(t_list) {
- THRIFT_ASSIGN_METADATA();
- THRIFT_ASSIGN_OPT(cpp_name);
- THRIFT_ASSIGN_ID(elem_type);
-}
-THRIFT_CONVERSION(t_set) {
- THRIFT_ASSIGN_METADATA();
- THRIFT_ASSIGN_OPT(cpp_name);
- THRIFT_ASSIGN_ID(elem_type);
-}
-THRIFT_CONVERSION(t_map) {
- THRIFT_ASSIGN_METADATA();
- THRIFT_ASSIGN_OPT(cpp_name);
- THRIFT_ASSIGN_ID(key_type);
- THRIFT_ASSIGN_ID(val_type);
-}
-
-THRIFT_CONVERSION(t_service) {
- THRIFT_ASSIGN_METADATA();
- THRIFT_ASSIGN_LIST_N(t_function, get_functions(), functions);
- THRIFT_ASSIGN_ID_N(t_service, get_extends(), extends_);
-}
-
-THRIFT_CONVERSION(t_base_type) {
- THRIFT_ASSIGN_METADATA();
- if (from->is_binary()) {
- to.value = plugin::t_base::TYPE_BINARY;
- } else {
- switch (from->get_base()) {
-#define T_BASETYPE_CASE(name) \
- case t_base_type::TYPE_##name: \
- to.value = plugin::t_base::TYPE_##name; \
- break
- T_BASETYPE_CASE(VOID);
- T_BASETYPE_CASE(STRING);
- T_BASETYPE_CASE(BOOL);
- T_BASETYPE_CASE(I8);
- T_BASETYPE_CASE(I16);
- T_BASETYPE_CASE(I32);
- T_BASETYPE_CASE(I64);
- T_BASETYPE_CASE(DOUBLE);
- default:
- throw plugin::ThriftPluginError("Base type union has no value");
- break;
-#undef T_BASETYPE_CASE
- }
- }
-}
-THRIFT_CONVERSION(t_type) {
-#define T_CONVERT_UNION_N(name, type) \
- else if (from->is_##name()) { \
- to.__isset.name##_val = true; \
- convert(reinterpret_cast< ::type*>(from), to.name##_val); \
- }
-#define T_CONVERT_UNION(name) T_CONVERT_UNION_N(name, t_##name)
- if (false) {
- }
- T_CONVERT_UNION(base_type)
- T_CONVERT_UNION(typedef)
- T_CONVERT_UNION(enum)
- T_CONVERT_UNION(struct)
- T_CONVERT_UNION_N(xception, t_struct)
- T_CONVERT_UNION(list)
- T_CONVERT_UNION(set)
- T_CONVERT_UNION(map)
- T_CONVERT_UNION(service)
- else {
- throw plugin::ThriftPluginError("Type union has no value");
- }
-#undef T_CONVERT_UNION_N
-#undef T_CONVERT_UNION
-}
-
-THRIFT_CONVERSION(t_scope) {
-#define T_SCOPE_ASSIGN(name, type) \
- boost::copy(from->name##s_ | boost::adaptors::map_values \
- | boost::adaptors::transformed(&store_type<type>), \
- std::back_inserter(to.name##s))
- T_SCOPE_ASSIGN(type, t_type);
- T_SCOPE_ASSIGN(constant, t_const);
- T_SCOPE_ASSIGN(service, t_service);
-#undef T_SCOPE_ASSIGN
-}
-
-void get_global_cache(plugin::TypeRegistry& reg) {
- reg.types = type_cache.cache;
- reg.constants = const_cache.cache;
- reg.services = service_cache.cache;
-}
-
-void clear_global_cache() {
- type_cache.clear();
- const_cache.clear();
- service_cache.clear();
-}
-
-THRIFT_CONVERSION(t_program) {
- THRIFT_ASSIGN_CONVERT(t_scope, scope(), scope);
- THRIFT_ASSIGN(path);
- THRIFT_ASSIGN(out_path);
- THRIFT_ASSIGN(name);
- THRIFT_ASSIGN(include_prefix);
- THRIFT_ASSIGN(cpp_includes);
- THRIFT_ASSIGN(c_includes);
- THRIFT_ASSIGN(namespaces);
- THRIFT_ASSIGN_N(is_out_path_absolute(), out_path_is_absolute, );
- THRIFT_ASSIGN_N(get_namespace(), namespace_, );
- THRIFT_ASSIGN_LIST_ID(t_type, typedef);
- THRIFT_ASSIGN_LIST_ID(t_type, enum);
- THRIFT_ASSIGN_LIST_ID(t_type, object);
- THRIFT_ASSIGN_LIST_ID(t_const, const);
- THRIFT_ASSIGN_LIST_ID(t_service, service);
- THRIFT_ASSIGN_LIST_N(t_program, get_includes(), includes);
- to.program_id = reinterpret_cast<plugin::t_program_id>(from);
-}
-
-PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options) {
- std::string language;
- std::map<std::string, std::string> parsed_options;
- t_generator::parse_options(options, language, parsed_options);
- std::string cmd = "thrift-gen-";
- if (language.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-0123456789")
- != std::string::npos) {
- std::cerr << "Invalid language name" << std::endl;
- return PLUGIN_FAILURE;
- }
- cmd.append(language);
- FILE* fd = THRIFT_POPEN(cmd.c_str());
- if (fd) {
-#ifdef _WIN32
- _setmode(fileno(fd), _O_BINARY);
-#endif
- boost::shared_ptr<TFramedTransport> transport(
- new TFramedTransport(boost::make_shared<TFDTransport>(fileno(fd))));
- TBinaryProtocol proto(transport);
-
- plugin::GeneratorInput input;
- input.__set_parsed_options(parsed_options);
- clear_global_cache();
- convert(program, input.program);
- get_global_cache(input.type_registry);
- try {
- input.write(&proto);
- transport->flush();
- } catch (std::exception& err) {
- std::cerr << "Error while sending data to plugin: " << err.what() << std::endl;
- THRIFT_PCLOSE(fd);
- return PLUGIN_FAILURE;
- }
-
- // TODO: be prepared for hang or crash of child process
- int ret = THRIFT_PCLOSE(fd);
- if (!ret) {
- return PLUGIN_SUCCEESS;
- } else {
- std::cerr << "plugin process returned non zero exit code: " << ret << std::endl;
- return PLUGIN_FAILURE;
- }
- }
- clear_global_cache();
- return PLUGIN_NOT_FOUND;
-}
-}
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/plugin_output.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/plugin_output.h b/compiler/cpp/src/plugin/plugin_output.h
deleted file mode 100644
index eab2d1b..0000000
--- a/compiler/cpp/src/plugin/plugin_output.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_PLUGIN_PLUGIN_OUTPUT_H
-#define T_PLUGIN_PLUGIN_OUTPUT_H
-
-#include <string>
-
-class t_program;
-
-namespace plugin_output {
-
-enum PluginDelegateResult {
- PLUGIN_NOT_FOUND,
- PLUGIN_FAILURE,
- PLUGIN_SUCCEESS,
-};
-
-PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options);
-}
-
-#endif
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/plugin/type_util.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/plugin/type_util.h b/compiler/cpp/src/plugin/type_util.h
deleted file mode 100644
index 508b741..0000000
--- a/compiler/cpp/src/plugin/type_util.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-#ifndef T_PLUGIN_TYPE_UTIL_H
-#define T_PLUGIN_TYPE_UTIL_H
-
-namespace apache {
-namespace thrift {
-namespace plugin {
-
-template <typename From>
-struct ToType {};
-
-template <typename From>
-typename ToType<From>::type* convert_forward(const From&);
-
-template <typename From, typename To>
-void convert(const From&, To*);
-
-template <typename From>
-typename ToType<From>::type* convert(const From& from);
-
-class TypeRegistry;
-void set_global_cache(const TypeRegistry&);
-}
-}
-}
-
-// conversion from raw compiler types to plugin wire type
-namespace plugin_output {
-
-template <typename From, typename To>
-void convert(From* from, To& to);
-
-template <typename From>
-typename apache::thrift::plugin::ToType<From>::type convert(From* from);
-
-void get_global_cache(apache::thrift::plugin::TypeRegistry&);
-void clear_global_cache();
-}
-
-#define THRIFT_TYPE_MAPPING(TYPE) \
- class TYPE; \
- namespace apache { \
- namespace thrift { \
- namespace plugin { \
- class TYPE; \
- template <> \
- struct ToType< ::TYPE> { \
- typedef TYPE type; \
- }; \
- template <> \
- struct ToType<TYPE> { \
- typedef ::TYPE type; \
- }; \
- } \
- } \
- }
-THRIFT_TYPE_MAPPING(t_base_type)
-THRIFT_TYPE_MAPPING(t_const)
-THRIFT_TYPE_MAPPING(t_const_value)
-THRIFT_TYPE_MAPPING(t_container)
-THRIFT_TYPE_MAPPING(t_doc)
-THRIFT_TYPE_MAPPING(t_enum)
-THRIFT_TYPE_MAPPING(t_enum_value)
-THRIFT_TYPE_MAPPING(t_field)
-THRIFT_TYPE_MAPPING(t_function)
-THRIFT_TYPE_MAPPING(t_list)
-THRIFT_TYPE_MAPPING(t_map)
-THRIFT_TYPE_MAPPING(t_program)
-THRIFT_TYPE_MAPPING(t_scope)
-THRIFT_TYPE_MAPPING(t_service)
-THRIFT_TYPE_MAPPING(t_set)
-THRIFT_TYPE_MAPPING(t_struct)
-THRIFT_TYPE_MAPPING(t_type)
-THRIFT_TYPE_MAPPING(t_typedef)
-#undef THRIFT_TYPE_MAPPING
-#endif
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/audit/t_audit.cpp
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/audit/t_audit.cpp b/compiler/cpp/src/thrift/audit/t_audit.cpp
new file mode 100644
index 0000000..1386f3b
--- /dev/null
+++ b/compiler/cpp/src/thrift/audit/t_audit.cpp
@@ -0,0 +1,464 @@
+
+#include <cassert>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+
+// Careful: must include globals first for extern definitions
+#include "thrift/globals.h"
+
+#include "thrift/parse/t_program.h"
+#include "thrift/parse/t_scope.h"
+#include "thrift/parse/t_const.h"
+#include "thrift/parse/t_field.h"
+
+#include "thrift/version.h"
+
+#include "thrift/audit/t_audit.h"
+
+extern int g_warn;
+extern std::string g_curpath;
+extern bool g_return_failure;
+
+void thrift_audit_warning(int level, const char* fmt, ...) {
+ if (g_warn < level) {
+ return;
+ }
+ va_list args;
+ printf("[Thrift Audit Warning:%s] ", g_curpath.c_str());
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ printf("\n");
+}
+
+void thrift_audit_failure(const char* fmt, ...) {
+ va_list args;
+ fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str());
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ g_return_failure = true;
+}
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram)
+{
+ const std::map<std::string, std::string>& newNamespaceMap = newProgram->get_all_namespaces();
+ const std::map<std::string, std::string>& oldNamespaceMap = oldProgram->get_all_namespaces();
+
+ for(std::map<std::string, std::string>::const_iterator oldNamespaceMapIt = oldNamespaceMap.begin();
+ oldNamespaceMapIt != oldNamespaceMap.end();
+ oldNamespaceMapIt++)
+ {
+ std::map<std::string, std::string>::const_iterator newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first);
+ if(newNamespaceMapIt == newNamespaceMap.end())
+ {
+ thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str());
+ }
+ else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second)
+ {
+ thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt->second).c_str());
+ }
+ }
+}
+
+void compare_enum_values(t_enum* newEnum,t_enum* oldEnum)
+{
+ const std::vector<t_enum_value*>& oldEnumValues = oldEnum->get_constants();
+ for(std::vector<t_enum_value*>::const_iterator oldEnumValuesIt = oldEnumValues.begin();
+ oldEnumValuesIt != oldEnumValues.end();
+ oldEnumValuesIt++)
+ {
+ int enumValue = (*oldEnumValuesIt)->get_value();
+ t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue);
+ if(newEnumValue != NULL)
+ {
+ std::string enumName = (*oldEnumValuesIt)->get_name();
+ if(enumName != newEnumValue->get_name())
+ {
+ thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str());
+ }
+ }
+ else
+ {
+ thrift_audit_failure("Enum value %d missing in %s\n", enumValue, oldEnum->get_name().c_str());
+ }
+
+ }
+}
+
+void compare_enums(const std::vector<t_enum*>& newEnumList, const std::vector<t_enum*>& oldEnumList)
+{
+ std::map<std::string,t_enum*> newEnumMap;
+ std::vector<t_enum*>::const_iterator newEnumIt;
+ for(newEnumIt = newEnumList.begin(); newEnumIt != newEnumList.end(); newEnumIt++)
+ {
+ newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt;
+ }
+ std::vector<t_enum*>::const_iterator oldEnumIt;
+ for(oldEnumIt = oldEnumList.begin(); oldEnumIt != oldEnumList.end(); oldEnumIt++)
+ {
+ std::map<std::string,t_enum*>::iterator newEnumMapIt;
+ newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name());
+
+ if(newEnumMapIt == newEnumMap.end())
+ {
+ thrift_audit_warning(1, "Enum %s not found in new thrift file\n",(*oldEnumIt)->get_name().c_str());
+ }
+ else
+ {
+ compare_enum_values(newEnumMapIt->second, *oldEnumIt);
+ }
+ }
+}
+
+//This function returns 'true' if the two arguements are of same types.
+//Returns false if they are of different type
+bool compare_type(t_type* newType, t_type* oldType)
+{
+ //Comparing names of two types will work when the newType and oldType are basic types or structs or enums.
+ //However, when they are containers, get_name() returns empty for which we have to compare the type of
+ //their elements as well.
+ if((newType->get_name()).empty() && (oldType->get_name()).empty())
+ {
+
+ if(newType->is_list() && oldType->is_list())
+ {
+ t_type* newElementType = ((t_list*)newType)->get_elem_type();
+ t_type* oldElementType = ((t_list*)oldType)->get_elem_type();
+ return compare_type(newElementType, oldElementType);
+ }
+ else if(newType->is_map() && oldType->is_map())
+ {
+ t_type* newKeyType = ((t_map*)newType)->get_key_type();
+ t_type* oldKeyType = ((t_map*)oldType)->get_key_type();
+
+ t_type* newValType = ((t_map*)newType)->get_val_type();
+ t_type* oldValType = ((t_map*)oldType)->get_val_type();
+
+ return (compare_type(newKeyType, oldKeyType) && compare_type(newValType, oldValType));
+ }
+ else if(newType->is_set() && oldType->is_set())
+ {
+ t_type* newElementType = ((t_set*)newType)->get_elem_type();
+ t_type* oldElementType = ((t_set*)oldType)->get_elem_type();
+ return compare_type(newElementType, oldElementType);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if(newType->get_name() == oldType->get_name())
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool compare_pair(std::pair<t_const_value*, t_const_value*> newMapPair, std::pair<t_const_value*, t_const_value*> oldMapPair)
+{
+ return compare_defaults(newMapPair.first, oldMapPair.first) && compare_defaults(newMapPair.second, oldMapPair.second);
+}
+
+// This function returns 'true' if the default values are same. Returns false if they are different.
+bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault)
+{
+ if(newStructDefault == NULL && oldStructDefault == NULL) return true;
+ else if(newStructDefault == NULL && oldStructDefault != NULL) return false;
+ else if (newStructDefault != NULL && oldStructDefault == NULL) return false;
+
+ if(newStructDefault->get_type() != oldStructDefault->get_type())
+ {
+ return false;
+ }
+
+ switch(newStructDefault->get_type())
+ {
+ case t_const_value::CV_INTEGER:
+ return (newStructDefault->get_integer() == oldStructDefault->get_integer());
+ case t_const_value::CV_DOUBLE:
+ return (newStructDefault->get_double() == oldStructDefault->get_double());
+ case t_const_value::CV_STRING:
+ return (newStructDefault->get_string() == oldStructDefault->get_string());
+ case t_const_value::CV_LIST:
+ {
+ const std::vector<t_const_value*>& oldDefaultList = oldStructDefault->get_list();
+ const std::vector<t_const_value*>& newDefaultList = newStructDefault->get_list();
+ bool defaultValuesCompare = (oldDefaultList.size() == newDefaultList.size());
+
+ return defaultValuesCompare && std::equal(newDefaultList.begin(), newDefaultList.end(), oldDefaultList.begin(), compare_defaults);
+ }
+ case t_const_value::CV_MAP:
+ {
+ const std::map<t_const_value*, t_const_value*> newMap = newStructDefault->get_map();
+ const std::map<t_const_value*, t_const_value*> oldMap = oldStructDefault->get_map();
+
+ bool defaultValuesCompare = (oldMap.size() == newMap.size());
+
+ return defaultValuesCompare && std::equal(newMap.begin(), newMap.end(), oldMap.begin(), compare_pair);
+ }
+ case t_const_value::CV_IDENTIFIER:
+ return (newStructDefault->get_identifier() == oldStructDefault->get_identifier());
+ default:
+ return false;
+ }
+
+}
+
+void compare_struct_field(t_field* newField, t_field* oldField, std::string oldStructName)
+{
+ t_type* newFieldType = newField->get_type();
+ t_type* oldFieldType = oldField->get_type();
+ if(!compare_type(newFieldType, oldFieldType))
+ {
+ thrift_audit_failure("Struct Field Type Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+ }
+
+ // A Struct member can be optional if it is mentioned explicitly, or if it is assigned with default values.
+ bool newStructFieldOptional = (newField->get_req() != t_field::T_REQUIRED);
+ bool oldStructFieldOptional = (oldField->get_req() != t_field::T_REQUIRED);
+
+ if(newStructFieldOptional != oldStructFieldOptional)
+ {
+ thrift_audit_failure("Struct Field Requiredness Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+ }
+ if(newStructFieldOptional || oldStructFieldOptional)
+ {
+ if(!compare_defaults(newField->get_value(), oldField->get_value()))
+ {
+ thrift_audit_warning(1, "Default value changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str());
+ }
+ }
+
+ std::string fieldName = newField->get_name();
+ if(fieldName != oldField->get_name())
+ {
+ thrift_audit_warning(1, "Struct field name changed for Id = %d in %s\n", newField->get_key(), oldStructName.c_str());
+ }
+
+}
+
+void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std::string& oldStructName = std::string())
+{
+ std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName;
+ const std::vector<t_field*>& oldStructMembersInIdOrder = oldStruct->get_sorted_members();
+ const std::vector<t_field*>& newStructMembersInIdOrder = newStruct->get_sorted_members();
+ std::vector<t_field*>::const_iterator oldStructMemberIt = oldStructMembersInIdOrder.begin();
+ std::vector<t_field*>::const_iterator newStructMemberIt = newStructMembersInIdOrder.begin();
+
+ // Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member
+ // lists together.
+ while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() && newStructMemberIt == newStructMembersInIdOrder.end()))
+ {
+ if(newStructMemberIt == newStructMembersInIdOrder.end() && oldStructMemberIt != oldStructMembersInIdOrder.end())
+ {
+ // A field ID has been removed from the end.
+ thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
+ oldStructMemberIt++;
+ }
+ else if(newStructMemberIt != newStructMembersInIdOrder.end() && oldStructMemberIt == oldStructMembersInIdOrder.end())
+ {
+ //New field ID has been added to the end.
+ if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED)
+ {
+ thrift_audit_failure("Required Struct Field Added for Id = %d in %s \n", (*newStructMemberIt)->get_key(), structName.c_str());
+ }
+ newStructMemberIt++;
+ }
+ else if((*newStructMemberIt)->get_key() == (*oldStructMemberIt)->get_key())
+ {
+ //Field ID found in both structs. Compare field types, default values.
+ compare_struct_field(*newStructMemberIt, *oldStructMemberIt, structName);
+
+ newStructMemberIt++;
+ oldStructMemberIt++;
+ }
+ else if((*newStructMemberIt)->get_key() < (*oldStructMemberIt)->get_key())
+ {
+ //New Field Id is inserted in between
+ //Adding fields to struct is fine, but adding them in the middle is suspicious. Error!!
+ thrift_audit_failure("Struct field is added in the middle with Id = %d in %s\n", (*newStructMemberIt)->get_key(), structName.c_str());
+ newStructMemberIt++;
+ }
+ else if((*newStructMemberIt)->get_key() > (*oldStructMemberIt)->get_key())
+ {
+ //A field is deleted in newStruct.
+ thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str());
+ oldStructMemberIt++;
+ }
+
+ }
+}
+
+void compare_structs(const std::vector<t_struct*>& newStructList, const std::vector<t_struct*>& oldStructList)
+{
+ std::map<std::string,t_struct*> newStructMap;
+ std::vector<t_struct*>::const_iterator newStructListIt;
+ for(newStructListIt = newStructList.begin(); newStructListIt != newStructList.end(); newStructListIt++)
+ {
+ newStructMap[(*newStructListIt)->get_name()] = *newStructListIt;
+ }
+
+ std::vector<t_struct*>::const_iterator oldStructListIt;
+ for(oldStructListIt = oldStructList.begin(); oldStructListIt != oldStructList.end(); oldStructListIt++)
+ {
+ std::map<std::string, t_struct*>::iterator newStructMapIt;
+ newStructMapIt = newStructMap.find((*oldStructListIt)->get_name());
+ if(newStructMapIt == newStructMap.end())
+ {
+ thrift_audit_failure("Struct %s not found in new thrift file\n", (*oldStructListIt)->get_name().c_str());
+ }
+ else
+ {
+ compare_single_struct(newStructMapIt->second, *oldStructListIt);
+ }
+ }
+
+}
+
+void compare_single_function(t_function* newFunction, t_function* oldFunction)
+{
+ t_type* newFunctionReturnType = newFunction->get_returntype();
+
+ if(newFunction->is_oneway() != oldFunction->is_oneway())
+ {
+ thrift_audit_failure("Oneway attribute changed for function %s\n",oldFunction->get_name().c_str());
+ }
+ if(!compare_type(newFunctionReturnType, oldFunction->get_returntype()))
+ {
+ thrift_audit_failure("Return type changed for function %s\n",oldFunction->get_name().c_str());
+ }
+
+ //Compare function arguments.
+ compare_single_struct(newFunction->get_arglist(), oldFunction->get_arglist());
+ std::string exceptionName = oldFunction->get_name();
+ exceptionName += "_exception";
+ compare_single_struct(newFunction->get_xceptions(), oldFunction->get_xceptions(), exceptionName);
+}
+
+void compare_functions(const std::vector<t_function*>& newFunctionList, const std::vector<t_function*>& oldFunctionList)
+{
+ std::map<std::string, t_function*> newFunctionMap;
+ std::map<std::string, t_function*>::iterator newFunctionMapIt;
+ for(std::vector<t_function*>::const_iterator newFunctionIt = newFunctionList.begin();
+ newFunctionIt != newFunctionList.end();
+ newFunctionIt++)
+ {
+ newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt;
+ }
+
+ for(std::vector<t_function*>::const_iterator oldFunctionIt = oldFunctionList.begin();
+ oldFunctionIt != oldFunctionList.end();
+ oldFunctionIt++)
+ {
+ newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name());
+ if(newFunctionMapIt == newFunctionMap.end())
+ {
+ thrift_audit_failure("New Thrift File has missing function %s\n",(*oldFunctionIt)->get_name().c_str());
+ continue;
+ }
+ else
+ {
+ //Function is found in both thrift files. Compare return type and argument list
+ compare_single_function(newFunctionMapIt->second, *oldFunctionIt);
+ }
+ }
+
+}
+
+void compare_services(const std::vector<t_service*>& newServices, const std::vector<t_service*>& oldServices)
+{
+ std::vector<t_service*>::const_iterator oldServiceIt;
+
+ std::map<std::string, t_service*> newServiceMap;
+ for(std::vector<t_service*>::const_iterator newServiceIt = newServices.begin();
+ newServiceIt != newServices.end();
+ newServiceIt++)
+ {
+ newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt;
+ }
+
+
+ for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++)
+ {
+ const std::string oldServiceName = (*oldServiceIt)->get_name();
+ std::map<std::string, t_service*>::iterator newServiceMapIt = newServiceMap.find(oldServiceName);
+
+ if(newServiceMapIt == newServiceMap.end())
+ {
+ thrift_audit_failure("New Thrift file is missing a service %s\n", oldServiceName.c_str());
+ }
+ else
+ {
+ t_service* oldServiceExtends = (*oldServiceIt)->get_extends();
+ t_service* newServiceExtends = (newServiceMapIt->second)->get_extends();
+
+ if(oldServiceExtends == NULL)
+ {
+ // It is fine to add extends. So if service in older thrift did not have any extends, we are fine.
+ // DO Nothing
+ }
+ else if(oldServiceExtends != NULL && newServiceExtends == NULL)
+ {
+ thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
+ }
+ else
+ {
+ std::string oldExtendsName = oldServiceExtends->get_name();
+ std::string newExtendsName = newServiceExtends->get_name();
+
+ if( newExtendsName != oldExtendsName)
+ {
+ thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str());
+ }
+ }
+
+ compare_functions((newServiceMapIt->second)->get_functions(), (*oldServiceIt)->get_functions());
+ }
+
+ }
+
+}
+
+void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst)
+{
+ std::vector<t_const*>::const_iterator newConstIt;
+ std::vector<t_const*>::const_iterator oldConstIt;
+
+ std::map<std::string, t_const*> newConstMap;
+
+ for(newConstIt = newConst.begin(); newConstIt != newConst.end(); newConstIt++)
+ {
+ newConstMap[(*newConstIt)->get_name()] = *newConstIt;
+ }
+
+ std::map<std::string, t_const*>::const_iterator newConstMapIt;
+ for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end(); oldConstIt++)
+ {
+ newConstMapIt = newConstMap.find((*oldConstIt)->get_name());
+ if(newConstMapIt == newConstMap.end())
+ {
+ thrift_audit_warning(1, "Constants Missing %s \n", ((*oldConstIt)->get_name()).c_str());
+ }
+ else if(!compare_type((newConstMapIt->second)->get_type(), (*oldConstIt)->get_type()))
+ {
+ thrift_audit_warning(1, "Constant %s is of different type \n", ((*oldConstIt)->get_name()).c_str());
+ }
+ else if(!compare_defaults((newConstMapIt->second)->get_value(), (*oldConstIt)->get_value()))
+ {
+ thrift_audit_warning(1, "Constant %s has different value\n", ((*oldConstIt)->get_name()).c_str());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/audit/t_audit.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/audit/t_audit.h b/compiler/cpp/src/thrift/audit/t_audit.h
new file mode 100644
index 0000000..be79e31
--- /dev/null
+++ b/compiler/cpp/src/thrift/audit/t_audit.h
@@ -0,0 +1,14 @@
+#ifndef T_AUDIT_H
+#define T_AUDIT_H
+
+void compare_namespace(t_program* newProgram, t_program* oldProgram);
+void compare_enums(const std::vector<t_enum*>& newEnumList,
+ const std::vector<t_enum*>& oldEnumList);
+bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault);
+void compare_structs(const std::vector<t_struct*>& newStructList,
+ const std::vector<t_struct*>& oldStructList);
+void compare_services(const std::vector<t_service*>& newServices,
+ const std::vector<t_service*>& oldServices);
+void compare_consts(const std::vector<t_const*>& newConst, const std::vector<t_const*>& oldConst);
+
+#endif
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/common.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/common.cc b/compiler/cpp/src/thrift/common.cc
new file mode 100644
index 0000000..3a2b9d3
--- /dev/null
+++ b/compiler/cpp/src/thrift/common.cc
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#include "thrift/common.h"
+#include "thrift/parse/t_base_type.h"
+
+t_type* g_type_void;
+t_type* g_type_string;
+t_type* g_type_binary;
+t_type* g_type_slist;
+t_type* g_type_bool;
+t_type* g_type_i8;
+t_type* g_type_i16;
+t_type* g_type_i32;
+t_type* g_type_i64;
+t_type* g_type_double;
+
+void initGlobals() {
+ g_type_void = new t_base_type("void", t_base_type::TYPE_VOID);
+ g_type_string = new t_base_type("string", t_base_type::TYPE_STRING);
+ g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING);
+ ((t_base_type*)g_type_binary)->set_binary(true);
+ g_type_slist = new t_base_type("string", t_base_type::TYPE_STRING);
+ ((t_base_type*)g_type_slist)->set_string_list(true);
+ g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL);
+ g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8);
+ g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16);
+ g_type_i32 = new t_base_type("i32", t_base_type::TYPE_I32);
+ g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64);
+ g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE);
+}
+
+void clearGlobals() {
+ delete g_type_void;
+ delete g_type_string;
+ delete g_type_bool;
+ delete g_type_i8;
+ delete g_type_i16;
+ delete g_type_i32;
+ delete g_type_i64;
+ delete g_type_double;
+}
+
+/**
+ * Those are not really needed for plugins but causes link errors without
+ */
+
+/**
+ * The location of the last parsed doctext comment.
+ */
+int g_doctext_lineno;
+int g_program_doctext_lineno = 0;
+PROGDOCTEXT_STATUS g_program_doctext_status = INVALID;
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/common.h
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/common.h b/compiler/cpp/src/thrift/common.h
new file mode 100644
index 0000000..6948846
--- /dev/null
+++ b/compiler/cpp/src/thrift/common.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef T_COMMON_H
+#define T_COMMON_H
+
+#include "thrift/parse/t_type.h"
+
+/**
+ * Global types for the parser to be able to reference
+ */
+
+extern t_type* g_type_void;
+extern t_type* g_type_string;
+extern t_type* g_type_binary;
+extern t_type* g_type_slist;
+extern t_type* g_type_bool;
+extern t_type* g_type_i8;
+extern t_type* g_type_i16;
+extern t_type* g_type_i32;
+extern t_type* g_type_i64;
+extern t_type* g_type_double;
+
+void initGlobals();
+void clearGlobals();
+
+#endif