Thrift compiler improvements, two modes for PHP

Summary: Complete PHP generator and CPP generator to new formats, and offer PHP generator that generates inline code free of any TProtocol abstraction


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664771 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/cpp.mk b/compiler/cpp/Makefile
similarity index 100%
rename from compiler/cpp/cpp.mk
rename to compiler/cpp/Makefile
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 6014e5f..43f8021 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -15,7 +15,7 @@
   mkdir(T_CPP_DIR, S_IREAD | S_IWRITE | S_IEXEC);
 
   // Make output file
-  string f_types_name = string(T_CPP_DIR)+"/"+program_name_+"Types.h";
+  string f_types_name = string(T_CPP_DIR)+"/"+program_name_+"_types.h";
   f_types_.open(f_types_name.c_str());
 
   // Print header
@@ -30,20 +30,75 @@
   
   // Include base types
   f_types_ <<
-    "#include \"Thrift.h\"" << endl <<
+    "#include <Thrift.h>" << endl <<
+    endl;
+
+  string open_ns = namespace_open(tprogram->get_namespace());
+
+  f_types_ <<
+    open_ns << endl <<
+    endl;
+
+  // Make output files
+  string f_header_name = string(T_CPP_DIR)+"/"+program_name_+".h";
+  f_header_.open(f_header_name.c_str());
+  string f_service_name = string(T_CPP_DIR)+"/"+program_name_+".cc";
+  f_service_.open(f_service_name.c_str());
+
+  // Print header file includes
+  f_header_ <<
+    autogen_comment();
+  f_header_ <<
+    "#ifndef " << program_name_ << "_H" << endl <<
+    "#define " << program_name_ << "_H" << endl <<
+    endl <<
+    "#include <Thrift.h>" << endl <<
+    "#include <TProcessor.h>" << endl <<
+    "#include <protocol/TProtocol.h>" << endl <<
+    "#include <transport/TTransport.h>" << endl <<
+    "#include \"" << program_name_ << "_types.h\"" << endl <<
+    endl <<
+    open_ns << endl <<
+    endl;
+
+  // Service implementation file includes
+  f_service_ <<
+    autogen_comment();
+  f_service_ <<
+    "#include \"" << program_name_ << ".h\"" << endl << 
+    endl <<
+    open_ns << endl <<
     endl;
 }
 
 /**
  * Closes the output files.
  */
-void t_cpp_generator::close_generator() {
+void t_cpp_generator::close_generator(t_program* tprogram) {
+  // Close ns
+  string close_ns = namespace_close(tprogram->get_namespace());
+  f_types_ <<
+    close_ns << endl <<
+    endl;
+  f_header_ <<
+    close_ns << endl <<
+    endl;
+  f_service_ <<
+    close_ns << endl <<
+    endl;
+
   // Close ifndef
   f_types_ <<
     "#endif" << endl;
+  f_header_ <<
+    "#endif" << endl;
   
   // Close output file
   f_types_.close();
+
+  // Close files
+  f_header_.close();
+  f_service_.close();
 }
 
 
@@ -105,26 +160,305 @@
  * @param tstruct The struct definition
  */
 void t_cpp_generator::generate_struct(t_struct* tstruct) {
-  f_types_ <<
-    indent() << "struct " << tstruct->get_name() << " {" << endl;
+  generate_struct_definition(f_types_, tstruct);
+  generate_struct_reader(f_service_, tstruct);
+  generate_struct_writer(f_service_, tstruct);
+}
+
+/**
+ * Writes the struct def.
+ *
+ * @param out Output stream
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_definition(ofstream& out,
+                                                 t_struct* tstruct) {
+  // Open struct def
+  out <<
+    indent() << "typedef struct _" << tstruct->get_name() << " {" << endl;
   
   indent_up();
 
-  const vector<t_field*>& members = tstruct->get_members();
+  // Get members
   vector<t_field*>::const_iterator m_iter; 
+  const vector<t_field*>& members = tstruct->get_members();
+
+  // Default constructor
+  bool init_ctor = false;
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(f_types_) <<
+    t_type* t = (*m_iter)->get_type();
+    while (t->is_typedef()) {
+      t = ((t_typedef*)t)->get_type();
+    }
+    if (t->is_base_type() &&
+        ((t_base_type*)t)->get_base() != t_base_type::TYPE_STRING) {
+      if (!init_ctor) {
+        init_ctor = true;
+        indent(out) <<
+          "_" << tstruct->get_name() << "() : ";
+        out << (*m_iter)->get_name() << "(0)";
+      } else
+        out << ", " << (*m_iter)->get_name() << "(0)";
+    }
+  }
+  if (init_ctor) {
+    out << " {} " << endl;
+  }
+
+  // Declare all fields
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    indent(out) <<
       declare_field(*m_iter) << endl;
   }
-  
-  indent_down();
-  
-  f_types_ <<
-    indent() << "};" << endl <<
+
+  // Isset vector
+  if (members.size() > 0) {
+    indent(out) <<
+      "struct __isset {" << endl;
+      indent_up();
+      
+      indent(out) <<
+        "__isset() : ";
+      bool first = true;
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        if (first) {
+          first = false;
+          out <<
+            (*m_iter)->get_name() << "(false)";
+        } else {
+          out <<
+            ", " << (*m_iter)->get_name() << "(false)";
+        }
+      }
+      out << " {}" << endl;
+      
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        indent(out) <<
+          "bool " << (*m_iter)->get_name() << ";" << endl;
+      }
+      indent_down();
+    indent(out) <<
+      "} __isset;" << endl;  
+  }
+
+  indent_down(); 
+  indent(out) <<
+    "} " << tstruct->get_name() << ";" << endl <<
     endl;
 }
 
 /**
+ * Makes a helper function to gen a struct reader.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_reader(ofstream& out,
+                                             t_struct* tstruct) {
+  indent(out) <<
+    "uint32_t read_struct_" << tstruct->get_name() << "(" <<
+    "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, " <<
+    "boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, " <<
+    tstruct->get_name() << "& value) {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables
+  out <<
+    endl << 
+    indent() << "uint32_t xfer = 0;" << endl <<
+    indent() << "std::string fname;" << endl <<
+    indent() << "facebook::thrift::protocol::TType ftype;" << endl <<
+    indent() << "int16_t fid;" << endl <<
+    endl <<
+    indent() << "xfer += iprot->readStructBegin(itrans, fname);" << endl <<
+    endl;
+  
+  // Loop over reading in fields
+  indent(out) <<
+    "while (true)" << endl;
+    scope_up(out);
+    
+    // Read beginning field marker
+    indent(out) <<
+      "xfer += iprot->readFieldBegin(itrans, fname, ftype, fid);" << endl;
+    
+    // Check for field STOP marker
+    out <<
+      indent() << "if (ftype == facebook::thrift::protocol::T_STOP) { " << endl <<
+      indent() << "  break;" << endl <<
+      indent() << "}" << endl;
+    
+    // Switch statement on the field we are reading
+    indent(out) <<
+      "switch (fid)" << endl;
+
+      scope_up(out);
+    
+      // Generate deserialization code for known cases
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        indent(out) <<
+          "case " << (*f_iter)->get_key() << ":" << endl;
+        indent_up();
+        generate_deserialize_field(*f_iter, "value.");
+        out <<
+          indent() << "value.__isset." << (*f_iter)->get_name() << " = true;" << endl <<
+          indent() << "break;" << endl;
+        indent_down();
+      }
+      
+      // In the default case we skip the field
+      out <<
+        indent() << "default:" << endl <<
+        indent() << "  xfer += iprot->skip(itrans, ftype);" << endl <<
+        indent() << "  break;" << endl;
+      
+      scope_down(out);
+
+    // Read field end marker
+    indent(out) <<
+      "xfer += iprot->readFieldEnd(itrans);" << endl;
+
+    scope_down(out);
+
+  out <<
+    endl <<
+    indent() << "xfer += iprot->readStructEnd(itrans);" << endl <<
+    indent() <<"return xfer;" << endl;
+
+  indent_down();
+  indent(out) <<
+    "}" << endl << endl;
+}
+
+/**
+ * Makes a helper function to gen a struct writer.
+ *
+ * @param out Stream to write to
+ * @param tstruct The struct
+ */
+void t_cpp_generator::generate_struct_writer(ofstream& out,
+                                             t_struct* tstruct) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) <<
+    "uint32_t write_struct_" << name << "(" <<
+    "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot, " <<
+    "boost::shared_ptr<facebook::thrift::transport::TTransport> otrans, " <<
+    "const " << name << "& value) {" << endl;
+  indent_up();
+
+  out <<
+    endl <<
+    indent() << "uint32_t xfer = 0;" << endl <<
+    endl;
+
+  indent(out) <<
+    "xfer += oprot->writeStructBegin(otrans, \"" << name << "\");" << endl;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    // Write field header
+    out <<
+      endl <<
+      indent() << "xfer += oprot->writeFieldBegin(otrans, " <<
+      "\"" << (*f_iter)->get_name() << "\", " <<
+      type_to_enum((*f_iter)->get_type()) << ", " <<
+      (*f_iter)->get_key() << ");" << endl;
+    // Write field contents
+    generate_serialize_field(*f_iter, "value.");
+    // Write field closer
+    indent(out) <<
+      "xfer += oprot->writeFieldEnd(otrans);" << endl <<
+      endl;
+  }
+  // Write the struct map
+  out <<
+    indent() << "xfer += oprot->writeFieldStop(otrans);" << endl <<
+    endl <<
+    indent() << "xfer += oprot->writeStructEnd(otrans);" << endl <<
+    indent() << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) <<
+    "}" << endl << endl;
+}
+
+/**
+ * Struct writer for result of a function, which can have only one of its
+ * fields set and does a conditional if else look up into the __isset field
+ * of the struct.
+ *
+ * @param out Output stream
+ * @param tstruct The result struct
+ */
+void t_cpp_generator::generate_struct_result_writer(ofstream& out,
+                                                    t_struct* tstruct) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) <<
+    "uint32_t write_struct_" << name << "(" <<
+    "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot, " <<
+    "boost::shared_ptr<facebook::thrift::transport::TTransport> otrans, " <<
+    "const " << name << "& value) {" << endl;
+  indent_up();
+
+  out <<
+    endl <<
+    indent() << "uint32_t xfer = 0;" << endl <<
+    endl;
+
+  indent(out) <<
+    "xfer += oprot->writeStructBegin(otrans, \"" << name << "\");" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out << 
+        endl <<
+        indent() << "if ";
+    } else {
+      out <<
+        " else if ";
+    }
+
+    out << "(value.__isset." << (*f_iter)->get_name() << ") {" << endl;
+    
+    indent_up();
+
+    // Write field header
+    out <<
+      indent() << "xfer += oprot->writeFieldBegin(otrans, " <<
+      "\"" << (*f_iter)->get_name() << "\", " <<
+      type_to_enum((*f_iter)->get_type()) << ", " <<
+      (*f_iter)->get_key() << ");" << endl;
+    // Write field contents
+    generate_serialize_field(*f_iter, "value.");
+    // Write field closer
+    indent(out) << "xfer += oprot->writeFieldEnd(otrans);" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+
+  // Write the struct map
+  out <<
+    endl <<
+    indent() << "xfer += oprot->writeFieldStop(otrans);" << endl <<
+    indent() << "xfer += oprot->writeStructEnd(otrans);" << endl <<
+    indent() << "return xfer;" << endl;
+
+  indent_down();
+  indent(out) <<
+    "}" << endl << endl;
+}
+
+/**
  * Generates a thrift service. In C++, this comprises an entirely separate
  * header and source file. The header file defines the methods and includes
  * the data types defined in the main header file, and the implementation
@@ -133,40 +467,27 @@
  * @param tservice The service definition
  */
 void t_cpp_generator::generate_service(t_service* tservice) {
-  // Make output files
-  string f_header_name = string(T_CPP_DIR)+"/"+service_name_+".h";
-  f_header_.open(f_header_name.c_str());
-  string f_service_name = string(T_CPP_DIR)+"/"+service_name_+".cc";
-  f_service_.open(f_service_name.c_str());
-
-  // Print header file includes
-  f_header_ <<
-    autogen_comment();
-  f_header_ <<
-    "#ifndef " << service_name_ << "_H" << endl <<
-    "#define " << service_name_ << "_H" << endl <<
-    endl <<
-    "#include \"TProcessor.h\"" << endl <<
-    "#include \"transport/TTransport.h\"" << endl <<
-    "#include \"protocol/TProtocol.h\"" << endl <<
-    "#include \"" << program_name_ << "Types.h\"" << endl <<
-    endl;
-  f_service_ <<
-    autogen_comment();
-  f_service_ <<
-    "#include \"" << service_name_ << ".h\"" << endl << endl;
-
-  // Generate the three main parts of the service
   generate_service_interface(tservice);
+  generate_service_helpers(tservice);
   generate_service_server(tservice);
   generate_service_client(tservice);
+}
 
