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:
Mark Slee 2006-06-07 06:46:24 +00:00
parent e8540637aa
commit b15a68bd89
12 changed files with 1774 additions and 343 deletions

View File

@ -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

View File

@ -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_;

File diff suppressed because it is too large Load Diff

View 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

View 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

View File

@ -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;
}

View File

@ -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) {}

View File

@ -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_;

View File

@ -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 */

View File

@ -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; }

View File

@ -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;
}