mirror of
https://github.com/valitydev/thrift.git
synced 2024-11-06 18:35:19 +00:00
Thrift compiler now compiles both native Java and C++ code
Summary: Compiles to both C++ and Java, plus a host of other cool options like command line control over which languages to output code in Reviewed By: aditya Test Plan: The unit test checkins are coming momentarily... git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664713 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e8540637aa
commit
b15a68bd89
@ -35,7 +35,8 @@ BIN_DIR = bin/
|
||||
# Source files
|
||||
SRC_FILES = main.cc \
|
||||
generate/t_generator.cc \
|
||||
generate/t_cpp_generator.cc
|
||||
generate/t_cpp_generator.cc \
|
||||
generate/t_java_generator.cc
|
||||
|
||||
# Autogenerated files
|
||||
GEN_FILES = thrift.tab.hh \
|
||||
@ -61,21 +62,23 @@ CFL = -g -Wall -I$(SRC_DIR) -I$(OBJ_DIR)
|
||||
# Flex library
|
||||
LIBS = -lfl
|
||||
|
||||
# Build directories
|
||||
obj_dirs: $(OBJ_DIR)parse $(OBJ_DIR)generate
|
||||
$(OBJ_DIR)parse:
|
||||
$(MKDIR) -p $(OBJ_DIR)parse
|
||||
$(OBJ_DIR)generate:
|
||||
$(MKDIR) -p $(OBJ_DIR)generate
|
||||
|
||||
# Scanner generation
|
||||
$(GEN_DIR)lex.yy.cc: $(SRC_DIR)thrift.l
|
||||
$(LEX) -o$@ $(SRC_DIR)thrift.l
|
||||
|
||||
# Parser generation
|
||||
$(GEN_DIR)thrift.tab.hh: $(GEN_DIR)thrift.tab.cc
|
||||
|
||||
$(GEN_DIR)thrift.tab.cc: $(SRC_DIR)thrift.y
|
||||
$(YACC) -d -o$(GEN_DIR)thrift.tab.cc $(SRC_DIR)thrift.y
|
||||
|
||||
# C++ compilation
|
||||
$(OBJ_DIR)lex.yy.o: $(GEN_DIR)lex.yy.cc
|
||||
$(CC) $(CFL) -c -o $@ $(GEN_DIR)lex.yy.cc
|
||||
|
||||
# C++ compilation
|
||||
# Parser generation
|
||||
$(GEN_DIR)thrift.tab.hh: $(GEN_DIR)thrift.tab.cc
|
||||
$(GEN_DIR)thrift.tab.cc: $(SRC_DIR)thrift.y
|
||||
$(YACC) -d -o$(GEN_DIR)thrift.tab.cc $(SRC_DIR)thrift.y
|
||||
$(OBJ_DIR)thrift.tab.o: $(GEN_DIR)thrift.tab.cc
|
||||
$(CC) $(CFL) -c -o $@ $(GEN_DIR)thrift.tab.cc
|
||||
|
||||
@ -84,15 +87,10 @@ $(OBJS): $(SRCS)
|
||||
$(CC) $(CFL) -c -o $@ ${subst $(OBJ_DIR),$(SRC_DIR),$*.cc}
|
||||
|
||||
# Main build rule
|
||||
thrift: $(OBJS) $(GOBS)
|
||||
thrift: obj_dirs $(OBJS) $(GOBS)
|
||||
$(LD) $(CFL) -o $(BIN_DIR)thrift $(OBJS) $(GOBS) $(LIBS)
|
||||
|
||||
# Build directory
|
||||
obj_dirs:
|
||||
$(MKDIR) -p $(OBJ_DIR)parse
|
||||
$(MKDIR) -p $(OBJ_DIR)generate
|
||||
|
||||
# Install it
|
||||
# Install
|
||||
install: thrift
|
||||
sudo install bin/thrift /usr/local/bin/thrift
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,16 +6,17 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "t_generator.h"
|
||||
#include "t_oop_generator.h"
|
||||
|
||||
// TODO(mcslee: Paramaterize the output dir
|
||||
#define T_CPP_DIR "gen-cpp"
|
||||
|
||||
/**
|
||||
* C++ code generator.
|
||||
* C++ code generator. This is legitimacy incarnate.
|
||||
*
|
||||
* @author Mark Slee <mcslee@facebook.com>
|
||||
*/
|
||||
class t_cpp_generator : public t_generator {
|
||||
class t_cpp_generator : public t_oop_generator {
|
||||
public:
|
||||
t_cpp_generator() {}
|
||||
~t_cpp_generator() {}
|
||||
@ -37,80 +38,57 @@ class t_cpp_generator : public t_generator {
|
||||
void generate_service_interface (t_service* tservice);
|
||||
void generate_service_client (t_service* tservice);
|
||||
void generate_service_server (t_service* tservice);
|
||||
void generate_dispatch_function (t_service* tservice, t_function* tfunction);
|
||||
void generate_process_function (t_service* tservice, t_function* tfunction);
|
||||
|
||||
/** Serialization constructs */
|
||||
|
||||
void generate_deserialize_field (std::string src,
|
||||
t_field* tfield,
|
||||
void generate_deserialize_field (t_field* tfield,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_struct (std::string src,
|
||||
t_struct* tstruct,
|
||||
void generate_deserialize_struct (t_struct* tstruct,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_container (std::string src,
|
||||
t_type* ttype,
|
||||
void generate_deserialize_container (t_type* ttype,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_set_element (std::string src,
|
||||
t_set* tset,
|
||||
void generate_deserialize_set_element (t_set* tset,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_map_element (std::string src,
|
||||
t_map* tmap,
|
||||
void generate_deserialize_map_element (t_map* tmap,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_list_element (std::string src,
|
||||
t_list* tlist,
|
||||
void generate_deserialize_list_element (t_list* tlist,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_field (std::string dest,
|
||||
t_field* tfield,
|
||||
void generate_serialize_field (t_field* tfield,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_struct (std::string dest,
|
||||
t_struct* tstruct,
|
||||
void generate_serialize_struct (t_struct* tstruct,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_container (std::string dest,
|
||||
t_type* ttype,
|
||||
void generate_serialize_container (t_type* ttype,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_map_element (std::string dest,
|
||||
t_map* tmap,
|
||||
void generate_serialize_map_element (t_map* tmap,
|
||||
std::string iter);
|
||||
|
||||
void generate_serialize_set_element (std::string dest,
|
||||
t_set* tmap,
|
||||
void generate_serialize_set_element (t_set* tmap,
|
||||
std::string iter);
|
||||
|
||||
void generate_serialize_list_element (std::string dest,
|
||||
t_list* tlist,
|
||||
void generate_serialize_list_element (t_list* tlist,
|
||||
std::string iter);
|
||||
|
||||
/** Scoping */
|
||||
|
||||
void scope_up(std::ostream& out) {
|
||||
indent(out) << "{" << std::endl;
|
||||
indent_up();
|
||||
}
|
||||
|
||||
void scope_down(std::ostream& out) {
|
||||
indent_down();
|
||||
indent(out) << "}" << std::endl;
|
||||
}
|
||||
|
||||
/** Helper rendering functions */
|
||||
|
||||
std::string autogen_comment();
|
||||
std::string type_name(t_type* ttype);
|
||||
std::string base_type_name(t_base_type::t_base tbase);
|
||||
std::string declare_field(t_field* tfield, bool init=false);
|
||||
std::string function_signature(t_function* tfunction, std::string prefix="");
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
|
||||
std::string type_to_enum(t_type* ttype);
|
||||
|
||||
private:
|
||||
|
||||
/** File streams */
|
||||
|
||||
std::ofstream f_types_;
|
||||
|
1118
compiler/src/generate/t_java_generator.cc
Normal file
1118
compiler/src/generate/t_java_generator.cc
Normal file
File diff suppressed because it is too large
Load Diff
107
compiler/src/generate/t_java_generator.h
Normal file
107
compiler/src/generate/t_java_generator.h
Normal file
@ -0,0 +1,107 @@
|
||||
#ifndef T_JAVA_GENERATOR_H
|
||||
#define T_JAVA_GENERATOR_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "t_oop_generator.h"
|
||||
|
||||
// TODO(mcslee: Paramaterize the output dir
|
||||
#define T_JAVA_DIR "gen-java"
|
||||
|
||||
/**
|
||||
* Java code generator.
|
||||
*
|
||||
* @author Mark Slee <mcslee@facebook.com>
|
||||
*/
|
||||
class t_java_generator : public t_oop_generator {
|
||||
public:
|
||||
t_java_generator() {}
|
||||
~t_java_generator() {}
|
||||
|
||||
/** Init and close methods */
|
||||
|
||||
void init_generator(t_program *tprogram);
|
||||
void close_generator();
|
||||
|
||||
/** Program-level generation functions */
|
||||
|
||||
void generate_typedef (t_typedef* ttypedef);
|
||||
void generate_enum (t_enum* tenum);
|
||||
void generate_struct (t_struct* tstruct);
|
||||
void generate_service (t_service* tservice);
|
||||
|
||||
/** Service-level generation functions */
|
||||
|
||||
void generate_service_interface (t_service* tservice);
|
||||
void generate_service_client (t_service* tservice);
|
||||
void generate_service_server (t_service* tservice);
|
||||
void generate_process_function (t_service* tservice, t_function* tfunction);
|
||||
|
||||
/** Serialization constructs */
|
||||
|
||||
void generate_deserialize_field (t_field* tfield,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_struct (t_struct* tstruct,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_container (t_type* ttype,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_set_element (t_set* tset,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_map_element (t_map* tmap,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_deserialize_list_element (t_list* tlist,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_field (t_field* tfield,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_struct (t_struct* tstruct,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_container (t_type* ttype,
|
||||
std::string prefix="");
|
||||
|
||||
void generate_serialize_map_element (t_map* tmap,
|
||||
std::string iter,
|
||||
std::string map);
|
||||
|
||||
void generate_serialize_set_element (t_set* tmap,
|
||||
std::string iter);
|
||||
|
||||
void generate_serialize_list_element (t_list* tlist,
|
||||
std::string iter);
|
||||
|
||||
/** Helper rendering functions */
|
||||
|
||||
std::string java_package();
|
||||
std::string java_type_imports();
|
||||
std::string java_thrift_imports();
|
||||
std::string type_name(t_type* ttype);
|
||||
std::string base_type_name(t_base_type::t_base tbase);
|
||||
std::string declare_field(t_field* tfield, bool init=false);
|
||||
std::string function_signature(t_function* tfunction, std::string prefix="");
|
||||
std::string argument_list(t_struct* tstruct);
|
||||
std::string type_to_enum(t_type* ttype);
|
||||
|
||||
private:
|
||||
|
||||
/** File streams */
|
||||
|
||||
std::ofstream f_types_;
|
||||
std::ofstream f_header_;
|
||||
std::ofstream f_service_;
|
||||
|
||||
std::ofstream f_client_;
|
||||
std::ofstream f_server_;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
44
compiler/src/generate/t_oop_generator.h
Normal file
44
compiler/src/generate/t_oop_generator.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef T_OOP_GENERATOR_H
|
||||
#define T_OOP_GENERATOR_H
|
||||
|
||||
#include "globals.h"
|
||||
#include "t_generator.h"
|
||||
|
||||
/**
|
||||
* Class with utility methods shared across common object oriented languages.
|
||||
*
|
||||
* @author Mark Slee <mcslee@facebook.com>
|
||||
*/
|
||||
class t_oop_generator : public t_generator {
|
||||
public:
|
||||
|
||||
/** Scoping */
|
||||
|
||||
void scope_up(std::ostream& out) {
|
||||
indent(out) << "{" << std::endl;
|
||||
indent_up();
|
||||
}
|
||||
|
||||
void scope_down(std::ostream& out) {
|
||||
indent_down();
|
||||
indent(out) << "}" << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a comment about this code being autogenerated.
|
||||
*
|
||||
* @return C-style comment mentioning that this file is autogenerated.
|
||||
*/
|
||||
std::string autogen_comment() {
|
||||
return
|
||||
std::string("/**\n") +
|
||||
" * Autogenerated by Thrift\n" +
|
||||
" * " + g_time_str +
|
||||
" *\n" +
|
||||
" * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
|
||||
" */\n";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "main.h"
|
||||
#include "parse/t_program.h"
|
||||
#include "generate/t_cpp_generator.h"
|
||||
#include "generate/t_java_generator.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -91,7 +92,13 @@ void failure(char* fmt, ...) {
|
||||
* Diplays the usage message and then exits with an error code.
|
||||
*/
|
||||
void usage() {
|
||||
fprintf(stderr, "Usage: thrift [-d] <filename>\n");
|
||||
fprintf(stderr, "Usage: thrift [options] file\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, " -cpp Generate C++ output files\n");
|
||||
fprintf(stderr, " -java Generate Java output files\n");
|
||||
//fprintf(stderr, " -php Generate PHP output files\n");
|
||||
//fprintf(stderr, " -python Generate Python output files\n");
|
||||
fprintf(stderr, " -d Print parse debugging to standard output\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -100,23 +107,36 @@ void usage() {
|
||||
*/
|
||||
int main(int argc, char** argv) {
|
||||
int i;
|
||||
bool gen_cpp = false;
|
||||
bool gen_java = false;
|
||||
|
||||
// Setup time string
|
||||
time_t now = time(NULL);
|
||||
g_time_str = ctime(&now);
|
||||
|
||||
// Check for necessary arguments
|
||||
if (argc < 2) usage();
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
for (i = 1; i < argc-1; i++) {
|
||||
if (strcmp(argv[i], "-d") == 0) {
|
||||
g_debug = 1;
|
||||
} else if (strcmp(argv[i], "-cpp") == 0) {
|
||||
gen_cpp = true;
|
||||
} else if (strcmp(argv[i], "-java") == 0) {
|
||||
gen_java = true;
|
||||
} else {
|
||||
fprintf(stderr, "!!! Unrecognized option: %s\n", argv[i]);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
// Setup time string
|
||||
time_t now = time(NULL);
|
||||
g_time_str = ctime(&now);
|
||||
|
||||
if (!gen_cpp && !gen_java) {
|
||||
fprintf(stderr, "!!! No output language(s) specified\n\n");
|
||||
usage();
|
||||
}
|
||||
|
||||
// Open input file
|
||||
char* input_file = argv[i];
|
||||
yyin = fopen(input_file, "r");
|
||||
@ -144,9 +164,18 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Generate code
|
||||
try {
|
||||
t_cpp_generator* cpp = new t_cpp_generator();
|
||||
cpp->generate_program(g_program);
|
||||
delete cpp;
|
||||
if (gen_cpp) {
|
||||
t_cpp_generator* cpp = new t_cpp_generator();
|
||||
cpp->generate_program(g_program);
|
||||
delete cpp;
|
||||
}
|
||||
|
||||
if (gen_java) {
|
||||
t_java_generator* java = new t_java_generator();
|
||||
java->generate_program(g_program);
|
||||
delete java;
|
||||
}
|
||||
|
||||
} catch (string s) {
|
||||
printf("Error: %s\n", s.c_str());
|
||||
} catch (const char* exc) {
|
||||
@ -157,6 +186,5 @@ int main(int argc, char** argv) {
|
||||
delete g_program;
|
||||
|
||||
// Finished
|
||||
printf("\nDone!\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
*/
|
||||
class t_field {
|
||||
public:
|
||||
t_field(t_type* type, std::string name) :
|
||||
type_(type), name_(name), key_(0) {}
|
||||
|
||||
t_field(t_type* type, std::string name, uint32_t key) :
|
||||
type_(type), name_(name), key_(key) {}
|
||||
|
||||
|
@ -19,29 +19,10 @@ class t_function {
|
||||
|
||||
~t_function() {}
|
||||
|
||||
/**
|
||||
* Implementation of the Fowler / Noll / Vo (FNV) Hash
|
||||
* http://www.isthe.com/chongo/tech/comp/fnv/
|
||||
*/
|
||||
static uint32_t fnv32(const char *s) {
|
||||
uint32_t hash = (uint32_t)216613626;
|
||||
while (*s) {
|
||||
hash +=
|
||||
(hash << 1) +
|
||||
(hash << 4) +
|
||||
(hash << 7) +
|
||||
(hash << 8) +
|
||||
(hash << 24);
|
||||
hash ^= *s++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
t_type* get_returntype() const { return returntype_; }
|
||||
const std::string& get_name() const { return name_; }
|
||||
t_struct* get_arglist() const { return arglist_; }
|
||||
uint32_t get_hash() const { return fnv32(name_.c_str()); }
|
||||
|
||||
|
||||
private:
|
||||
t_type* returntype_;
|
||||
std::string name_;
|
||||
|
@ -10,6 +10,8 @@
|
||||
class t_struct : public t_type {
|
||||
public:
|
||||
t_struct() {}
|
||||
t_struct(const std::string& name) : t_type(name) {}
|
||||
|
||||
~t_struct() {}
|
||||
|
||||
/** Set the struct name */
|
||||
|
@ -49,7 +49,6 @@ symbol ([\,\{\}\(\)\=<>])
|
||||
|
||||
"typedef" { return tok_typedef; }
|
||||
"struct" { return tok_struct; }
|
||||
"function" { return tok_function; }
|
||||
"service" { return tok_service; }
|
||||
"enum" { return tok_enum; }
|
||||
|
||||
|
@ -56,7 +56,6 @@ int y_field_val = 0;
|
||||
/** Thrift actions */
|
||||
%token tok_typedef
|
||||
%token tok_struct
|
||||
%token tok_function
|
||||
%token tok_service
|
||||
%token tok_enum
|
||||
|
||||
@ -213,6 +212,7 @@ FunctionList:
|
||||
Function:
|
||||
FunctionType FunctionModifiers tok_identifier '(' FieldList ')'
|
||||
{
|
||||
$5->set_name(std::string($3) + "_args");
|
||||
$$ = new t_function($1, $3, $5);
|
||||
y_field_val = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user