-  f_header_ <<
-    "#endif" << endl;
-
-  // Close files
-  f_header_.close();
-  f_service_.close();
+/**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_cpp_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter; 
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_struct_definition(f_service_, ts);
+    generate_struct_reader(f_service_, ts);
+    generate_struct_writer(f_service_, ts);
+    generate_function_helpers(*f_iter);
+  }
 }
 
 /**
@@ -179,14 +500,14 @@
     "class " << service_name_ << "If {" << endl <<
     " public: " << endl;
   indent_up(); 
+  f_header_ <<
+    indent() << "virtual ~" << service_name_ << "If() {}" << endl;
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     f_header_ <<
       indent() << "virtual " << function_signature(*f_iter) << " = 0;" << endl;
   }
-  f_header_ <<
-    indent() << "virtual ~" << service_name_ << "If() {}" << endl;
   indent_down();
   f_header_ <<
     "}; " << endl << endl;
@@ -207,13 +528,13 @@
   indent_up();
   f_header_ <<
     indent() << service_name_ << "Client" <<
-    "(boost::shared_ptr<facebook::thrift::transport::TTransport> trans, boost::shared_ptr<facebook::thrift::protocol::TProtocol> prot) : " <<
+    "(boost::shared_ptr<facebook::thrift::transport::TTransport> trans, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> prot) : " <<
     "_itrans(trans), _otrans(trans), " <<
     "_iprot(prot), _oprot(prot) {}" << endl;
   f_header_ <<
     indent() << service_name_ << "Client" <<
     "(boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans," <<
-    " boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) : " <<
+    " boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) : " <<
     "_itrans(itrans), _otrans(otrans), " <<
     "_iprot(iprot), _oprot(oprot) {}" << endl;
 
@@ -241,8 +562,8 @@
   f_header_ <<
     indent() << "boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans;" << endl <<
     indent() << "boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans;" << endl <<
-    indent() << "boost::shared_ptr<facebook::thrift::protocol::TProtocol>  _iprot;"  << endl <<
-    indent() << "boost::shared_ptr<facebook::thrift::protocol::TProtocol>  _oprot;"  << endl;
+    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol>  _iprot;"  << endl <<
+    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol>  _oprot;"  << endl;
   indent_down();  
 
   f_header_ <<
@@ -294,39 +615,36 @@
                              string("send_") + (*f_iter)->get_name(),
                              (*f_iter)->get_arglist());
 
-    // Open function
+    // Open the send function
     indent(f_service_) <<
       function_signature(&send_function, scope) << endl;
     scope_up(f_service_);
 
+    string argsname = (*f_iter)->get_name() + "_args";
+    string resultname = (*f_iter)->get_name() + "_result";
+
     // Serialize the request
     f_service_ <<
-      indent() <<
-      "_oprot->writeStructBegin(_otrans, \"function\");" << endl <<
-      indent() <<
-      "_oprot->writeFieldBegin(_otrans, \"name\", facebook::thrift::protocol::T_STRING, 0);" << endl <<
-      indent() <<
-      "_oprot->writeString(_otrans, \"" << funname << "\");" << endl <<
-      indent() <<
-      "_oprot->writeFieldEnd(_otrans);" << endl <<
-      indent() <<
-      "_oprot->writeFieldBegin(_otrans, \"args\", facebook::thrift::protocol::T_STRUCT, 1);" << endl;     
-    generate_serialize_struct((*f_iter)->get_arglist());
+      indent() << "int32_t cseqid = 0;" << endl <<
+      indent() << "_oprot->writeMessageBegin(_otrans, \"" << (*f_iter)->get_name() << "\", facebook::thrift::protocol::T_CALL, cseqid);" << endl <<
+      endl <<
+      indent() << argsname << " __args;" << endl;
+    
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ <<
+        indent() << "__args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << ";" << endl;
+    }
+      
     f_service_ <<
-      indent() <<
-      "_oprot->writeFieldEnd(_otrans);" << endl <<
-      indent() <<
-      "_oprot->writeFieldStop(_otrans);" << endl <<
-      indent() <<
-      "_oprot->writeStructEnd(_otrans);" << endl;
-    
-    // Flush the request
-    indent(f_service_) <<
-      "_otrans->flush();" << endl;
-    
+      indent() << "write_struct_" <<  argsname << "(_oprot, _otrans, __args);" << endl <<
+      endl <<
+      indent() << "_oprot->writeMessageEnd(_otrans);" << endl <<
+      indent() << "_otrans->flush();" << endl;
+       
     scope_down(f_service_);
     f_service_ << endl;
 
+    // Generate recv function only if not an async function
     if (!(*f_iter)->is_async()) {
       t_struct noargs;
       t_function recv_function((*f_iter)->get_returntype(),
@@ -337,34 +655,63 @@
         function_signature(&recv_function, scope) << endl;
       scope_up(f_service_);
 
-      // Read the response
-      t_struct result_struct((*f_iter)->get_name() + "_result");
-      t_field result_field((*f_iter)->get_returntype(), "_result");
-      
+      f_service_ <<
+        endl <<
+        indent() << "int32_t rseqid = 0;" << endl <<
+        indent() << "std::string fname;" << endl <<
+        indent() << "facebook::thrift::protocol::TMessageType mtype;" << endl <<
+        endl <<
+        indent() << "_iprot->readMessageBegin(_itrans, fname, mtype, rseqid);" << endl <<
+        indent() << "if (mtype != facebook::thrift::protocol::T_REPLY || fname.compare(\"" << (*f_iter)->get_name() << "\") != 0) {" << endl;
+      indent_up();
+        f_service_ <<
+          indent() << "throw facebook::thrift::Exception(\"Unexpected message type, name, or id\");" << endl;
+      indent_down();
+      f_service_ <<
+        indent() << "}" << endl;
+
+      f_service_ <<
+        endl <<
+        indent() << resultname << " __result;" << endl;
+
       // Add a field to the return struct if non void
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) <<
-          type_name((*f_iter)->get_returntype()) << " _result;" << endl;
-        result_struct.append(&result_field);
-      }
-      
-      // Deserialize response struct
-      generate_deserialize_struct(&result_struct);
-      
+      f_service_ <<
+        indent() << "read_struct_" << resultname << "(_iprot, _itrans, __result);" << endl <<
+        indent() << "_iprot->readMessageEnd(_itrans);" << endl <<
+        endl;
+
+
       // Careful, only return _result if not a void function
       if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) <<
-          "return _result;" << endl;
-      } else {
+        f_service_ <<
+          indent() << "if (__result.__isset.success) {" << endl <<
+          indent() << "  return __result.success;" << endl <<
+          indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ <<
+          indent() << "if (__result.__isset." << (*x_iter)->get_name() << ") {" << endl <<
+          indent() << "  throw __result." << (*x_iter)->get_name() << ";" << endl <<
+          indent() << "}" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
         indent(f_service_) <<
           "return;" << endl;
+      } else {
+        f_service_ <<
+          indent() << "throw facebook::thrift::Exception(\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
       }
-      
+             
       // Close function
       scope_down(f_service_);
       f_service_ << endl;
     }
-
   }
 }
 
@@ -387,10 +734,10 @@
   indent_up();
   f_header_ << 
     indent() <<
-    service_name_ << "ServerIf(boost::shared_ptr<facebook::thrift::protocol::TProtocol> protocol) : " <<
+    service_name_ << "ServerIf(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> protocol) : " <<
                        "_iprot(protocol), _oprot(protocol) {}" << endl <<
     indent() <<
-    service_name_ << "ServerIf(boost::shared_ptr<facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<facebook::thrift::protocol::TProtocol> oprot) : " <<
+    service_name_ << "ServerIf(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) : " <<
                        "_iprot(iprot), _oprot(oprot) {}" << endl <<
     indent() << "bool process(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, " <<
                              "boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl <<
@@ -402,8 +749,8 @@
     " protected:" << endl;
   indent_up();
   f_header_ <<
-    indent() << "boost::shared_ptr<facebook::thrift::protocol::TProtocol> _iprot;" << endl <<
-    indent() << "boost::shared_ptr<facebook::thrift::protocol::TProtocol> _oprot;" << endl;
+    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> _iprot;" << endl <<
+    indent() << "boost::shared_ptr<const facebook::thrift::protocol::TProtocol> _oprot;" << endl;
   indent_down();
 
   // Process function declarations
@@ -413,7 +760,7 @@
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     indent(f_header_) <<
       "void process_" << (*f_iter)->get_name() <<
-      "(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl;
+      "(int32_t seqid, boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl;
   }
   indent_down();
   f_header_ <<
@@ -422,29 +769,22 @@
   // Generate the server implementation
   f_service_ <<
     "bool " << service_name_ << "ServerIf::" <<
-    "process(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans) {" << endl;
+    "process(boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans) {" << endl;
   indent_up();
 
   f_service_ <<
-    indent() <<
-    "std::string _name;" << endl <<
-    indent() <<
-    "std::string _fname;" << endl <<
-    indent() <<
-    "facebook::thrift::protocol::TType _ftype;" << endl <<
-    indent() <<
-    "uint16_t _fid;" << endl <<
-    indent() <<
-    "_iprot->readStructBegin(_itrans, _name);" << endl <<
-    indent() <<
-    "_iprot->readFieldBegin(_itrans, _name, _ftype, _fid);" << endl <<
-    indent() <<
-    "_iprot->readString(_itrans, _fname);" << endl <<
-    indent() <<
-    "_iprot->readFieldEnd(_itrans);" << endl <<
-    indent() <<
-    "_iprot->readFieldBegin(_itrans, _name, _ftype, _fid);" << endl;
-
+    endl <<
+    indent() << "std::string fname;" << endl <<
+    indent() << "facebook::thrift::protocol::TMessageType mtype;" << endl <<
+    indent() << "int32_t seqid;" << endl <<
+    endl <<
+    indent() << "_iprot->readMessageBegin(itrans, fname, mtype, seqid);" << endl <<
+    endl <<
+    indent() << "if (mtype != facebook::thrift::protocol::T_CALL) {" << endl <<
+    indent() << "  throw facebook::thrift::Exception(\"Unexpected message type\");" << endl <<
+    indent() << "}" << endl <<
+    endl;
+    
   bool first = true;
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     if (!first) {
@@ -454,11 +794,11 @@
       first = false;
     }
     f_service_ <<
-      "if (_fname.compare(\"" << (*f_iter)->get_name() <<"\") == 0) {" << endl;
+      "if (fname.compare(\"" << (*f_iter)->get_name() <<"\") == 0) {" << endl;
     indent_up();
     indent(f_service_) <<
       "process_" << (*f_iter)->get_name() <<
-      "(_itrans, _otrans);" << endl;
+      "(seqid, itrans, otrans);" << endl;
     indent_down();
     indent(f_service_) << "}";
   }
@@ -466,22 +806,14 @@
     " else {" << endl;
   indent_up();
   indent(f_service_) <<
-    "fprintf(stderr, \"Unknown function: '%s'\\n\", " <<
-    "_fname.c_str());" << endl;
+    "throw facebook::thrift::Exception(\"Unknown function name: '\"+fname+\"'\");" << endl;
   indent_down();
   indent(f_service_) <<
     "}" << endl;
 
   // Read end of args field, the T_STOP, and the struct close
   f_service_ <<
-    indent() <<
-    "_iprot->readFieldEnd(_itrans);" << endl <<
-    indent() <<
-    "_iprot->readFieldBegin(_itrans, _name, _ftype, _fid);" << endl <<   
-    indent() <<
-    "_iprot->readStructEnd(_itrans);" << endl <<
-    indent() <<
-    "return true;" << endl;
+    indent() << "return true;" << endl;
 
   indent_down();
   f_service_ <<
@@ -495,6 +827,30 @@
 }
 
 /**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_cpp_generator::generate_function_helpers(t_function* tfunction) {
+  t_struct result(tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_struct_definition(f_service_, &result);
+  generate_struct_reader(f_service_, &result);
+  generate_struct_result_writer(f_service_, &result);
+}
+
+/**
  * Generates a process function definition.
  *
  * @param tfunction The function to write a dispatcher for
@@ -505,27 +861,37 @@
   f_service_ <<
     "void " << tservice->get_name() << "ServerIf::" <<
     "process_" << tfunction->get_name() <<
-    "(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans)" << endl;
+    "(int32_t seqid, boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans)" << endl;
   scope_up(f_service_);
 
-  // Get the struct of function call params
-  t_struct* arg_struct = tfunction->get_arglist();
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
 
-  // Declare the function arguments
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(f_service_) <<
-      declare_field(*f_iter, true) << endl;
+  f_service_ <<
+    indent() << argsname << " __args;" << endl <<
+    indent() << "read_struct_" << argsname << "(_iprot, itrans, __args);" << endl <<
+    indent() << "_iprot->readMessageEnd(itrans);" << endl <<
+    endl <<
+    indent() << resultname << " __result;" << endl;
+ 
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  if (xceptions.size() > 0) {
+    f_service_ <<
+      indent() << "try {" << endl;
+    indent_up();
   }
 
-  // Deserialize the function arguments as a struct
-  generate_deserialize_struct(arg_struct);
-  
   // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
   f_service_ << indent();
   if (!tfunction->get_returntype()->is_void()) {
-    f_service_ << type_name(tfunction->get_returntype()) << " _result = ";
+    f_service_ << "__result.success = ";    
   }
   f_service_ <<
     tfunction->get_name() << "(";
@@ -536,22 +902,40 @@
     } else {
       f_service_ << ", ";
     }
-    f_service_ << (*f_iter)->get_name();
+    f_service_ << "__args." << (*f_iter)->get_name();
   }
   f_service_ << ");" << endl;
 
-  // Serialize the result into a struct
-  t_struct result_struct(tfunction->get_name() + "_result");
-  t_field result_field(tfunction->get_returntype(), "_result");
-
-  // Only append the field if non-void
+  // Set isset on success field
   if (!tfunction->get_returntype()->is_void()) {
-    result_struct.append(&result_field);
+    f_service_ <<
+      indent() << "__result.__isset.success = true;" << endl;
   }
-  generate_serialize_struct(&result_struct);
-  indent(f_service_) <<
-    "_otrans->flush();" << endl;
 
+  if (xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}";
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << " catch (" << (*x_iter)->get_type()->get_name() << " &" << (*x_iter)->get_name() << ") {" << endl;
+      indent_up();
+      f_service_ <<
+        indent() << "__result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl <<
+        indent() << "__result.__isset." << (*x_iter)->get_name() << " = true;" << endl;
+      indent_down();
+      f_service_ << indent() << "}";
+    }
+    f_service_ << endl;
+  }
+
+
+  // Serialize the result into a struct
+  f_service_ <<
+    endl <<
+    indent() << "_oprot->writeMessageBegin(otrans, \"" << tfunction->get_name() << "\", facebook::thrift::protocol::T_REPLY, seqid);" << endl <<
+    indent() << "write_struct_" << resultname << "(_oprot, otrans, __result);" << endl <<
+    indent() << "_oprot->writeMessageEnd(otrans);" << endl <<
+    indent() << "otrans->flush();" << endl;
+    
   // Close function
   scope_down(f_service_);
   f_service_ << endl;
@@ -574,15 +958,14 @@
 
   string name = prefix + tfield->get_name();
 
-  if (type->is_struct()) {
-    generate_deserialize_struct((t_struct*)(tfield->get_type()),
-                                 name + ".");
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct((t_struct*)(tfield->get_type()), name);
   } else if (type->is_container()) {
     generate_deserialize_container(tfield->get_type(), name);
   } else if (type->is_base_type() || type->is_enum()) {
 
     indent(f_service_) <<
-      "_iprot->";
+      "xfer += iprot->";
     
     if (type->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -592,28 +975,25 @@
           name;
         break;
       case t_base_type::TYPE_STRING:
-        f_service_ << "readString(_itrans, " << name << ");";
+        f_service_ << "readString(itrans, " << name << ");";
         break;
       case t_base_type::TYPE_BYTE:
-        f_service_ << "readByte(_itrans, " << name << ");";
+        f_service_ << "readByte(itrans, " << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        f_service_ << "readI16(itrans, " << name << ");";
         break;
       case t_base_type::TYPE_I32:
-        f_service_ << "readI32(_itrans, " << name << ");";
-        break;
-      case t_base_type::TYPE_U32:
-        f_service_ << "readU32(_itrans, " << name << ");";
+        f_service_ << "readI32(itrans, " << name << ");";
         break;
       case t_base_type::TYPE_I64:
-        f_service_ << "readI64(_itrans, " << name << ");";
-        break;
-      case t_base_type::TYPE_U64:
-        f_service_ << "readU64(_itrans, " << name << ");";
+        f_service_ << "readI64(itrans, " << name << ");";
         break;
       default:
-        throw "compiler error: no C++ name for base type " + tbase;
+        throw "compiler error: no C++ reader for base type " + tbase + name;
       }
     } else if (type->is_enum()) {
-      f_service_ << "readI32(_itrans, (int32_t&)" << name << ");";
+      f_service_ << "readI32(itrans, (int32_t&)" << name << ");";
     }
     f_service_ <<
       endl;
@@ -631,73 +1011,8 @@
  */
 void t_cpp_generator::generate_deserialize_struct(t_struct* tstruct,
                                                   string prefix) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  scope_up(f_service_);
-
-  // Read the struct fields from the protocol
-  string fid   = tmp("_fid");
-  string ftype = tmp("_ftype");
-  string fname = tmp("_name");
-  
-  // Declare stack tmp variables
-  f_service_ <<
-    indent() << "std::string " << fname << ";" << endl <<
-    indent() << "facebook::thrift::protocol::TType " << ftype << ";" << endl <<
-    indent() << "uint16_t " << fid << ";" << endl <<
-    indent() << "_iprot->readStructBegin(_itrans, " << fname << ");" << endl;
-  
-  // Loop over reading in fields
   indent(f_service_) <<
-    "while (true)" << endl;
-
-    scope_up(f_service_);
-    
-    // Read beginning field marker
-    indent(f_service_) <<
-      "_iprot->readFieldBegin(_itrans, " <<
-      fname << ", " << ftype << ", " << fid << ");" << endl;
-    
-    // Check for field STOP marker
-    indent(f_service_) <<
-      "if (" << ftype << " == facebook::thrift::protocol::T_STOP) { break; }" << endl;
-    
-    // Switch statement on the field we are reading
-    indent(f_service_) <<
-      "switch (" << fid << ")" << endl;
-
-      scope_up(f_service_);
-    
-      // Generate deserialization code for known cases
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        indent(f_service_) <<
-          "case " << (*f_iter)->get_key() << ":" << endl;
-        indent_up();
-        generate_deserialize_field(*f_iter, prefix);
-        indent(f_service_) <<
-          "break;" << endl;
-        indent_down();
-      }
-      
-      // In the default case we skip the field
-      f_service_ <<
-        indent() << "default:" << endl <<
-        indent() << "  _iprot->skip(_itrans, " << ftype << ");" << endl <<
-        indent() << "  break;" << endl;
-      
-      scope_down(f_service_);
-
-    // Read field end marker
-    indent(f_service_) <<
-      "_iprot->readFieldEnd(_itrans);" << endl;
-    
-    scope_down(f_service_);
-      
-  indent(f_service_) <<
-    "_iprot->readStructEnd(_itrans);" << endl;
-
-  scope_down(f_service_);
+    "xfer += read_struct_" << tstruct->get_name() << "(iprot, itrans, " << prefix << ");" << endl;
 }
 
 void t_cpp_generator::generate_deserialize_container(t_type* ttype,
@@ -710,24 +1025,24 @@
   string etype = tmp("_etype");
   
   indent(f_service_) <<
-    "int32_t " << size << ";" << endl;
+    "uint32_t " << size << ";" << endl;
   
   // Declare variables, read header
   if (ttype->is_map()) {
     f_service_ <<
       indent() << "facebook::thrift::protocol::TType " << ktype << ";" << endl <<
       indent() << "facebook::thrift::protocol::TType " << vtype << ";" << endl <<
-      indent() << "_iprot->readMapBegin(_itrans, " <<
+      indent() << "iprot->readMapBegin(itrans, " <<
                    ktype << ", " << vtype << ", " << size << ");" << endl;
   } else if (ttype->is_set()) {
     f_service_ <<
       indent() << "facebook::thrift::protocol::TType " << etype << ";" << endl <<
-      indent() << "_iprot->readSetBegin(_itrans, " <<
+      indent() << "iprot->readSetBegin(itrans, " <<
                    etype << ", " << size << ");" << endl;
   } else if (ttype->is_list()) {
     f_service_ <<
       indent() << "facebook::thrift::protocol::TType " << etype << ";" << endl <<
-      indent() << "_iprot->readListBegin(_itrans, " <<
+      indent() << "iprot->readListBegin(itrans, " <<
                    etype << ", " << size << ");" << endl;
   }
 
@@ -735,7 +1050,7 @@
   // For loop iterates over elements
   string i = tmp("_i");
   indent(f_service_) <<
-    "int32_t " << i << ";" << endl;
+    "uint32_t " << i << ";" << endl;
   indent(f_service_) <<
     "for (" <<
     i << " = 0; " << i << " < " << size << "; ++" << i << ")" << endl;
@@ -754,11 +1069,11 @@
 
   // Read container end
   if (ttype->is_map()) {
-    indent(f_service_) << "_iprot->readMapEnd(_itrans);" << endl;
+    indent(f_service_) << "iprot->readMapEnd(itrans);" << endl;
   } else if (ttype->is_set()) {
-    indent(f_service_) << "_iprot->readSetEnd(_itrans);" << endl;
+    indent(f_service_) << "iprot->readSetEnd(itrans);" << endl;
   } else if (ttype->is_list()) {
-    indent(f_service_) << "_iprot->readListEnd(_itrans);" << endl;
+    indent(f_service_) << "iprot->readListEnd(itrans);" << endl;
   }
 
   scope_down(f_service_);
@@ -835,9 +1150,9 @@
       prefix + tfield->get_name();
   }
   
-  if (type->is_struct()) {
+  if (type->is_struct() || type->is_xception()) {
     generate_serialize_struct((t_struct*)(tfield->get_type()),
-                              prefix + tfield->get_name() + ".");
+                              prefix + tfield->get_name());
   } else if (type->is_container()) {
     generate_serialize_container(tfield->get_type(),
                                  prefix + tfield->get_name());
@@ -845,7 +1160,7 @@
 
     string name = prefix + tfield->get_name();
     indent(f_service_) <<
-      "_oprot->";
+      "xfer += oprot->";
     
     if (type->is_base_type()) {
       t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -855,28 +1170,25 @@
           "compiler error: cannot serialize void field in a struct: " + name;
         break;
       case t_base_type::TYPE_STRING:
-        f_service_ << "writeString(_otrans, " << name << ");";
+        f_service_ << "writeString(otrans, " << name << ");";
         break;
       case t_base_type::TYPE_BYTE:
-        f_service_ << "writeByte(_otrans, " << name << ");";
+        f_service_ << "writeByte(otrans, " << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        f_service_ << "writeI16(otrans, " << name << ");";
         break;
       case t_base_type::TYPE_I32:
-        f_service_ << "writeI32(_otrans, " << name << ");";
-        break;
-      case t_base_type::TYPE_U32:
-        f_service_ << "writeU32(_otrans, " << name << ");";
+        f_service_ << "writeI32(otrans, " << name << ");";
         break;
       case t_base_type::TYPE_I64:
-        f_service_ << "writeI64(_otrans, " << name << ");";
-        break;
-      case t_base_type::TYPE_U64:
-        f_service_ << "writeU64(_otrans, " << name << ");";
+        f_service_ << "writeI64(otrans, " << name << ");";
         break;
       default:
-        throw "compiler error: no C++ name for base type " + tbase;
+        throw "compiler error: no C++ writer for base type " + tbase + name;
       }
     } else if (type->is_enum()) {
-      f_service_ << "writeI32(_otrans, (int32_t)" << name << ");";
+      f_service_ << "writeI32(otrans, (int32_t)" << name << ");";
     }
     f_service_ << endl;
   } else {
@@ -895,32 +1207,8 @@
  */
 void t_cpp_generator::generate_serialize_struct(t_struct* tstruct,
                                                 string prefix) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  scope_up(f_service_);
   indent(f_service_) <<
-    "_oprot->writeStructBegin(_otrans, \"" << name << "\");" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    // Write field header
-    indent(f_service_) <<
-      "_oprot->writeFieldBegin(_otrans, " <<
-      "\"" << (*f_iter)->get_name() << "\", " <<
-      type_to_enum((*f_iter)->get_type()) << ", " <<
-      (*f_iter)->get_key() << ");" << endl;
-    // Write field contents
-    generate_serialize_field(*f_iter, prefix);
-    // Write field closer
-    indent(f_service_) <<
-      "_oprot->writeFieldEnd(_otrans);" << endl;
-  }
-  // Write the struct map
-  f_service_ <<
-    indent() << "_oprot->writeFieldStop(_otrans);" << endl <<
-    indent() << "_oprot->writeStructEnd(_otrans);" << endl;
-
-  scope_down(f_service_);
+    "xfer += write_struct_" << tstruct->get_name() << "(oprot, otrans, " << prefix << ");" << endl;
 }
 
 void t_cpp_generator::generate_serialize_container(t_type* ttype,
@@ -929,18 +1217,18 @@
   
   if (ttype->is_map()) {
     indent(f_service_) <<
-      "_oprot->writeMapBegin(_otrans, " <<
+      "xfer += oprot->writeMapBegin(otrans, " <<
       type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
       type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
       prefix << ".size());" << endl;
   } else if (ttype->is_set()) {
     indent(f_service_) <<
-      "_oprot->writeSetBegin(_otrans, " <<
+      "xfer += oprot->writeSetBegin(otrans, " <<
       type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
       prefix << ".size());" << endl;
   } else if (ttype->is_list()) {
     indent(f_service_) <<
-      "_oprot->writeListBegin(_otrans, " <<
+      "xfer += oprot->writeListBegin(otrans, " <<
       type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
       prefix << ".size());" << endl;
   }
@@ -962,20 +1250,20 @@
     } else if (ttype->is_list()) {
       generate_serialize_list_element((t_list*)ttype, iter);
     }
+
+    scope_down(f_service_);
     
     if (ttype->is_map()) {
       indent(f_service_) <<
-        "_oprot->writeMapEnd(_otrans);" << endl;
+        "xfer += oprot->writeMapEnd(otrans);" << endl;
     } else if (ttype->is_set()) {
       indent(f_service_) <<
-        "_oprot->writeSetEnd(_otrans);" << endl;
+        "xfer += oprot->writeSetEnd(otrans);" << endl;
     } else if (ttype->is_list()) {
       indent(f_service_) <<
-        "_oprot->writeListEnd(_otrans);" << endl;
-    }
-    
-    scope_down(f_service_);
- 
+        "xfer += oprot->writeListEnd(otrans);" << endl;
+    }    
+
   scope_down(f_service_);  
 }
 
@@ -1011,6 +1299,51 @@
 }
 
 /**
+ * Opens namespace.
+ *
+ * @param ns The namepsace, w/ periods in it
+ * @return Namespaces
+ */
+string t_cpp_generator::namespace_open(string ns) {
+  if (ns.size() == 0) {
+    return "";
+  }
+  string result = "";
+  string::size_type loc;
+  while ((loc = ns.find(".")) != string::npos) {
+    result += "namespace ";
+    result += ns.substr(0, loc);
+    result += " { ";
+    ns = ns.substr(loc+1);
+  }
+  if (ns.size() > 0) {
+    result += "namespace " + ns + " { ";
+  }
+  return result;
+}
+
+/**
+ * Closes namespace.
+ *
+ * @param ns The namepsace, w/ periods in it
+ * @return Namespaces
+ */
+string t_cpp_generator::namespace_close(string ns) {
+  if (ns.size() == 0) {
+    return "";
+  }
+  string result = "}";
+  string::size_type loc;
+  while ((loc = ns.find(".")) != string::npos) {
+    result += "}";
+    ns = ns.substr(loc+1);
+  }
+  result += " // namespace";
+  return result;
+}
+
+
+/**
  * Returns a C++ type name
  *
  * @param ttype The type
@@ -1046,17 +1379,15 @@
   case t_base_type::TYPE_STRING:
     return "std::string";
   case t_base_type::TYPE_BYTE:
-    return "uint8_t";
+    return "int8_t";
+  case t_base_type::TYPE_I16:
+    return "int16_t";
   case t_base_type::TYPE_I32:
     return "int32_t";
-  case t_base_type::TYPE_U32:
-    return "uint32_t";
   case t_base_type::TYPE_I64:
     return "int64_t";
-  case t_base_type::TYPE_U64:
-    return "uint64_t";
   default:
-    throw "compiler error: no C++ name for base type " + tbase;
+    throw "compiler error: no C++ base type name for base type " + tbase;
   }
 }
 
@@ -1083,10 +1414,9 @@
         result += " = \"\"";
         break;
       case t_base_type::TYPE_BYTE:
+      case t_base_type::TYPE_I16:
       case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_U32:
       case t_base_type::TYPE_I64:
-      case t_base_type::TYPE_U64:
         result += " = 0";
         break;
       default:
@@ -1150,19 +1480,19 @@
       return "facebook::thrift::protocol::T_STRING";
     case t_base_type::TYPE_BYTE:
       return "facebook::thrift::protocol::T_BYTE";
+    case t_base_type::TYPE_I16:
+      return "facebook::thrift::protocol::T_I16";
     case t_base_type::TYPE_I32:
       return "facebook::thrift::protocol::T_I32";
-    case t_base_type::TYPE_U32:
-      return "facebook::thrift::protocol::T_U32";
     case t_base_type::TYPE_I64:
       return "facebook::thrift::protocol::T_I64";
-    case t_base_type::TYPE_U64:
-      return "facebook::thrift::protocol::T_U64";
     }
   } else if (type->is_enum()) {
     return "facebook::thrift::protocol::T_I32";
   } else if (type->is_struct()) {
     return "facebook::thrift::protocol::T_STRUCT";
+  } else if (type->is_xception()) {
+    return "facebook::thrift::protocol::T_STRUCT";
   } else if (type->is_map()) {
     return "facebook::thrift::protocol::T_MAP";
   } else if (type->is_set()) {
diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h
index 801c06c..48cdb4c 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.h
+++ b/compiler/cpp/src/generate/t_cpp_generator.h
@@ -24,22 +24,30 @@
   /** Init and close methods */
 
   void init_generator(t_program *tprogram);
-  void close_generator();
+  void close_generator(t_program *tprogram);
 
   /** 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);
+  void generate_typedef  (t_typedef*  ttypedef);
+  void generate_enum     (t_enum*     tenum);
+  void generate_struct   (t_struct*   tstruct);
+  void generate_service  (t_service*  tservice);
+
+  void generate_struct_definition (std::ofstream& out, t_struct* tstruct);
+  void generate_struct_reader     (std::ofstream& out, t_struct* tstruct);
+  void generate_struct_writer     (std::ofstream& out, t_struct* tstruct);
+  void generate_struct_result_writer (std::ofstream& out, t_struct* tstruct);
 
   /** Service-level generation functions */
 
   void generate_service_interface (t_service* tservice);
+  void generate_service_helpers   (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);
 
+  void generate_function_helpers  (t_function* tfunction);
+
   /** Serialization constructs */
 
   void generate_deserialize_field        (t_field*    tfield, 
@@ -80,6 +88,8 @@
 
   /** Helper rendering functions */
 
+  std::string namespace_open(std::string ns);
+  std::string namespace_close(std::string ns);
   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);
diff --git a/compiler/cpp/src/generate/t_generator.cc b/compiler/cpp/src/generate/t_generator.cc
index d68e66d..99baf33 100644
--- a/compiler/cpp/src/generate/t_generator.cc
+++ b/compiler/cpp/src/generate/t_generator.cc
@@ -36,6 +36,13 @@
     generate_struct(*st_iter);
   }
 
+  // Generate xceptions
+  vector<t_struct*> xceptions = tprogram->get_xceptions();
+  vector<t_struct*>::iterator x_iter;
+  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+    generate_xception(*x_iter);
+  }
+
   // Generate services
   vector<t_service*> services = tprogram->get_services();
   vector<t_service*>::iterator sv_iter;
@@ -45,5 +52,5 @@
   }
 
   // Close the generator
-  close_generator();
+  close_generator(tprogram);
 }
diff --git a/compiler/cpp/src/generate/t_generator.h b/compiler/cpp/src/generate/t_generator.h
index be0b83e..16d8084 100644
--- a/compiler/cpp/src/generate/t_generator.h
+++ b/compiler/cpp/src/generate/t_generator.h
@@ -29,14 +29,17 @@
   /** Optional methods that may be imlemented by subclasses. */
 
   virtual void init_generator    (t_program*  tprogram) {}
-  virtual void close_generator   () {}
+  virtual void close_generator   (t_program*  tprogram) {}
 
   /** Pure virtual methods implemented by the generator subclasses. */
 
-  virtual void generate_typedef  (t_typedef*  ttypedef) = 0;
-  virtual void generate_enum     (t_enum*     tenum)    = 0;
-  virtual void generate_struct   (t_struct*   tstruct)  = 0;
-  virtual void generate_service  (t_service*  tservice) = 0;
+  virtual void generate_typedef  (t_typedef*  ttypedef)  = 0;
+  virtual void generate_enum     (t_enum*     tenum)     = 0;
+  virtual void generate_struct   (t_struct*   tstruct)   = 0;
+  virtual void generate_xception (t_struct*   txception) {
+    generate_struct(txception);
+  }
+  virtual void generate_service  (t_service*  tservice)  = 0;
 
   /** Method to get the program name, may be overridden */
 
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index 13b5022..f112407 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -49,7 +49,7 @@
 /**
  * Does nothing in Java
  */
-void t_java_generator::close_generator() {}
+void t_java_generator::close_generator(t_program *tprogram) {}
 
 /**
  * Generates a typedef. This is not done in Java.
@@ -583,15 +583,9 @@
       case t_base_type::TYPE_I32:
         f_service_ << "readI32(_itrans);";
         break;
-      case t_base_type::TYPE_U32:
-        f_service_ << "readU32(_itrans);";
-        break;
       case t_base_type::TYPE_I64:
         f_service_ << "readI64(_itrans);";
         break;
-      case t_base_type::TYPE_U64:
-        f_service_ << "readU64(_itrans);";
-        break;
       default:
         throw "compiler error: no C++ name for base type " + tbase;
       }
@@ -846,15 +840,9 @@
       case t_base_type::TYPE_I32:
         f_service_ << "writeI32(_otrans, " << name << ");";
         break;
-      case t_base_type::TYPE_U32:
-        f_service_ << "writeU32(_otrans, " << name << ");";
-        break;
       case t_base_type::TYPE_I64:
         f_service_ << "writeI64(_otrans, " << name << ");";
         break;
-      case t_base_type::TYPE_U64:
-        f_service_ << "writeU64(_otrans, " << name << ");";
-        break;
       default:
         throw "compiler error: no C++ name for base type " + tbase;
       }
@@ -1066,10 +1054,8 @@
   case t_base_type::TYPE_BYTE:
     return "byte";
   case t_base_type::TYPE_I32:
-  case t_base_type::TYPE_U32:
     return (in_container ? "Integer" : "int");
   case t_base_type::TYPE_I64:
-  case t_base_type::TYPE_U64:
     return (in_container ? "Long" : "long");
   default:
     throw "compiler error: no C++ name for base type " + tbase;
@@ -1099,9 +1085,7 @@
         break;
       case t_base_type::TYPE_BYTE:
       case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_U32:
       case t_base_type::TYPE_I64:
-      case t_base_type::TYPE_U64:
         result += " = 0";
         break;
     }
@@ -1168,12 +1152,8 @@
       return "TType.BYTE";
     case t_base_type::TYPE_I32:
       return "TType.I32";
-    case t_base_type::TYPE_U32:
-      return "TType.U32";
     case t_base_type::TYPE_I64:
       return "TType.I64";
-    case t_base_type::TYPE_U64:
-      return "TType.U64";
     }
   } else if (type->is_enum()) {
     return "TType.I32";
diff --git a/compiler/cpp/src/generate/t_java_generator.h b/compiler/cpp/src/generate/t_java_generator.h
index 3dd4dbd..0fa9074 100644
--- a/compiler/cpp/src/generate/t_java_generator.h
+++ b/compiler/cpp/src/generate/t_java_generator.h
@@ -24,7 +24,7 @@
   /** Init and close methods */
 
   void init_generator(t_program *tprogram);
-  void close_generator();
+  void close_generator(t_program *tprogram);
 
   /** Program-level generation functions */
 
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index 09a39a6..efd24c5 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -15,7 +15,7 @@
   mkdir(T_PHP_DIR, S_IREAD | S_IWRITE | S_IEXEC);
 
   // Make output file
-  string f_types_name = string(T_PHP_DIR)+"/"+program_name_+"Types.php";
+  string f_types_name = string(T_PHP_DIR)+"/"+program_name_+"_types.php";
   f_types_.open(f_types_name.c_str());
 
   // Print header
@@ -30,13 +30,13 @@
  */
 string t_php_generator::php_includes() {
   return
-    string("require_once THRIFT_ROOT.'/Thrift.php';\n\n");
+    string("require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';\n\n");
 }
 
 /**
  * Does nothing in PHP
  */
-void t_php_generator::close_generator() {
+void t_php_generator::close_generator(t_program *tprogram) {
   // Close types file
   f_types_ << "?>" << endl;
   f_types_.close();
@@ -101,6 +101,27 @@
   f_types_ << "}" << endl << endl;
 }
 
+void t_php_generator::generate_struct(t_struct* tstruct) {
+  generate_php_struct(tstruct, false);
+}
+
+/**
+ * Generates a struct definition for a thrift exception. Basically the same
+ * as a struct but extends the Exception class.
+ *
+ * @param txception The struct definition
+ */
+void t_php_generator::generate_xception(t_struct* txception) {
+  generate_php_struct(txception, true);  
+}
+
+void t_php_generator::generate_php_struct(t_struct* tstruct,
+                                          bool is_exception) {
+  generate_php_struct_definition(f_types_, tstruct, is_exception);
+  generate_php_struct_reader(f_types_, tstruct);
+  generate_php_struct_writer(f_types_, tstruct);
+}
+
 /**
  * Generates a struct definition for a thrift data type. This is nothing in PHP
  * where the objects are all just associative arrays (unless of course we
@@ -108,30 +129,206 @@
  *
  * @param tstruct The struct definition
  */
-void t_php_generator::generate_struct(t_struct* tstruct) {
-  f_types_ <<
-    "class " << tstruct->get_name() << " {" << endl;
-  indent_up();
-
+void t_php_generator::generate_php_struct_definition(ofstream& out,
+                                                     t_struct* tstruct,
+                                                     bool is_exception) {
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter; 
+
+  out <<
+    "class " << tstruct->get_name();
+  if (is_exception) {
+    out << " extends Exception";
+  }
+  out <<
+    " {" << endl;
+  indent_up();
+
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(f_types_) <<
-      "public " << declare_field(*m_iter, true) << endl;
+    // This fills in default values, as opposed to nulls
+    //indent(out) <<
+    //"public " << declare_field(*m_iter, true) << endl;
+
+    indent(out) <<
+      "public $" << (*m_iter)->get_name() << " = null;" << endl;
   }
  
   indent_down();
 
-  f_types_ <<
+  out <<
+    indent() << "}" << endl <<
+    endl;
+}
+
+void t_php_generator::generate_php_struct_reader(ofstream& out,
+                                                 t_struct* tstruct) {
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  indent(out) <<
+    "function read_struct_" << tstruct->get_name() <<
+    "($iprot, $itrans, &$value) " << endl;
+  scope_up(out);
+
+  out <<
+    indent() << "$xfer = 0;" << endl <<
+    indent() << "$fname = null;" << endl <<
+    indent() << "$ftype = 0;" << endl <<
+    indent() << "$fid = 0;" << endl;
+
+  // Declare stack tmp variables
+  if (!binary_inline_) {
+    indent(out) <<
+      "$xfer += $iprot->readStructBegin($itrans, $fname);" << endl;   
+  }
+
+  // Loop over reading in fields
+  indent(out) <<
+    "while (true)" << endl;
+
+    scope_up(out);
+    
+    // Read beginning field marker
+    if (binary_inline_) {
+      t_field fftype(g_program->get_byte_type(), "ftype");
+      t_field ffid(g_program->get_i16_type(), "fid");
+      generate_deserialize_field(out, &fftype);
+      out <<
+        indent() << "if ($ftype == TType::STOP) {" << endl <<
+        indent() << "  break;" << endl <<
+        indent() << "}" << endl;      
+      generate_deserialize_field(out, &ffid);
+    } else {
+      indent(out) <<
+        "$xfer += $iprot->readFieldBegin($itrans, $fname, $ftype, $fid);" << endl;
+      // Check for field STOP marker and break
+      indent(out) <<
+        "if ($ftype == TType::STOP) {" << endl;
+      indent_up();
+      indent(out) <<
+        "break;" << endl;
+      indent_down();
+      indent(out) <<
+        "}" << endl;
+    }   
+   
+    // Switch statement on the field we are reading
+    indent(out) <<
+      "switch ($fid)" << endl;
+
+      scope_up(out);
+    
+      // Generate deserialization code for known cases
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        indent(out) <<
+          "case " << (*f_iter)->get_key() << ":" << endl;
+        indent_up();
+        generate_deserialize_field(out, *f_iter, "value->");
+        indent(out) <<
+          "break;" << endl;
+        indent_down();
+      }
+      
+      // In the default case we skip the field
+      out <<
+        indent() <<  "default:" << endl <<
+        indent() <<  "  $xfer += $iprot->skip($itrans, $ftype);" << endl <<
+        indent() <<  "  break;" << endl;
+      
+      scope_down(out);
+      
+    if (!binary_inline_) {
+      // Read field end marker
+      indent(out) <<
+        "$xfer += $iprot->readFieldEnd($itrans);" << endl;
+    }
+    
+    scope_down(out);
+    
+  if (!binary_inline_) {
+    indent(out) <<
+      "$xfer += $iprot->readStructEnd($itrans);" << endl;
+  }
+
+  indent(out) <<
+    "return $xfer;" << endl;
+
+  indent_down();
+  out <<
+    indent() << "}" << endl <<
+    endl;
+}
+
+void t_php_generator::generate_php_struct_writer(ofstream& out,
+                                                 t_struct* tstruct) {
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  if (binary_inline_) {
+    indent(out) <<
+      "function write_struct_" << name <<
+      "(&$_output, &$value) {" << endl;
+  } else {
+    indent(out) <<
+      "function write_struct_" << name <<
+      "($oprot, $otrans, &$value) {" << endl;
+  }
+  indent_up();
+  
+  indent(out) <<
+    "$xfer = 0;" << endl;
+
+  if (!binary_inline_) {
+    indent(out) <<
+      "$xfer += $oprot->writeStructBegin($otrans, '" << name << "');" << endl;
+  }
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    // Write field header
+    if (binary_inline_) {
+      out <<
+        indent() << "$_output .= pack('c', " << type_to_enum((*f_iter)->get_type()) << ");" << endl <<
+        indent() << "$_output .= pack('n', " << (*f_iter)->get_key() << ");" << endl;
+    } else {
+      indent(out) <<
+        "$xfer += $oprot->writeFieldBegin($otrans, " <<
+        "'" << (*f_iter)->get_name() << "', " <<
+        type_to_enum((*f_iter)->get_type()) << ", " <<
+        (*f_iter)->get_key() << ");" << endl;
+    }
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "value->");
+
+    // Write field closer
+    if (!binary_inline_) {
+      indent(out) <<
+        "$xfer += $oprot->writeFieldEnd($otrans);" << endl;
+    }
+  }
+
+  if (binary_inline_) {
+    out <<
+      indent() << "$_output .= pack('c', TType::STOP);" << endl;
+  } else {
+    // Write the struct map
+    out <<
+      indent() << "$xfer += $oprot->writeFieldStop($otrans);" << endl <<
+      indent() << "$xfer += $oprot->writeStructEnd($otrans);" << endl;
+  }
+
+  out <<
+    indent() << "return $xfer;" << endl;
+
+  indent_down();
+  out <<
     indent() << "}" << endl <<
     endl;
 }
 
 /**
- * Generates a thrift service. In C++, this comprises an entirely separate
- * header and source file. The header file defines the methods and includes
- * the data types defined in the main header file, and the implementation
- * file contains implementations of the basic printer and default interfaces.
+ * Generates a thrift service.
  *
  * @param tservice The service definition
  */
@@ -145,12 +342,13 @@
     php_includes();
 
   f_service_ <<
-    "require_once dirname(__FILE__).'/" << service_name_ << "Types.php';" << endl << endl;
+    "require_once dirname(__FILE__).'/" << service_name_ << "_types.php';" << endl << endl;
 
   // Generate the three main parts of the service (well, two for now in PHP)
   generate_service_interface(tservice);
-  // generate_service_server(tservice);
   generate_service_client(tservice);
+  generate_service_helpers(tservice);
+  // generate_service_server(tservice);
   
   // Close service file
   f_service_ << "?>" << endl;
@@ -158,6 +356,50 @@
 }
 
 /**
+ * Generates helper functions for a service.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_php_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter;
+
+  f_service_ <<
+    "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl;
+
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_php_struct_definition(f_service_, ts, false);
+    generate_php_struct_reader(f_service_, ts);
+    generate_php_struct_writer(f_service_, ts);
+    generate_php_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_php_generator::generate_php_function_helpers(t_function* tfunction) {
+  t_struct result(tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_php_struct_definition(f_service_, &result, false);
+  generate_php_struct_reader(f_service_, &result);
+}
+
+/**
  * Generates a service interface definition.
  *
  * @param tservice The service to generate a header definition for
@@ -191,14 +433,20 @@
   // Private members
   f_service_ <<
     indent() << "private $_itrans = null;" << endl <<
-    indent() << "private $_otrans = null;" << endl << endl;
+    indent() << "private $_otrans = null;" << endl <<
+    endl;
 
   if (!binary_inline_) {
     f_service_ <<
-      indent() << "private $_iprot = null;"  << endl <<
-      indent() << "private $_oprot = null;"  << endl << endl;
+      indent() << "private $_iprot = null;" << endl <<
+      indent() << "private $_oprot = null;" << endl <<
+      endl;
   }
 
+  f_service_ <<
+    indent() << "private $_seqid = 0;" << endl <<
+    endl;
+
   // Constructor function
   f_service_ <<
     indent() << "public function __construct() {" << endl <<
@@ -230,92 +478,176 @@
 
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::const_iterator f_iter; 
+  vector<t_function*>::const_iterator f_iter;    
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* arg_struct = (*f_iter)->get_arglist();
+    const vector<t_field*>& fields = arg_struct->get_members();
+    vector<t_field*>::const_iterator fld_iter;
     string funname = (*f_iter)->get_name();
 
     // Open function
     indent(f_service_) <<
       "public function " << function_signature(*f_iter) << endl;
     scope_up(f_service_);
+      indent(f_service_) <<
+        "$this->send_" << funname << "(";
 
-    // Serialize the request header
-    if (binary_inline_) {
-      f_service_ <<
-        indent() << "$_output = '';" << endl <<
-        indent() << "$_output .= pack('c', TType::STRING);" << endl <<
-        indent() << "$_output .= strrev(pack('l', 0));" << endl <<
-        indent() << "$_output .= strrev(pack('l', strlen('" << funname << "')));" << endl <<
-        indent() << "$_output .= '" << funname << "';" << endl <<
-        indent() << "$_output .= pack('c', TType::STRUCT);" << endl <<
-        indent() << "$_output .= strrev(pack('l', 1));" << endl;
-    } else {
-      f_service_ <<
-        indent() << "$this->_oprot->writeStructBegin($this->_otrans, 'function');" << endl <<
-        indent() << "$this->_oprot->writeFieldBegin($this->_otrans, 'name', TType::STRING, 0);"  << endl <<
-        indent() << "$this->_oprot->writeString($this->_otrans, '" << funname << "');" << endl <<
-        indent() << "$this->_oprot->writeFieldEnd($this->_otrans);" << endl <<
-        indent() << "$this->_oprot->writeFieldBegin($this->_otrans, 'args', TType::STRUCT, 1);" << endl;
-    }
+      bool first = true;
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        if (first) {
+          first = false;
+        } else {
+          f_service_ << ", ";
+        }
+        f_service_ << "$" << (*fld_iter)->get_name();
+      }
+      f_service_ << ");" << endl;
 
-    // Serialize request arguments
-    generate_serialize_struct((*f_iter)->get_arglist());
+      if (!(*f_iter)->is_async()) {
+        f_service_ << indent();
+        if (!(*f_iter)->get_returntype()->is_void()) {
+          f_service_ << "return ";
+        }
+        f_service_ <<
+          "$this->recv_" << funname << "();" << endl;
+      }
+    scope_down(f_service_);
+    f_service_ << endl;
 
-    // Write to the stream
-    if (binary_inline_) { 
-      f_service_ <<
-        indent() << "$_output .= pack('c', TType::STOP);" << endl <<
-        indent() << "$this->_otrans->write($_output);" << endl;
-    } else {
-      f_service_ <<
-        indent() << "$this->_oprot->writeFieldEnd($this->_otrans);" << endl <<
-        indent() << "$this->_oprot->writeFieldStop($this->_otrans);" << endl <<
-        indent() << "$this->_oprot->writeStructEnd($this->_otrans);" << endl;
-    }
-      
-    // Flush the request
     indent(f_service_) <<
-      "$this->_otrans->flush();" << endl;
+      "public function send_" << function_signature(*f_iter) << endl;
+    scope_up(f_service_);  
 
-    // Read the response
-    t_struct result_struct((*f_iter)->get_name() + "_result");
-    t_field result_field((*f_iter)->get_returntype(), "_result");
+      std::string argsname = (*f_iter)->get_name() + "_args";
 
-    // Add a field to the return struct if non void
-    if (!(*f_iter)->get_returntype()->is_void()) {
+      // Serialize the request header
+      if (binary_inline_) {
+        f_service_ <<
+          indent() << "$_output = '';" << endl <<
+          indent() << "$_output .= pack('N', strlen('" << funname << "'));" << endl <<
+          indent() << "$_output .= '" << funname << "';" << endl <<
+          indent() << "$_output .= pack('cN', TMessageType::CALL, $this->seqid);" << endl;
+      } else {
+        f_service_ <<
+          indent() << "$this->_oprot->writeMessageBegin($this->_otrans, '" << (*f_iter)->get_name() << "', TMessageType::CALL, $this->seqid);" << endl;
+      }
+      
+      f_service_ <<
+        indent() << "$__args = new " << argsname << "();" << endl;
+      
+      for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+        f_service_ <<
+          indent() << "$__args->" << (*fld_iter)->get_name() << " = $" << (*fld_iter)->get_name() << ";" << endl;
+      }
+           
+      // Write to the stream
+      if (binary_inline_) { 
+        f_service_ <<
+          indent() << "write_struct_" << argsname << "($_output, $__args);" << endl <<
+          indent() << "$this->_otrans->write($_output);" << endl;
+      } else {
+        f_service_ <<
+          indent() << "write_struct_" << argsname << "($this->_oprot, $this->_otrans, $__args);" << endl <<
+          indent() << "$this->_oprot->writeMessageEnd($this->_otrans);" << endl;
+      }
+      
+      // Flush the request
       indent(f_service_) <<
-        declare_field(&result_field, true, true) << endl;
-      result_struct.append(&result_field);
-    }
+        "$this->_otrans->flush();" << endl;
+      
+      
+    scope_down(f_service_);
+      
 
-    // Deserialize response struct
-    generate_deserialize_struct(&result_struct);
+    if (!(*f_iter)->is_async()) {
+      std::string resultname = (*f_iter)->get_name() + "_result";
+      t_struct noargs;
+      
+      t_function recv_function((*f_iter)->get_returntype(),
+                               string("recv_") + (*f_iter)->get_name(),
+                               &noargs);
+      // Open function
+      f_service_ <<
+        endl <<
+        indent() << "public function " << function_signature(&recv_function) << endl;
+      scope_up(f_service_);
 
-    // Careful, only return _result if not a void function
-    if (!(*f_iter)->get_returntype()->is_void()) {
-      indent(f_service_) <<
-        "return $_result;" << endl;
-    } else {
-      indent(f_service_) <<
-        "return;" << endl;
-    }
+      f_service_ <<
+        indent() << "$rseqid = 0;" << endl <<
+        indent() << "$fname = null;" << endl <<
+        indent() << "$mtype = 0;" << endl <<
+        endl;
+
+      if (binary_inline_) {
+        t_field ffname(g_program->get_string_type(), "fname");
+        t_field fmtype(g_program->get_byte_type(), "mtype");
+        t_field fseqid(g_program->get_i32_type(), "rseqid");
+        generate_deserialize_field(f_service_, &ffname, "", true);
+        generate_deserialize_field(f_service_, &fmtype, "", true);
+        generate_deserialize_field(f_service_, &fseqid, "", true);
+      } else {
+        f_service_ <<
+          indent() << "$this->_iprot->readMessageBegin($this->_itrans, $fname, $mtype, $rseqid);" << endl;
+      }
+
+      // TODO(mcslee): Validate message reply here
+
+      f_service_ <<
+        indent() << "$__result = new " << resultname << "();" << endl <<
+        indent() << "read_struct_" << resultname << "($this->_iprot, $this->_otrans, $__result);" << endl;
+
+      if (!binary_inline_) {
+        f_service_ <<
+          indent() << "$this->_iprot->readMessageEnd($this->_itrans);" << endl <<
+          endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if (!(*f_iter)->get_returntype()->is_void()) {
+        f_service_ <<
+          indent() << "if ($__result->success !== null) {" << endl <<
+          indent() << "  return $__result->success;" << endl <<
+          indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ <<
+          indent() << "if ($__result->" << (*x_iter)->get_name() << " !== null) {" << endl <<
+          indent() << "  throw $__result->" << (*x_iter)->get_name() << ";" << endl <<
+          indent() << "}" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
+        indent(f_service_) <<
+          "return;" << endl;
+      } else {
+        f_service_ <<
+          indent() << "throw Exception(\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
+      }     
+    }      
 
     // Close function
     scope_down(f_service_);
     f_service_ << endl;
+    
   }
 
   indent_down();
   f_service_ <<
-    "}" << endl;
-  f_service_.close();
+    "}" << endl << endl;
 }
 
 /**
  * Deserializes a field of any type.
  */
-void t_php_generator::generate_deserialize_field(t_field* tfield,
-                                                 string prefix) {
+void t_php_generator::generate_deserialize_field(ofstream &out,
+                                                 t_field* tfield,
+                                                 string prefix,
+                                                 bool inclass) {
   t_type* type = tfield->get_type();
   while (type->is_typedef()) {
     type = ((t_typedef*)type)->get_type();
@@ -328,14 +660,17 @@
 
   string name = prefix + tfield->get_name();
 
-  if (type->is_struct()) {
-    generate_deserialize_struct((t_struct*)(tfield->get_type()),
-                                 name + "->");
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out,
+                                (t_struct*)(tfield->get_type()),
+                                 name);
   } else if (type->is_container()) {
-    generate_deserialize_container(tfield->get_type(), name);
+    generate_deserialize_container(out, tfield->get_type(), name);
   } else if (type->is_base_type() || type->is_enum()) {
 
     if (binary_inline_) {
+      std::string itrans = inclass ? "$this->_itrans" : "$itrans";
+
       if (type->is_base_type()) {
         t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
         switch (tbase) {
@@ -343,28 +678,41 @@
           throw "compiler error: cannot serialize void field in a struct: " +
             name;
           break;
-        case t_base_type::TYPE_STRING:        
-          f_service_ <<
-            indent() << "$_len = unpack('l', strrev($this->_itrans->readAll(4)));" << endl <<
+        case t_base_type::TYPE_STRING:
+          out <<
+            indent() << "$_len = unpack('N', " << itrans << "->readAll(4));" << endl <<
             indent() << "$_len = $_len[1];" << endl <<
-            indent() << "$" << name << " = $this->_itrans->readAll($_len);" << endl;
+            indent() << "if ($_len > 0x7fffffff) {" << endl <<
+            indent() << "  $_len = 0 - (($len - 1) ^ 0xffffffff);" << endl <<
+            indent() << "}" << endl <<
+            indent() << "$" << name << " = " << itrans << "->readAll($_len);" << endl;
           break;
         case t_base_type::TYPE_BYTE:
-          f_service_ <<
-            indent() << "$" << name << " = unpack('c', $this->_itrans->readAll(1));" << endl <<
+          out <<
+            indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));" << endl <<
             indent() << "$" << name << " = $" << name << "[1];" << endl;
           break;
+        case t_base_type::TYPE_I16:
+          out <<
+            indent() << "$_val = unpack('n', " << itrans << "->readAll(2));" << endl <<
+            indent() << "$_val = $_val[1];" << endl <<
+            indent() << "if ($_val > 0x7fff) {" << endl <<
+            indent() << "  $_val = 0 - (($_val - 1) ^ 0xffff);" << endl <<
+            indent() << "}" << endl <<
+            indent() << "$" << name << " = $_val;" << endl;
+          break;
         case t_base_type::TYPE_I32:
-          f_service_ <<
-            indent() << "$" << name << " = unpack('l', strrev($this->_itrans->readAll(4)));" << endl <<
-            indent() << "$" << name << " = $" << name << "[1];" << endl;
-          break;
-        case t_base_type::TYPE_U32:
-          f_service_ << "readU32($this->_itrans, $" << name << ");";
+          out <<
+            indent() << "$_val = unpack('N', " << itrans << "->readAll(4));" << endl <<
+            indent() << "$_val = $_val[1];" << endl <<
+            indent() << "if ($_val > 0x7fffffff) {" << endl <<
+            indent() << "  $_val = 0 - (($_val - 1) ^ 0xffffffff);" << endl <<
+            indent() << "}" << endl <<
+            indent() << "$" << name << " = $_val;" << endl;
           break;
         case t_base_type::TYPE_I64:
-          f_service_ <<
-            indent() << "$_arr = unpack('N2', $this->_itrans->readAll(8));" << endl <<
+          out <<
+            indent() << "$_arr = unpack('N2', " << itrans << "->readAll(8));" << endl <<
             indent() << "if ($_arr[1] & 0x80000000) {" << endl <<
             indent() << "  $_arr[1] = $_arr[1] ^ 0xFFFFFFFF;" << endl <<
             indent() << "  $_arr[2] = $_arr[2] ^ 0xFFFFFFFF;" << endl <<
@@ -373,22 +721,22 @@
             indent() << "  $" << name << " = $_arr[1]*4294967296 + $_arr[2];" << endl <<
             indent() << "}" << endl;
           break;
-        case t_base_type::TYPE_U64:
-          f_service_ << "readU64($this->_itrans, $" << name << ");";
-          break;
         default:
-          throw "compiler error: no C++ name for base type " + tbase;
+          throw "compiler error: no PHP name for base type " + tbase + tfield->get_name();
         }
       } else if (type->is_enum()) {
-        f_service_ <<
-          indent() << "$" << name << " = unpack('l', strrev($this->_itrans->readAll(4)));" << endl <<
-          indent() << "$" << name << " = $" << name << "[1];" << endl;
+          out <<
+            indent() << "$_val = unpack('N', " << itrans << "->readAll(4));" << endl <<
+            indent() << "$_val = $_val[1];" << endl <<
+            indent() << "if ($_val > 0x7fffffff) {" << endl <<
+            indent() << "  $_val = 0 - (($_val - 1) ^ 0xffffffff);" << endl <<
+            indent() << "}" << endl <<
+            indent() << "$" << name << " = $_val;" << endl;
       }
-
     } else {
 
-      indent(f_service_) <<
-        "$this->_iprot->";
+      indent(out) <<
+        "$xfer += $iprot->";
       
       if (type->is_base_type()) {
         t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -398,30 +746,27 @@
             name;
           break;
         case t_base_type::TYPE_STRING:        
-          f_service_ << "readString($this->_itrans, $" << name << ");";
+          out << "readString($itrans, $" << name << ");";
           break;
         case t_base_type::TYPE_BYTE:
-          f_service_ << "readByte($this->_itrans, $" << name << ");";
+          out << "readByte($itrans, $" << name << ");";
+          break;
+        case t_base_type::TYPE_I16:
+          out << "readI16($itrans, $" << name << ");";
           break;
         case t_base_type::TYPE_I32:
-          f_service_ << "readI32($this->_itrans, $" << name << ");";
-          break;
-        case t_base_type::TYPE_U32:
-          f_service_ << "readU32($this->_itrans, $" << name << ");";
+          out << "readI32($itrans, $" << name << ");";
           break;
         case t_base_type::TYPE_I64:
-          f_service_ << "readI64($this->_itrans, $" << name << ");";
-          break;
-        case t_base_type::TYPE_U64:
-          f_service_ << "readU64($this->_itrans, $" << name << ");";
+          out << "readI64($itrans, $" << name << ");";
           break;
         default:
-          throw "compiler error: no C++ name for base type " + tbase;
+          throw "compiler error: no PHP name for base type " + tbase;
         }
       } else if (type->is_enum()) {
-        f_service_ << "readI32($this->_itrans, $" << name << ");";
+        out << "readI32($itrans, $" << name << ");";
       }
-      f_service_ << endl;
+      out << endl;
     }
 
   } else {
@@ -436,107 +781,18 @@
  * buffer for deserialization, and that there is a variable protocol which
  * is a reference to a TProtocol serialization object.
  */
-void t_php_generator::generate_deserialize_struct(t_struct* tstruct,
+void t_php_generator::generate_deserialize_struct(ofstream &out,
+                                                  t_struct* tstruct,
                                                   string prefix) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  scope_up(f_service_);
-
-  // Read the struct fields from the protocol
-  string fid   = tmp("_fid");
-  string ftype = tmp("_ftype");
-  string fname = tmp("_name");
-
-  t_field ffid(g_program->get_i32_type(), fid);
-  t_field fftype(g_program->get_byte_type(), ftype);
-
-  f_service_ <<
-    indent() << "$" << fname << " = null;" << endl <<
-    indent() << "$" << ftype << " = null;" << endl <<
-    indent() << "$" << fid << " = 0;" << endl;
-
-  // Declare stack tmp variables
-  if (!binary_inline_) {
-    f_service_ <<
-      indent() << "$this->_iprot->readStructBegin($this->_itrans, $" << fname << ");" << endl;   
-  }
-
-  // Loop over reading in fields
-  indent(f_service_) <<
-    "while (true)" << endl;
-
-    scope_up(f_service_);
-    
-    // Read beginning field marker
-    if (binary_inline_) {
-      generate_deserialize_field(&fftype);
-      f_service_ <<
-        indent() << "if ($" << ftype << " == TType::STOP) {" << endl <<
-        indent() << "  break;" << endl <<
-        indent() << "}" << endl;      
-      generate_deserialize_field(&ffid);
-    } else {
-      indent(f_service_) <<
-        "$this->_iprot->readFieldBegin($this->_itrans, " << 
-        "$" << fname << ", $" << ftype << ", $" << fid << ");" << endl;
-
-      // Check for field STOP marker and break
-      indent(f_service_) <<
-        "if ($" << ftype << " == TType::STOP) {" << endl;
-      indent_up();
-      indent(f_service_) <<
-        "break;" << endl;
-      indent_down();
-      indent(f_service_) <<
-        "}" << endl;
-    }
-    
-   
-    // Switch statement on the field we are reading
-    indent(f_service_) <<
-      "switch ($" << fid << ")" << endl;
-
-      scope_up(f_service_);
-    
-      // Generate deserialization code for known cases
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        indent(f_service_) <<
-          "case " << (*f_iter)->get_key() << ":" << endl;
-        indent_up();
-        generate_deserialize_field(*f_iter, prefix);
-        indent(f_service_) <<
-          "break;" << endl;
-        indent_down();
-      }
-      
-      // In the default case we skip the field
-      f_service_ <<
-        indent() <<  "default:" << endl <<
-        indent() <<  "  $this->_iprot->skip($this->_itrans, $" << ftype << ");" << endl <<
-        indent() <<  "  break;" << endl;
-      
-      scope_down(f_service_);
-      
-    if (!binary_inline_) {
-      // Read field end marker
-      indent(f_service_) <<
-        "$this->_iprot->readFieldEnd($this->_itrans);" << endl;
-    }
-    
-    scope_down(f_service_);
-    
-  if (!binary_inline_) {
-    indent(f_service_) <<
-      "$this->_iprot->readStructEnd($this->_itrans);" << endl;
-  }
-
-  scope_down(f_service_);
+  out <<
+    indent() << "$" << prefix << " = new " << tstruct->get_name() << "();" << endl <<
+    indent() << "$xfer += read_struct_" << tstruct->get_name() << "($iprot, $itrans, $" << prefix << ");" << endl;
 }
 
-void t_php_generator::generate_deserialize_container(t_type* ttype,
+void t_php_generator::generate_deserialize_container(ofstream &out,
+                                                     t_type* ttype,
                                                      string prefix) {
-  scope_up(f_service_);
+  scope_up(out);
   
   string size = tmp("_size");
   string ktype = tmp("_ktype");
@@ -548,125 +804,128 @@
   t_field fvtype(g_program->get_byte_type(), vtype);
   t_field fetype(g_program->get_byte_type(), etype);
 
-  indent(f_service_) <<
+  indent(out) <<
     "$" << size << " = 0;" << endl;
   
   // Declare variables, read header
   if (ttype->is_map()) {
-    f_service_ <<
+    out <<
       indent() << "$" << ktype << " = 0;" << endl <<
       indent() << "$" << vtype << " = 0;" << endl;
     if (binary_inline_) {
-      generate_deserialize_field(&fktype);
-      generate_deserialize_field(&fvtype);
-      generate_deserialize_field(&fsize);
+      generate_deserialize_field(out, &fktype);
+      generate_deserialize_field(out, &fvtype);
+      generate_deserialize_field(out, &fsize);
     } else {
-      f_service_ <<
-        indent() << "$this->_iprot->readMapBegin($this->_itrans, " <<
+      out <<
+        indent() << "$xfer += $iprot->readMapBegin($itrans, " <<
         "$" << ktype << ", $" << vtype << ", $" << size << ");" << endl;
     }
   } else if (ttype->is_set()) {
     if (binary_inline_) {
-      generate_deserialize_field(&fetype);
-      generate_deserialize_field(&fsize);
+      generate_deserialize_field(out, &fetype);
+      generate_deserialize_field(out, &fsize);
     } else {
-      f_service_ <<
+      out <<
         indent() << "$" << etype << " = 0;" << endl <<
-        indent() << "$this->_iprot->readSetBegin($this->_itrans, " <<
+        indent() << "$xfer += $iprot->readSetBegin($itrans, " <<
         "$" << etype << ", $" << size << ");" << endl;
     }
   } else if (ttype->is_list()) {
     if (binary_inline_) {
-      generate_deserialize_field(&fetype);
-      generate_deserialize_field(&fsize);
+      generate_deserialize_field(out, &fetype);
+      generate_deserialize_field(out, &fsize);
     } else {
-      f_service_ <<
+      out <<
         indent() << "$" << etype << " = 0;" << endl <<
-        indent() << "$this->_iprot->readListBegin($this->_itrans, " <<
+        indent() << "$xfer += $iprot->readListBegin($itrans, " <<
         "$" << etype << ", $" << size << ");" << endl;
     }
   }
 
   // For loop iterates over elements
   string i = tmp("_i");
-  indent(f_service_) <<
+  indent(out) <<
     "for ($" <<
     i << " = 0; $" << i << " < $" << size << "; ++$" << i << ")" << endl;
   
-    scope_up(f_service_);
+    scope_up(out);
     
     if (ttype->is_map()) {
-      generate_deserialize_map_element((t_map*)ttype, prefix);
+      generate_deserialize_map_element(out, (t_map*)ttype, prefix);
     } else if (ttype->is_set()) {
-      generate_deserialize_set_element((t_set*)ttype, prefix);
+      generate_deserialize_set_element(out, (t_set*)ttype, prefix);
     } else if (ttype->is_list()) {
-      generate_deserialize_list_element((t_list*)ttype, prefix);
+      generate_deserialize_list_element(out, (t_list*)ttype, prefix);
     }
     
-    scope_down(f_service_);
+    scope_down(out);
 
   if (!binary_inline_) {
     // Read container end
     if (ttype->is_map()) {
-      indent(f_service_) << "$this->_iprot->readMapEnd($this->_itrans);" << endl;
+      indent(out) << "$xfer += $iprot->readMapEnd($itrans);" << endl;
     } else if (ttype->is_set()) {
-      indent(f_service_) << "$this->_iprot->readSetEnd($this->_itrans);" << endl;
+      indent(out) << "$xfer += $iprot->readSetEnd($itrans);" << endl;
     } else if (ttype->is_list()) {
-      indent(f_service_) << "$this->_iprot->readListEnd($this->_itrans);" << endl;
+      indent(out) << "$xfer += $iprot->readListEnd($itrans);" << endl;
     }
   }
 
-  scope_down(f_service_);
+  scope_down(out);
 }
 
 
 /**
  * Generates code to deserialize a map
  */
-void t_php_generator::generate_deserialize_map_element(t_map* tmap,
+void t_php_generator::generate_deserialize_map_element(ofstream &out,
+                                                       t_map* tmap,
                                                        string prefix) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
   t_field fval(tmap->get_val_type(), val);
 
-  indent(f_service_) <<
+  indent(out) <<
     declare_field(&fkey, true, true) << endl;
-  indent(f_service_) <<
+  indent(out) <<
     declare_field(&fval, true, true) << endl;
 
-  generate_deserialize_field(&fkey);
-  generate_deserialize_field(&fval);
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
 
-  indent(f_service_) <<
+  indent(out) <<
     "$" << prefix << "[$" << key << "] = $" << val << ";" << endl;
 }
 
-void t_php_generator::generate_deserialize_set_element(t_set* tset,
+void t_php_generator::generate_deserialize_set_element(ofstream &out,
+                                                       t_set* tset,
                                                        string prefix) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
-  indent(f_service_) <<
+  indent(out) <<
     "$" << elem << " = null;" << endl;
 
-  generate_deserialize_field(&felem);
+  generate_deserialize_field(out, &felem);
 
-  indent(f_service_) <<
+  indent(out) <<
     "$" << prefix << " []= $" << elem << ";" << endl;
 }
 
-void t_php_generator::generate_deserialize_list_element(t_list* tlist,
+void t_php_generator::generate_deserialize_list_element(ofstream &out,
+                                                        t_list* tlist,
                                                         string prefix) {
   string elem = tmp("_elem");
   t_field felem(tlist->get_elem_type(), elem);
 
-  indent(f_service_) <<
+  indent(out) <<
     "$" << elem << " = null;" << endl;
 
-  generate_deserialize_field(&felem);
+  generate_deserialize_field(out, &felem);
 
-  indent(f_service_) <<
+  indent(out) <<
     "$" << prefix << " []= $" << elem << ";" << endl;
 }
 
@@ -677,7 +936,8 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_php_generator::generate_serialize_field(t_field* tfield,
+void t_php_generator::generate_serialize_field(ofstream &out,
+                                               t_field* tfield,
                                                string prefix) {
   t_type* type = tfield->get_type();
   while (type->is_typedef()) {
@@ -690,11 +950,13 @@
       prefix + tfield->get_name();
   }
   
-  if (type->is_struct()) {
-    generate_serialize_struct((t_struct*)(tfield->get_type()),
-                              prefix + tfield->get_name() + "->");
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out,
+                              (t_struct*)(tfield->get_type()),
+                              prefix + tfield->get_name());
   } else if (type->is_container()) {
-    generate_serialize_container(tfield->get_type(),
+    generate_serialize_container(out,
+                                 tfield->get_type(),
                                  prefix + tfield->get_name());
   } else if (type->is_base_type() || type->is_enum()) {
 
@@ -709,40 +971,37 @@
             "compiler error: cannot serialize void field in a struct: " + name;
           break;
         case t_base_type::TYPE_STRING:
-          f_service_ <<
-            indent() << "$_output .= strrev(pack('l', strlen($" << name << ")));" << endl <<
+          out <<
+            indent() << "$_output .= pack('N', strlen($" << name << "));" << endl <<
             indent() << "$_output .= $" << name << ";" << endl;
           break;
         case t_base_type::TYPE_BYTE:
-          f_service_ <<
+          out <<
             indent() << "$_output .= pack('c', $" << name << ");" << endl;
           break;
-        case t_base_type::TYPE_I32:
-          f_service_ <<
-            indent() << "$_output .= strrev(pack('l', $" << name << "));" << endl;
+        case t_base_type::TYPE_I16:
+          out <<
+            indent() << "$_output .= pack('n', $" << name << ");" << endl;
           break;
-        case t_base_type::TYPE_U32:
-          f_service_ <<
-            indent() << "writeU32($this->_otrans, $" << name << ");" << endl;
+        case t_base_type::TYPE_I32:
+          out <<
+            indent() << "$_output .= pack('N', $" << name << ");" << endl;
           break;
         case t_base_type::TYPE_I64:
-          f_service_ << 
+          out << 
             indent() << "$_output .= pack('N2', $" << name << " >> 32, $" << name << " & 0xFFFFFFFF);" << endl;
           break;
-        case t_base_type::TYPE_U64:
-          f_service_ << "writeU64($this->_otrans, $" << name << ");";
-          break;
         default:
-          throw "compiler error: no C++ name for base type " + tbase;
+          throw "compiler error: no PHP name for base type " + tbase;
         }
       } else if (type->is_enum()) {
-        f_service_ <<
-          indent() << "$_output .= strrev(pack('l', $" << name << "));" << endl;
+        out <<
+          indent() << "$_output .= pack('N', $" << name << ");" << endl;
       }
     } else {
 
-      indent(f_service_) <<
-        "$this->_oprot->";
+      indent(out) <<
+        "$xfer += $oprot->";
       
       if (type->is_base_type()) {
         t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -752,30 +1011,27 @@
             "compiler error: cannot serialize void field in a struct: " + name;
           break;
         case t_base_type::TYPE_STRING:
-          f_service_ << "writeString($this->_otrans, $" << name << ");";
+          out << "writeString($otrans, $" << name << ");";
           break;
         case t_base_type::TYPE_BYTE:
-          f_service_ << "writeByte($this->_otrans, $" << name << ");";
+          out << "writeByte($otrans, $" << name << ");";
+          break;
+        case t_base_type::TYPE_I16:
+          out << "writeI16($otrans, $" << name << ");";
           break;
         case t_base_type::TYPE_I32:
-          f_service_ << "writeI32($this->_otrans, $" << name << ");";
-          break;
-        case t_base_type::TYPE_U32:
-          f_service_ << "writeU32($this->_otrans, $" << name << ");";
+          out << "writeI32($otrans, $" << name << ");";
           break;
         case t_base_type::TYPE_I64:
-          f_service_ << "writeI64($this->_otrans, $" << name << ");";
-          break;
-        case t_base_type::TYPE_U64:
-          f_service_ << "writeU64($this->_otrans, $" << name << ");";
+          out << "writeI64($otrans, $" << name << ");";
           break;
         default:
-          throw "compiler error: no C++ name for base type " + tbase;
+          throw "compiler error: no PHP name for base type " + tbase;
         }
       } else if (type->is_enum()) {
-        f_service_ << "writeI32($this->_otrans, $" << name << ");";
+        out << "writeI32($otrans, $" << name << ");";
       }
-      f_service_ << endl;
+      out << endl;
     }
   } else {
     printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
@@ -791,176 +1047,140 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_php_generator::generate_serialize_struct(t_struct* tstruct,
-                                                 string prefix) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  scope_up(f_service_);
-
-  if (!binary_inline_) {
-    indent(f_service_) <<
-      "$this->_oprot->writeStructBegin($this->_otrans, '" << name << "');" << endl;
-  }
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    // Write field header
-    if (binary_inline_) {
-      f_service_ <<
-        indent() << "$_output .= pack('c', " << type_to_enum((*f_iter)->get_type()) << ");" << endl <<
-        indent() << "$_output .= strrev(pack('l', " << (*f_iter)->get_key() << "));" << endl;
-    } else {
-      indent(f_service_) <<
-        "$this->_oprot->writeFieldBegin($this->_otrans, " <<
-        "'" << (*f_iter)->get_name() << "', " <<
-        type_to_enum((*f_iter)->get_type()) << ", " <<
-        (*f_iter)->get_key() << ");" << endl;
-    }
-
-    // Write field contents
-    generate_serialize_field(*f_iter, prefix);
-
-    // Write field closer
-    if (binary_inline_) {
-    } else {
-      indent(f_service_) <<
-        "$this->_oprot->writeFieldEnd($this->_otrans);" << endl;
-    }
-  }
-
+void t_php_generator::generate_serialize_struct(ofstream &out,
+                                                t_struct* tstruct,
+                                                string prefix) {
   if (binary_inline_) {
-    f_service_ <<
-      indent() << "$_output .= pack('c', TType::STOP);" << endl;
+    indent(out) <<
+      "$xfer += write_struct_" << tstruct->get_name() << "($_output, $" << prefix << ");" << endl;
   } else {
-    // Write the struct map
-    f_service_ <<
-      indent() << "$this->_oprot->writeFieldStop($this->_otrans);" << endl <<
-      indent() << "$this->_oprot->writeStructEnd($this->_otrans);" << endl;
+    indent(out) <<
+      "$xfer += write_struct_" << tstruct->get_name() << "($oprot, $otrans, $" << prefix << ");" << endl;
   }
-
-  scope_down(f_service_);
 }
 
-void t_php_generator::generate_serialize_container(t_type* ttype,
+void t_php_generator::generate_serialize_container(ofstream &out,
+                                                   t_type* ttype,
                                                    string prefix) {
-  scope_up(f_service_);
+  scope_up(out);
   
   if (ttype->is_map()) {
     if (binary_inline_) {
-      f_service_ <<
+      out <<
         indent() << "$_output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_key_type()) << ");" << endl <<
         indent() << "$_output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_val_type()) << ");" << endl <<
         indent() << "$_output .= strrev(pack('l', count($" << prefix << ")));" << endl;
     } else {
-      indent(f_service_) <<
-        "$this->_oprot->writeMapBegin($this->_otrans, " <<
+      indent(out) <<
+        "$oprot->writeMapBegin($otrans, " <<
         type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
         type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
         "count($" << prefix << "));" << endl;
     }
   } else if (ttype->is_set()) {
     if (binary_inline_) {
-      f_service_ <<
+      out <<
         indent() << "$_output .= pack('c', " << type_to_enum(((t_set*)ttype)->get_elem_type()) << ");" << endl <<
         indent() << "$_output .= strrev(pack('l', count($" << prefix << ")));" << endl;
 
     } else {
-      indent(f_service_) <<
-        "$this->_oprot->writeSetBegin($this->_otrans, " <<
+      indent(out) <<
+        "$oprot->writeSetBegin($otrans, " <<
         type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
         "count($" << prefix << "));" << endl;
     }
   } else if (ttype->is_list()) {
     if (binary_inline_) {
-      f_service_ <<
+      out <<
         indent() << "$_output .= pack('c', " << type_to_enum(((t_list*)ttype)->get_elem_type()) << ");" << endl <<
         indent() << "$_output .= strrev(pack('l', count($" << prefix << ")));" << endl;
 
     } else {
-      indent(f_service_) <<
-        "$this->_oprot->writeListBegin($this->_otrans, " <<
+      indent(out) <<
+        "$oprot->writeListBegin($otrans, " <<
         type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
         "count($" << prefix << "));" << endl;
     }
   }
 
-    scope_up(f_service_);
+    scope_up(out);
 
     if (ttype->is_map()) {
       string kiter = tmp("_kiter");
       string viter = tmp("_viter");
-      indent(f_service_) << 
+      indent(out) << 
         "foreach ($" << prefix << " as " <<
         "$" << kiter << " => $" << viter << ")" << endl;
-      scope_up(f_service_);     
-      generate_serialize_map_element((t_map*)ttype, kiter, viter);
-      scope_down(f_service_);
+      scope_up(out);     
+      generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
+      scope_down(out);
     } else if (ttype->is_set()) {
       string iter = tmp("_iter");
-      indent(f_service_) << 
+      indent(out) << 
         "foreach ($" << prefix << " as $" << iter << ")" << endl;
-      scope_up(f_service_);
-      generate_serialize_set_element((t_set*)ttype, iter);
-      scope_down(f_service_);
+      scope_up(out);
+      generate_serialize_set_element(out, (t_set*)ttype, iter);
+      scope_down(out);
     } else if (ttype->is_list()) {
       string iter = tmp("_iter");
-      indent(f_service_) << 
+      indent(out) << 
         "foreach ($" << prefix << " as $" << iter << ")" << endl;
-      scope_up(f_service_);
-      generate_serialize_list_element((t_list*)ttype, iter);
-      scope_down(f_service_);
+      scope_up(out);
+      generate_serialize_list_element(out, (t_list*)ttype, iter);
+      scope_down(out);
     }
     
- 
-    scope_down(f_service_);
+    scope_down(out);
 
   if (!binary_inline_) {
     if (ttype->is_map()) {
-      indent(f_service_) <<
-        "$this->_oprot->writeMapEnd($this->_otrans);" << endl;
+      indent(out) <<
+        "$oprot->writeMapEnd($otrans);" << endl;
     } else if (ttype->is_set()) {
-      indent(f_service_) <<
-        "$this->_oprot->writeSetEnd($this->_otrans);" << endl;
+      indent(out) <<
+        "$oprot->writeSetEnd($otrans);" << endl;
     } else if (ttype->is_list()) {
-      indent(f_service_) <<
-        "$this->_oprot->writeListEnd($this->_otrans);" << endl;
+      indent(out) <<
+        "$oprot->writeListEnd($otrans);" << endl;
     }
   }
  
-  scope_down(f_service_);  
+  scope_down(out);  
 }
 
 /**
  * Serializes the members of a map.
  *
  */
-void t_php_generator::generate_serialize_map_element(t_map* tmap,
-                                                      string kiter,
-                                                      string viter) {
+void t_php_generator::generate_serialize_map_element(ofstream &out,
+                                                     t_map* tmap,
+                                                     string kiter,
+                                                     string viter) {
   t_field kfield(tmap->get_key_type(), kiter);
-  generate_serialize_field(&kfield, "");
+  generate_serialize_field(out, &kfield, "");
 
   t_field vfield(tmap->get_val_type(), viter);
-  generate_serialize_field(&vfield, "");
+  generate_serialize_field(out, &vfield, "");
 }
 
 /**
  * Serializes the members of a set.
  */
-void t_php_generator::generate_serialize_set_element(t_set* tset,
-                                                      string iter) {
+void t_php_generator::generate_serialize_set_element(ofstream &out,
+                                                     t_set* tset,
+                                                     string iter) {
   t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(&efield, "");
+  generate_serialize_field(out, &efield, "");
 }
 
 /**
  * Serializes the members of a list.
  */
-void t_php_generator::generate_serialize_list_element(t_list* tlist,
+void t_php_generator::generate_serialize_list_element(ofstream &out,
+                                                      t_list* tlist,
                                                       string iter) {
   t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(&efield, "");
+  generate_serialize_field(out, &efield, "");
 }
 
 /**
@@ -1007,16 +1227,14 @@
     return "TString";
   case t_base_type::TYPE_BYTE:
     return "UInt8";
+  case t_base_type::TYPE_I16:
+    return "Int16";
   case t_base_type::TYPE_I32:
     return "Int32";
-  case t_base_type::TYPE_U32:
-    return "UInt32";
   case t_base_type::TYPE_I64:
     return "Int64";
-  case t_base_type::TYPE_U64:
-    return "UInt64";
   default:
-    throw "compiler error: no C++ name for base type " + tbase;
+    throw "compiler error: no PHP name for base type " + tbase;
   }
 }
 
@@ -1041,10 +1259,9 @@
         result += " = ''";
         break;
       case t_base_type::TYPE_BYTE:
+      case t_base_type::TYPE_I16:
       case t_base_type::TYPE_I32:
-      case t_base_type::TYPE_U32:
       case t_base_type::TYPE_I64:
-      case t_base_type::TYPE_U64:
         result += " = 0";
         break;
       default:
@@ -1115,14 +1332,12 @@
       return "TType::STRING";
     case t_base_type::TYPE_BYTE:
       return "TType::BYTE";
+    case t_base_type::TYPE_I16:
+      return "TType::I16";
     case t_base_type::TYPE_I32:
       return "TType::I32";
-    case t_base_type::TYPE_U32:
-      return "TType::U32";
     case t_base_type::TYPE_I64:
       return "TType::I64";
-    case t_base_type::TYPE_U64:
-      return "TType::U64";
     }
   } else if (type->is_enum()) {
     return "TType::I32";
diff --git a/compiler/cpp/src/generate/t_php_generator.h b/compiler/cpp/src/generate/t_php_generator.h
index e5fb30c..d5bc8e0 100644
--- a/compiler/cpp/src/generate/t_php_generator.h
+++ b/compiler/cpp/src/generate/t_php_generator.h
@@ -8,9 +8,6 @@
 
 #include "t_oop_generator.h"
 
-// TODO(mcslee: Paramaterize the output dir
-#define T_PHP_DIR "gen-php"
-
 /**
  * Java code generator.
  *
@@ -20,6 +17,11 @@
  public:
   t_php_generator(bool binary_inline=false) {
     binary_inline_ = binary_inline;
+    if (binary_inline_) {
+      T_PHP_DIR = "gen-phpi";
+    } else {
+      T_PHP_DIR = "gen-php";
+    }
   }
   
   ~t_php_generator() {}
@@ -27,57 +29,80 @@
   /** Init and close methods */
 
   void init_generator(t_program *tprogram);
-  void close_generator();
+  void close_generator(t_program *tprogram);
 
   /** 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);
+  void generate_typedef  (t_typedef*  ttypedef);
+  void generate_enum     (t_enum*     tenum);
+  void generate_struct   (t_struct*   tstruct);
+  void generate_xception (t_struct*   txception);
+  void generate_service  (t_service*  tservice);
+
+
+  void generate_php_struct(t_struct* tstruct, bool is_exception);
+  void generate_php_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception);
+  void generate_php_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_php_struct_writer(std::ofstream& out, t_struct* tstruct);
+
+  void generate_php_function_helpers  (t_function* tfunction);
 
   /** Service-level generation functions */
 
+  void generate_service_helpers(t_service*  tservice);
   void generate_service_interface (t_service* tservice);
   void generate_service_client    (t_service* tservice);
 
   /** Serialization constructs */
 
-  void generate_deserialize_field        (t_field*    tfield, 
+  void generate_deserialize_field        (std::ofstream &out,
+                                          t_field*    tfield, 
+                                          std::string prefix="",
+                                          bool inclass=false);
+  
+  void generate_deserialize_struct       (std::ofstream &out,
+                                          t_struct*   tstruct,
                                           std::string prefix="");
   
-  void generate_deserialize_struct       (t_struct*   tstruct,
+  void generate_deserialize_container    (std::ofstream &out,
+                                          t_type*     ttype,
                                           std::string prefix="");
   
-  void generate_deserialize_container    (t_type*     ttype,
-                                          std::string prefix="");
-  
-  void generate_deserialize_set_element  (t_set*      tset,
+  void generate_deserialize_set_element  (std::ofstream &out,
+                                          t_set*      tset,
                                           std::string prefix="");
 
-  void generate_deserialize_map_element  (t_map*      tmap,
+  void generate_deserialize_map_element  (std::ofstream &out,
+                                          t_map*      tmap,
                                           std::string prefix="");
 
-  void generate_deserialize_list_element (t_list*     tlist,
+  void generate_deserialize_list_element (std::ofstream &out,
+                                          t_list*     tlist,
                                           std::string prefix="");
 
-  void generate_serialize_field          (t_field*    tfield,
+  void generate_serialize_field          (std::ofstream &out,
+                                          t_field*    tfield,
                                           std::string prefix="");
 
-  void generate_serialize_struct         (t_struct*   tstruct,
+  void generate_serialize_struct         (std::ofstream &out,
+                                          t_struct*   tstruct,
                                           std::string prefix="");
 
-  void generate_serialize_container      (t_type*     ttype,
+  void generate_serialize_container      (std::ofstream &out,
+                                          t_type*     ttype,
                                           std::string prefix="");
 
-  void generate_serialize_map_element    (t_map*      tmap,
+  void generate_serialize_map_element    (std::ofstream &out,
+                                          t_map*      tmap,
                                           std::string kiter,
                                           std::string viter);
 
-  void generate_serialize_set_element    (t_set*      tmap,
+  void generate_serialize_set_element    (std::ofstream &out,
+                                          t_set*      tmap,
                                           std::string iter);
 
-  void generate_serialize_list_element   (t_list*     tlist,
+  void generate_serialize_list_element   (std::ofstream &out,
+                                          t_list*     tlist,
                                           std::string iter);
 
   /** Helper rendering functions */
@@ -93,8 +118,10 @@
  private:
 
   /** File streams */
+  char* T_PHP_DIR;
 
   std::ofstream f_types_;
+  std::ofstream f_helpers_;
   std::ofstream f_service_;
 
   /** Generate protocol-independent template? Or Binary inline code? */
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
index 6a7faf8..944cd66 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -95,12 +95,12 @@
 void usage() {
   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, "  -phpi   Generate PHP inlined files\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, "  --phpi   Generate PHP inlined files\n");
   //fprintf(stderr, "  -python Generate Python output files\n");
-  fprintf(stderr, "  -d      Print parse debugging to standard output\n");
+  fprintf(stderr, "  --debug      Print parse debugging to standard output\n");
   exit(1);
 }
 
@@ -124,16 +124,16 @@
   }
 
   for (i = 1; i < argc-1; i++) {
-    if (strcmp(argv[i], "-d") == 0) {
+    if (strcmp(argv[i], "--debug") == 0) {
       g_debug = 1;
-    } else if (strcmp(argv[i], "-cpp") == 0) {
+    } else if (strcmp(argv[i], "--cpp") == 0) {
       gen_cpp = true;
-    } else if (strcmp(argv[i], "-java") == 0) {
+    } else if (strcmp(argv[i], "--java") == 0) {
       gen_java = true;
-    } else if (strcmp(argv[i], "-php") == 0) {
+    } else if (strcmp(argv[i], "--php") == 0) {
       gen_php = true;
       php_inline = false;
-    } else if (strcmp(argv[i], "-phpi") == 0) {
+    } else if (strcmp(argv[i], "--phpi") == 0) {
       gen_php = true;
       php_inline = true;
     } else {
diff --git a/compiler/cpp/src/parse/t_base_type.h b/compiler/cpp/src/parse/t_base_type.h
index f6cc197..5aebba7 100644
--- a/compiler/cpp/src/parse/t_base_type.h
+++ b/compiler/cpp/src/parse/t_base_type.h
@@ -15,10 +15,9 @@
     TYPE_VOID,
     TYPE_STRING,
     TYPE_BYTE,
+    TYPE_I16,
     TYPE_I32,
-    TYPE_U32,
-    TYPE_I64,
-    TYPE_U64
+    TYPE_I64
   };
 
   t_base_type(std::string name, t_base base) :
diff --git a/compiler/cpp/src/parse/t_field.h b/compiler/cpp/src/parse/t_field.h
index fc38456..7f4d0e9 100644
--- a/compiler/cpp/src/parse/t_field.h
+++ b/compiler/cpp/src/parse/t_field.h
@@ -14,19 +14,19 @@
   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) :
+  t_field(t_type* type, std::string name, int32_t key) :
     type_(type), name_(name), key_(key) {}
 
   ~t_field() {}
 
   t_type* get_type() const { return type_; }
   const std::string& get_name() const { return name_; }
-  uint32_t get_key() const { return key_; }
+  int32_t get_key() const { return key_; }
 
  private:
   t_type* type_;
   std::string name_;
-  uint32_t key_;
+  int32_t key_;
 };
 
 #endif
diff --git a/compiler/cpp/src/parse/t_function.h b/compiler/cpp/src/parse/t_function.h
index 9e6c56a..58667d8 100644
--- a/compiler/cpp/src/parse/t_function.h
+++ b/compiler/cpp/src/parse/t_function.h
@@ -20,6 +20,20 @@
     returntype_(returntype),
     name_(name),
     arglist_(arglist),
+    async_(async) {
+    xceptions_ = new t_struct;
+  }
+
+
+  t_function(t_type* returntype,
+             std::string name,
+             t_struct* arglist,
+             t_struct* xceptions,
+             bool async=false) :
+    returntype_(returntype),
+    name_(name),
+    arglist_(arglist),
+    xceptions_(xceptions),
     async_(async) {}
 
   ~t_function() {}
@@ -27,12 +41,14 @@
   t_type*      get_returntype() const { return returntype_; }
   const std::string& get_name() const { return name_; }
   t_struct*    get_arglist()    const { return arglist_; }
+  t_struct*    get_xceptions()  const { return xceptions_; }
   bool         is_async()       const { return async_; }
 
  private:
   t_type* returntype_;
   std::string name_;
   t_struct* arglist_;
+  t_struct* xceptions_;
   bool async_;
 };
 
diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h
index cda24c6..98968ff 100644
--- a/compiler/cpp/src/parse/t_program.h
+++ b/compiler/cpp/src/parse/t_program.h
@@ -21,6 +21,7 @@
  *   Typedefs
  *   Enumerations
  *   Structs
+ *   Exceptions
  *   Services
  *
  * @author Mark Slee <mcslee@facebook.com>
@@ -28,52 +29,54 @@
 class t_program {
  public:
   t_program(std::string name) :
-    name_(name) {
+    name_(name), namespace_() {
     type_void   = new t_base_type("void",   t_base_type::TYPE_VOID);
     type_string = new t_base_type("string", t_base_type::TYPE_STRING);
     type_byte   = new t_base_type("byte",   t_base_type::TYPE_BYTE);
+    type_i16    = new t_base_type("i16",    t_base_type::TYPE_I16);
     type_i32    = new t_base_type("i32",    t_base_type::TYPE_I32);
-    type_u32    = new t_base_type("u32",    t_base_type::TYPE_U32);
     type_i64    = new t_base_type("i64",    t_base_type::TYPE_I64);
-    type_u64    = new t_base_type("u64",    t_base_type::TYPE_U64);
   }
 
   ~t_program() {
     delete type_string;
     delete type_byte;
+    delete type_i16;
     delete type_i32;
-    delete type_u32;
     delete type_i64;
-    delete type_u64;
   }
 
   // Name accessor
   const std::string& get_name() const { return name_; }
 
+  // Namespace
+  const std::string& get_namespace() const { return namespace_; }
+
   // Accessors for program elements
-  const std::vector<t_typedef*>& get_typedefs() const { return typedefs_; }
-  const std::vector<t_enum*>&    get_enums()    const { return enums_;    }
-  const std::vector<t_struct*>&  get_structs()  const { return structs_;  }
-  const std::vector<t_service*>& get_services() const { return services_; }
+  const std::vector<t_typedef*>& get_typedefs()  const { return typedefs_;  }
+  const std::vector<t_enum*>&    get_enums()     const { return enums_;     }
+  const std::vector<t_struct*>&  get_structs()   const { return structs_;   }
+  const std::vector<t_struct*>&  get_xceptions() const { return xceptions_; }
+  const std::vector<t_service*>& get_services()  const { return services_;  }
 
   // Accessors for global types
   t_type* get_void_type()   const { return type_void;   }
   t_type* get_string_type() const { return type_string; }
   t_type* get_byte_type()   const { return type_byte;   }
+  t_type* get_i16_type()    const { return type_i16;    }
   t_type* get_i32_type()    const { return type_i32;    }
-  t_type* get_u32_type()    const { return type_u32;    }
   t_type* get_i64_type()    const { return type_i64;    }
-  t_type* get_u64_type()    const { return type_u64;    }
 
   // Custom data type lookup
-  void add_custom_type(std::string name, t_type* type) {
-    custom_types_[name] = type;
-  }
   t_type* get_custom_type(std::string name) {
     return custom_types_[name];
   }
 
   // New program element addition
+  void set_namespace(std::string name) {
+    namespace_ = name;
+  }
+
   void add_typedef(t_typedef* td) {
     typedefs_.push_back(td);
     add_custom_type(td->get_symbolic(), td);
@@ -86,19 +89,32 @@
     structs_.push_back(ts);
     add_custom_type(ts->get_name(), ts);
   }
+  void add_xception(t_struct* tx) {
+    xceptions_.push_back(tx);
+    add_custom_type(tx->get_name(), tx);
+  }
   void add_service(t_service* ts) {
     services_.push_back(ts);
   }
 
  private:
+  // Add custom type for lookup
+  void add_custom_type(std::string name, t_type* type) {
+    custom_types_[name] = type;
+  }
+
   // Name
   std::string name_;
 
+  // Namespace
+  std::string namespace_;
+
   // Components
-  std::vector<t_typedef*> typedefs_;
-  std::vector<t_enum*>    enums_;
-  std::vector<t_struct*>  structs_;
-  std::vector<t_service*> services_;
+  std::vector<t_typedef*>  typedefs_;
+  std::vector<t_enum*>     enums_;
+  std::vector<t_struct*>   structs_;
+  std::vector<t_struct*>   xceptions_;
+  std::vector<t_service*>  services_;
 
   // Type map
   std::map<std::string, t_type*> custom_types_;
@@ -107,10 +123,9 @@
   t_type* type_void;
   t_type* type_string;
   t_type* type_byte;
+  t_type* type_i16;
   t_type* type_i32;
-  t_type* type_u32;
   t_type* type_i64;
-  t_type* type_u64;  
 };
 
 #endif
diff --git a/compiler/cpp/src/parse/t_struct.h b/compiler/cpp/src/parse/t_struct.h
index 6e87c8c..a365cd4 100644
--- a/compiler/cpp/src/parse/t_struct.h
+++ b/compiler/cpp/src/parse/t_struct.h
@@ -9,22 +9,41 @@
 
 class t_struct : public t_type {
  public:
-  t_struct() {}
-  t_struct(const std::string& name) : t_type(name) {}
+  t_struct() : is_xception_(false) {}
+  t_struct(const std::string& name) : t_type(name), is_xception_(false) {}
 
   ~t_struct() {}
 
   /** Set the struct name */
-  void set_name(const std::string& name) { name_ = name; }
+  void set_name(const std::string& name) {
+    name_ = name;
+  }
+
+  /** Mark as an exception */
+  void set_xception(bool is_xception) {
+    is_xception_ = is_xception;
+  }
 
   /** Add a new field to the list */
-  void append(t_field* elem) { members_.push_back(elem); }
+  void append(t_field* elem) {
+    members_.push_back(elem);
+  }
 
-  const std::vector<t_field*>& get_members() { return members_; }
-  bool is_struct() const { return true; }
+  const std::vector<t_field*>& get_members() {
+    return members_;
+  }
+
+  bool is_struct() const {
+    return !is_xception_;
+  }
+
+  bool is_xception() const {
+    return is_xception_;
+  }
 
  private:
   std::vector<t_field*> members_;
+  bool is_xception_;
 };
 
 #endif
diff --git a/compiler/cpp/src/parse/t_type.h b/compiler/cpp/src/parse/t_type.h
index 6703bfa..6328961 100644
--- a/compiler/cpp/src/parse/t_type.h
+++ b/compiler/cpp/src/parse/t_type.h
@@ -19,6 +19,7 @@
   virtual bool is_typedef()   const { return false; }
   virtual bool is_enum()      const { return false; }
   virtual bool is_struct()    const { return false; }
+  virtual bool is_xception()  const { return false; }
   virtual bool is_list()      const { return false; }
   virtual bool is_set()       const { return false; }
   virtual bool is_map()       const { return false; }
diff --git a/compiler/cpp/src/thrift.l b/compiler/cpp/src/thrift.l
index 9d2944a..1f4d7fe 100644
--- a/compiler/cpp/src/thrift.l
+++ b/compiler/cpp/src/thrift.l
@@ -19,7 +19,7 @@
 
 /** Helper definitions */
 intconstant  ([0-9]+)
-identifier   ([a-zA-Z_][a-zA-Z_0-9]*)
+identifier   ([a-zA-Z_][\.a-zA-Z_0-9]*)
 whitespace   ([ \t\r\n]*)
 multicomm    ("/*""/"*([^*/]|[^*]"/"|"*"[^/])*"*"*"*/")
 comment      ("//"[^\n]*)
@@ -31,15 +31,17 @@
 {multicomm}   { /* do nothing */ }
 {comment}     { /* do nothing */ }
 
-{symbol}      { return yytext[0];   }
+{symbol}      { return yytext[0]; }
+
+"namespace"   { return tok_namespace; }
 
 "void"        { return tok_void;     }
 "byte"        { return tok_byte;     }
-"string"      { return tok_string;   }
+"i16"         { return tok_i16;      }
 "i32"         { return tok_i32;      }
-"u32"         { return tok_u32;      }
 "i64"         { return tok_i64;      }
-"u64"         { return tok_u64;      }
+"double"      { return tok_double;   }
+"string"      { return tok_string;   }
 
 "map"         { return tok_map;      }
 "list"        { return tok_list;     }
@@ -49,11 +51,13 @@
 
 "typedef"     { return tok_typedef;  }
 "struct"      { return tok_struct;   }
+"exception"   { return tok_xception; }
+"throws"      { return tok_throws;   }
 "service"     { return tok_service;  }
 "enum"        { return tok_enum;     }
 
 
-{intconstant} { yylval.iconst = atoi(yytext) ; return tok_int_constant; }
+{intconstant} { yylval.iconst = atoi(yytext); return tok_int_constant; }
 {identifier}  { yylval.id = strdup(yytext); return tok_identifier; }
 
 %%
diff --git a/compiler/cpp/src/thrift.y b/compiler/cpp/src/thrift.y
index d0882ff..069d6c8 100644
--- a/compiler/cpp/src/thrift.y
+++ b/compiler/cpp/src/thrift.y
@@ -13,7 +13,7 @@
 #include "globals.h"
 #include "parse/t_program.h"
 
-int y_field_val = 0;
+int y_field_val = -1;
 
 %}
 
@@ -35,13 +35,16 @@
 %token<id>     tok_identifier
 %token<iconst> tok_int_constant
 
+/** Namespace */
+%token tok_namespace
+
 /** Base datatypes */
 %token tok_byte
 %token tok_string
+%token tok_i16
 %token tok_i32
-%token tok_u32
 %token tok_i64
-%token tok_u64
+%token tok_double
 
 /** Complex Types */
 %token tok_map
@@ -57,6 +60,8 @@
 /** Thrift actions */
 %token tok_typedef
 %token tok_struct
+%token tok_xception
+%token tok_throws
 %token tok_service
 %token tok_enum
 
@@ -67,18 +72,22 @@
 %type<ttype>     SetType
 %type<ttype>     ListType
 
+%type<id>        Namespace
+
 %type<ttypedef>  Typedef
 %type<ttype>     DefinitionType
 
 %type<tfield>    Field
 %type<ttype>     FieldType
 %type<tstruct>   FieldList
+%type<tstruct>   ThrowsOptional
 
 %type<tenum>     Enum
 %type<tenum>     EnumDefList
 %type<tconstant> EnumDef
 
 %type<tstruct>   Struct
+%type<tstruct>   Xception
 
 %type<tservice>  Service
 
@@ -109,7 +118,12 @@
     }
 
 Definition:
-  Typedef
+  Namespace
+    {
+      pdebug("Definition -> Namespace");
+      g_program->set_namespace($1);
+    }
+| Typedef
     {
       pdebug("Definition -> Typedef");
       g_program->add_typedef($1);
@@ -124,11 +138,23 @@
       pdebug("Definition -> Struct");
       g_program->add_struct($1);
     }
+| Xception
+    { 
+      pdebug("Definition -> Xception");
+      g_program->add_xception($1);     
+    }
 | Service
     {
       pdebug("Definition -> Service");
       g_program->add_service($1);
-    }  
+    }
+
+Namespace:
+  tok_namespace tok_identifier
+    {
+      pdebug("Namespace -> tok_namespace tok_identifier");
+      $$ = $2;
+    }
 
 Typedef:
   tok_typedef DefinitionType tok_identifier
@@ -187,7 +213,17 @@
       pdebug("Struct -> tok_struct tok_identifier { FieldList }");
       $4->set_name($2);
       $$ = $4;
-      y_field_val = 0;
+      y_field_val = -1;
+    }
+
+Xception:
+  tok_xception tok_identifier '{' FieldList '}'
+    {
+      pdebug("Xception -> tok_xception tok_identifier { FieldList }");
+      $4->set_name($2);
+      $4->set_xception(true);
+      $$ = $4;
+      y_field_val = -1;
     }
 
 Service:
@@ -199,7 +235,7 @@
     }
 
 FunctionList:
-  FunctionList Function
+  FunctionList Function CommaOptional
     {
       pdebug("FunctionList -> FunctionList Function");
       $$ = $1;
@@ -211,12 +247,18 @@
       $$ = new t_service;
     }
 
+CommaOptional:
+  ','
+    {}
+|
+    {}
+
 Function:
-  FunctionType AsyncOptional tok_identifier '(' FieldList ')'
+  FunctionType AsyncOptional tok_identifier '(' FieldList ')' ThrowsOptional
     {
       $5->set_name(std::string($3) + "_args");
-      $$ = new t_function($1, $3, $5, $2);
-      y_field_val = 0;
+      $$ = new t_function($1, $3, $5, $7, $2);
+      y_field_val = -1;
     }
 
 AsyncOptional:
@@ -229,6 +271,16 @@
       $$ = false;
     }
 
+ThrowsOptional:
+  tok_throws '(' FieldList ')'
+    {
+      $$ = $3;
+    }
+|
+    {
+      $$ = new t_struct;
+    }
+
 FieldList:
   FieldList ',' Field
     {
@@ -252,18 +304,17 @@
   FieldType tok_identifier '=' tok_int_constant
     {
       pdebug("Field -> FieldType tok_identifier = tok_int_constant");
-      if ($4 < 0) {
-        yyerror("Negative value (%d) not allowed as a field key.", $4);
-        exit(1);
+      if ($4 <= 0) {
+        printf("WARNING (%d): Nonpositive value (%d) not allowed as a field key for '%s'.\n", yylineno, $4, $2);
+        $4 = y_field_val--;
       }
-      $$ = new t_field($1, $2, (uint32_t)$4);
-      y_field_val = $4+1;
+      $$ = new t_field($1, $2, $4);
     }
 | FieldType tok_identifier
     {
       pdebug("Field -> FieldType tok_identifier");
-      printf("WARNING (%d): No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", yylineno, $2);
-      $$ = new t_field($1, $2, y_field_val++);
+      printf("WARNING (%d): No field key specified for '%s', resulting protocol may have conflicts or not be backwards compatible!\n", yylineno, $2);
+      $$ = new t_field($1, $2, y_field_val--);
     }
 
 DefinitionType:
@@ -322,26 +373,21 @@
       pdebug("BaseType -> tok_byte");
       $$ = g_program->get_byte_type();
     }
+| tok_i16
+    {
+      pdebug("BaseType -> tok_i16");
+      $$ = g_program->get_i16_type();
+    }
 | tok_i32
     {
       pdebug("BaseType -> tok_i32");
       $$ = g_program->get_i32_type();
     }
-| tok_u32
-    {
-      pdebug("BaseType -> tok_u32");
-      $$ = g_program->get_u32_type();
-    }
 | tok_i64
     {
       pdebug("BaseType -> tok_i64");
       $$ = g_program->get_i64_type();
     }
-| tok_u64
-    {
-      pdebug("BaseType -> tok_u64");
-      $$ = g_program->get_u64_type();
-    }
 
 ContainerType:
   MapType
diff --git a/compiler/py/setup.py b/compiler/py/setup.py
index 3901042..7167181 100644
--- a/compiler/py/setup.py
+++ b/compiler/py/setup.py
@@ -1,12 +1,12 @@
 from distutils.core import setup
 
-setup(name='Thrift',
-      version='1.0',
-      description='Thrift IDL compiler',
-      author =['Mark Slee', 'Marc Kwiatkowski'],
-      author_email= ['mcslee@facebook.com', 'marc@facebook.com'],
-      url='http://code.facebook.com/thrift',
-      package_dir={'thrift' : 'src'},
+setup(name = 'Thrift',
+      version = '1.0',
+      description = 'Thrift IDL compiler',
+      author = ['Mark Slee', 'Marc Kwiatkowski'],
+      author_email = ['mcslee@facebook.com', 'marc@facebook.com'],
+      url = 'http://code.facebook.com/thrift',
+      package_dir = {'thrift' : 'src'},
       py_modules = ['thrift.parser', 'thrift.cpp_generator', 'thrift.generator', 'thrift.php_generator'],
       scripts = ['src/thrift']
       )