summaryrefslogtreecommitdiff
path: root/cpp/rubygen
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2008-02-27 16:37:48 +0000
committerAlan Conway <aconway@apache.org>2008-02-27 16:37:48 +0000
commit0731e05211ff5e47e6a8b2c006bd6012da5cc161 (patch)
treec30b793e7db0471caf9cc9b2226fdf20a353c8f9 /cpp/rubygen
parent178e1ad48948e5818ee3922cb73e515f581557d6 (diff)
downloadqpid-python-0731e05211ff5e47e6a8b2c006bd6012da5cc161.tar.gz
Generate code for both 0-99 preview and 0-10 final specs .
0-10 final: extended code generation and non-generated support classes. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@631638 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/rubygen')
-rwxr-xr-xcpp/rubygen/0-10/amqp_0_10.rb175
-rwxr-xr-xcpp/rubygen/99-0/MethodBodyConstVisitor.rb (renamed from cpp/rubygen/templates/MethodBodyConstVisitor.rb)2
-rwxr-xr-xcpp/rubygen/99-0/MethodBodyDefaultVisitor.rb (renamed from cpp/rubygen/templates/MethodBodyDefaultVisitor.rb)2
-rwxr-xr-xcpp/rubygen/99-0/MethodHolder.rb (renamed from cpp/rubygen/templates/MethodHolder.rb)2
-rwxr-xr-xcpp/rubygen/99-0/Operations.rb (renamed from cpp/rubygen/templates/Operations.rb)4
-rwxr-xr-xcpp/rubygen/99-0/OperationsInvoker.rb (renamed from cpp/rubygen/templates/OperationsInvoker.rb)4
-rwxr-xr-xcpp/rubygen/99-0/Proxy.rb (renamed from cpp/rubygen/templates/Proxy.rb)8
-rw-r--r--cpp/rubygen/99-0/Session.rb (renamed from cpp/rubygen/templates/Session.rb)4
-rwxr-xr-xcpp/rubygen/99-0/all_method_bodies.rb (renamed from cpp/rubygen/templates/all_method_bodies.rb)2
-rwxr-xr-xcpp/rubygen/99-0/constants.rb (renamed from cpp/rubygen/templates/constants.rb)2
-rw-r--r--cpp/rubygen/99-0/frame_body_lists.rb (renamed from cpp/rubygen/templates/frame_body_lists.rb)2
-rw-r--r--cpp/rubygen/99-0/structs.rb (renamed from cpp/rubygen/templates/structs.rb)2
-rwxr-xr-xcpp/rubygen/MethodBodyDefaultVisitor.rb2
-rwxr-xr-xcpp/rubygen/amqpgen.rb72
-rwxr-xr-xcpp/rubygen/cppgen.rb73
-rwxr-xr-xcpp/rubygen/generate35
-rwxr-xr-xcpp/rubygen/templates/amqp_0_10.rb64
17 files changed, 333 insertions, 122 deletions
diff --git a/cpp/rubygen/0-10/amqp_0_10.rb b/cpp/rubygen/0-10/amqp_0_10.rb
new file mode 100755
index 0000000000..985d275668
--- /dev/null
+++ b/cpp/rubygen/0-10/amqp_0_10.rb
@@ -0,0 +1,175 @@
+#!/usr/bin/env ruby
+$: << ".." # Include .. in load path
+require 'cppgen'
+
+class Amqp_0_10 < CppGen
+ ArrayTypes={
+ "str16-array" => "Str16",
+ "amqp-host-array" => "connection::AmqpHostUrl",
+ "command-fragments" => "session::CommandFragment",
+ "in-doubt" => "dtx::Xid"
+ }
+
+ def initialize(outdir, amqp)
+ super(outdir, amqp)
+ @ns="qpid::amqp_0_10"
+ @dir="qpid/amqp_0_10"
+ end
+
+ # domains
+
+ def domain_h(d)
+ typename=d.name.typename
+ if d.enum
+ scope("enum #{typename} {", "};") {
+ genl d.enum.choices.map { |c| "#{c.name.constname} = #{c.value}" }.join(",\n")
+ }
+ elsif d.type_ == "array"
+ @array_domains << "typedef Array<#{ArrayTypes[d.name]}> #{typename};\n"
+ else
+ genl "typedef #{d.type_.amqp2cpp} #{typename};"
+ end
+ end
+
+ # structs
+
+ # field members and MemberInfo
+ def member_h(m)
+ genl "static const MemberInfo INFO;"
+ m.fields.each { |f| genl "#{f.type_.amqp2cpp} #{f.cppname};" }
+ end
+
+ # MemberInfo constant definition.
+ def member_cpp(m)
+ infotype=m.is_a?(AmqpStruct) ? "Struct1Info" : "MemberInfo"
+ scope("{infotype} #{m.classname}::INFO = {","};") {
+ inits=[]
+ inits << (m.parent.is_a?(AmqpClass) ? "&CLASS_INFO" : "0")
+ inits << m.name << (m.code or "0");
+ if m.is_a?(AmqpStruct)
+ inits << (m.size or 0) << (m.pack or 0)
+ end
+ genl inits.join(", ")
+ }
+ end
+
+ def struct_h(s) struct(s.classname, "public Struct") { member_h s }; end
+ def struct_cpp(s) member_cpp s; end
+ def gen_structs()
+ file="#{@dir}/structs"
+ h_file(file) {
+ include "#{@dir}/built_in_types.h"
+ include "#{@dir}/helpers.h"
+ include "<boost/call_traits.hpp>"
+ genl "using boost::call_traits;"
+ namespace(@ns) {
+ @amqp.structs.each { |s| struct_h s }
+ each_class_ns { |c| c.structs.each { |s| struct_h s }}
+ }
+ }
+ cpp_file(file) {
+ include file
+ namespace(@ns) {
+ @amqp.structs.each { |s| struct_h s }
+ each_class_ns { |c| c.structs.each { |s| struct_cpp s }}
+ }
+ }
+ end
+
+ # command and control
+
+ def action_h(a)
+ name=a.name.typename
+ struct(name, "public #{a.base}") {
+ genl "#{name}() {}"
+ scope("#{name}(",");") { genl a.parameters } unless a.fields.empty?
+ scope("template <class T> void invoke(T& target) {","}") {
+ scope("target.#{a.funcname}(", ");") { genl a.values }
+ }
+ scope("template <class S> void serialize(S& s) {","}") {
+ gen "s"
+ a.fields.each { |f| gen "(#{f.cppname})"}
+ genl ";"
+ } unless a.fields.empty?
+ member_h a
+ }
+ end
+
+ def action_cpp(a) # command or control
+ # ctor
+ scope("#{a.classname}::#{a.classname}(",") :") { genl a.parameters }
+ indent() { genl a.initializers }
+ genl "{}"
+ # member constants
+ member_cpp a
+ end
+
+ def class_h(c)
+ genl "extern const ClassInfo CLASS_INFO;"
+ @array_domains=""
+ c.domains.each { |d| domain_h d }
+ c.structs.each { |s| struct_h s }
+ gen @array_domains
+ end
+
+ def class_cpp(c)
+ genl "const ClassInfo CLASS_INFO = { #{c.code}, \"#{c.name}\" };"
+ c.structs.each { |s| struct_cpp s }
+ end
+
+ def gen_specification()
+ h_file("#{@dir}/specification") {
+ include "#{@dir}/built_in_types"
+ include "#{@dir}/helpers"
+ include "<boost/call_traits.hpp>"
+ genl "using boost::call_traits;"
+ namespace(@ns) {
+ # We don't generate top-level domains, as they have clashing values.
+ each_class_ns { |c| class_h c }
+ each_class_ns { |c| c.actions.each { |a| action_h a}
+ }
+ }
+ }
+ cpp_file("#{@dir}/specification") {
+ include "#{@dir}/specification"
+ namespace(@ns) {
+ each_class_ns { |c| class_cpp c }
+ each_class_ns { |c| c.actions.each { |a| action_cpp a}
+ }
+ }
+ }
+ end
+
+ def gen_proxy()
+ h_file("#{@dir}/Proxy.h") {
+ include "#{@dir}/specification"
+ namespace(@ns) {
+ genl "template <class F, class R=F::result_type>"
+ cpp_class("ProxyTemplate") {
+ public
+ genl "ProxyTemplate(F f) : functor(f) {}"
+ @amqp.classes.each { |c|
+ c.actions.each { |a|
+ scope("R #{a.funcname}(", ")") { genl a.parameters }
+ scope() {
+ var=a.name.funcname
+ scope("#{a.classname} #{var}(",");") { genl a.arguments }
+ genl "return functor(#{var});"
+ }
+ }
+ }
+ private
+ genl "F functor;"
+ }
+ }
+ }
+ end
+
+ def generate
+ gen_specification
+ gen_proxy
+ end
+end
+
+Amqp_0_10.new($outdir, $amqp).generate();
+
diff --git a/cpp/rubygen/templates/MethodBodyConstVisitor.rb b/cpp/rubygen/99-0/MethodBodyConstVisitor.rb
index 18f74a2e41..f9ef95f5a0 100755
--- a/cpp/rubygen/templates/MethodBodyConstVisitor.rb
+++ b/cpp/rubygen/99-0/MethodBodyConstVisitor.rb
@@ -23,5 +23,5 @@ class MethodBodyConstVisitorGen < CppGen
end
end
-MethodBodyConstVisitorGen.new(Outdir, Amqp).generate();
+MethodBodyConstVisitorGen.new($outdir, $amqp).generate();
diff --git a/cpp/rubygen/templates/MethodBodyDefaultVisitor.rb b/cpp/rubygen/99-0/MethodBodyDefaultVisitor.rb
index 4944b10a84..a74b0c06d6 100755
--- a/cpp/rubygen/templates/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/99-0/MethodBodyDefaultVisitor.rb
@@ -31,5 +31,5 @@ class MethodBodyDefaultVisitorGen < CppGen
end
end
-MethodBodyDefaultVisitorGen.new(Outdir, Amqp).generate();
+MethodBodyDefaultVisitorGen.new($outdir, $amqp).generate();
diff --git a/cpp/rubygen/templates/MethodHolder.rb b/cpp/rubygen/99-0/MethodHolder.rb
index 7e915677b2..a708db6676 100755
--- a/cpp/rubygen/templates/MethodHolder.rb
+++ b/cpp/rubygen/99-0/MethodHolder.rb
@@ -96,5 +96,5 @@ EOS
end
end
-MethodHolderGen.new(Outdir, Amqp).generate();
+MethodHolderGen.new($outdir, $amqp).generate();
diff --git a/cpp/rubygen/templates/Operations.rb b/cpp/rubygen/99-0/Operations.rb
index 91007ef3e1..c985bb6105 100755
--- a/cpp/rubygen/templates/Operations.rb
+++ b/cpp/rubygen/99-0/Operations.rb
@@ -91,6 +91,6 @@ EOS
end
end
-OperationsGen.new("client",ARGV[0], Amqp).generate()
-OperationsGen.new("server",ARGV[0], Amqp).generate()
+OperationsGen.new("client",ARGV[0], $amqp).generate()
+OperationsGen.new("server",ARGV[0], $amqp).generate()
diff --git a/cpp/rubygen/templates/OperationsInvoker.rb b/cpp/rubygen/99-0/OperationsInvoker.rb
index 747dd06189..642f98ce8e 100755
--- a/cpp/rubygen/templates/OperationsInvoker.rb
+++ b/cpp/rubygen/99-0/OperationsInvoker.rb
@@ -88,5 +88,5 @@ class OperationsInvokerGen < CppGen
end
end
-OperationsInvokerGen.new("client",ARGV[0], Amqp).generate()
-OperationsInvokerGen.new("server",ARGV[0], Amqp).generate()
+OperationsInvokerGen.new("client",ARGV[0], $amqp).generate()
+OperationsInvokerGen.new("server",ARGV[0], $amqp).generate()
diff --git a/cpp/rubygen/templates/Proxy.rb b/cpp/rubygen/99-0/Proxy.rb
index 467476506c..2829884673 100755
--- a/cpp/rubygen/templates/Proxy.rb
+++ b/cpp/rubygen/99-0/Proxy.rb
@@ -62,7 +62,9 @@ EOS
include "<sstream>"
include "#{@classname}.h"
include "qpid/framing/amqp_types_full.h"
- Amqp.methods_on(@chassis).each { |m| include "qpid/framing/"+m.body_name }
+ @amqp.methods_on(@chassis).each {
+ |m| include "qpid/framing/"+m.body_name
+ }
genl
namespace("qpid::framing") {
genl "#{@classname}::#{@classname}(FrameHandler& f) :"
@@ -75,6 +77,6 @@ EOS
end
-ProxyGen.new("client", Outdir, Amqp).generate;
-ProxyGen.new("server", Outdir, Amqp).generate;
+ProxyGen.new("client", $outdir, $amqp).generate;
+ProxyGen.new("server", $outdir, $amqp).generate;
diff --git a/cpp/rubygen/templates/Session.rb b/cpp/rubygen/99-0/Session.rb
index 6a50fdb462..e01a28a62d 100644
--- a/cpp/rubygen/templates/Session.rb
+++ b/cpp/rubygen/99-0/Session.rb
@@ -190,6 +190,6 @@ EOS
end
end
-SessionNoKeywordGen.new(ARGV[0], Amqp).generate()
-SessionGen.new(ARGV[0], Amqp).generate()
+SessionNoKeywordGen.new(ARGV[0], $amqp).generate()
+SessionGen.new(ARGV[0], $amqp).generate()
diff --git a/cpp/rubygen/templates/all_method_bodies.rb b/cpp/rubygen/99-0/all_method_bodies.rb
index d06f459493..5971d49189 100755
--- a/cpp/rubygen/templates/all_method_bodies.rb
+++ b/cpp/rubygen/99-0/all_method_bodies.rb
@@ -17,5 +17,5 @@ class AllMethodBodiesGen < CppGen
end
end
-AllMethodBodiesGen.new(Outdir, Amqp).generate();
+AllMethodBodiesGen.new($outdir, $amqp).generate();
diff --git a/cpp/rubygen/templates/constants.rb b/cpp/rubygen/99-0/constants.rb
index 5fbbefe218..b5f559d504 100755
--- a/cpp/rubygen/templates/constants.rb
+++ b/cpp/rubygen/99-0/constants.rb
@@ -78,5 +78,5 @@ class ConstantsGen < CppGen
end
end
-ConstantsGen.new(Outdir, Amqp).generate();
+ConstantsGen.new($outdir, $amqp).generate();
diff --git a/cpp/rubygen/templates/frame_body_lists.rb b/cpp/rubygen/99-0/frame_body_lists.rb
index 634001ab14..b20e4550f3 100644
--- a/cpp/rubygen/templates/frame_body_lists.rb
+++ b/cpp/rubygen/99-0/frame_body_lists.rb
@@ -26,6 +26,6 @@ EOS
end
end
-FrameBodyListsGen.new(ARGV[0], Amqp).generate;
+FrameBodyListsGen.new(ARGV[0], $amqp).generate;
diff --git a/cpp/rubygen/templates/structs.rb b/cpp/rubygen/99-0/structs.rb
index edbadb01f6..336591be00 100644
--- a/cpp/rubygen/templates/structs.rb
+++ b/cpp/rubygen/99-0/structs.rb
@@ -534,5 +534,5 @@ EOS
end
end
-StructGen.new(ARGV[0], Amqp).generate()
+StructGen.new(ARGV[0], $amqp).generate()
diff --git a/cpp/rubygen/MethodBodyDefaultVisitor.rb b/cpp/rubygen/MethodBodyDefaultVisitor.rb
index d1212153ca..1fff1d51db 100755
--- a/cpp/rubygen/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/MethodBodyDefaultVisitor.rb
@@ -30,5 +30,5 @@ class MethodBodyDefaultVisitorGen < CppGen
end
end
-MethodBodyDefaultVisitorGen.new(Outdir, Amqp).generate();
+MethodBodyDefaultVisitorGen.new($outdir, $amqp).generate();
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb
index da6ed689a3..fbbdc8dd2e 100755
--- a/cpp/rubygen/amqpgen.rb
+++ b/cpp/rubygen/amqpgen.rb
@@ -119,7 +119,16 @@ class AmqpElement
# List of children of type elname, or all children if elname
# not specified.
def children(elname=nil)
- @cache_children[elname] ||= @children.select { |c| elname==c.xml.name }
+ if elname
+ @cache_children[elname] ||= @children.select { |c| elname==c.xml.name }
+ else
+ @children
+ end
+ end
+
+ def each_descendant(&block)
+ yield self
+ @children.each { |c| c.each_descendant(&block) }
end
# Look up child of type elname with attribute name.
@@ -264,17 +273,21 @@ class AmqpRole < AmqpElement
amqp_attr_reader :implement
end
-class AmqpControl < AmqpElement
+# Base class for command and control.
+class AmqpAction < AmqpElement
def initialize(xml,amqp) super; end
amqp_child_reader :implement, :field, :response
amqp_attr_reader :code
end
-class AmqpCommand < AmqpElement
+class AmqpControl < AmqpAction
+ def initialize(xml,amqp) super; end
+end
+
+class AmqpCommand < AmqpAction
def initialize(xml,amqp) super; end
- amqp_child_reader :implement, :field, :exception, :response
+ amqp_child_reader :exception
amqp_single_child_reader :result, :segments
- amqp_attr_reader :code
end
class AmqpClass < AmqpElement
@@ -295,6 +308,8 @@ class AmqpClass < AmqpElement
def l4?() # preview
!["connection", "session", "execution"].include?(name)
end
+
+ def actions() controls+commands; end
end
class AmqpType < AmqpElement
@@ -321,6 +336,8 @@ class AmqpRoot < AmqpElement
super(xml, nil)
end
+ def merge(root) xml_merge(xml, root.xml); end
+
def version() major + "-" + minor; end
# Find the element corresponding to an amqp dotted name.
@@ -370,25 +387,30 @@ class Generator
def initialize (outdir, amqp)
@amqp=amqp
@outdir=outdir
- @prefix='' # For indentation or comments.
+ @prefix=[''] # For indentation or comments.
@indentstr=' ' # One indent level.
@outdent=2
Pathname.new(@outdir).mkpath unless @outdir=="-" or File.directory?(@outdir)
end
# Create a new file, set @out.
- def file(file)
+ def file(file, &block)
GenFiles.add file
if (@outdir != "-")
- path=Pathname.new "#{@outdir}/#{file}"
- path.parent.mkpath
+ @path=Pathname.new "#{@outdir}/#{file}"
+ @path.parent.mkpath
@out=String.new # Generate in memory first
- yield # Generate to @out
- if path.exist? and path.read == @out
- puts "Skipped #{path} - unchanged" # Dont generate if unchanged
+ if block then yield; endfile; end
+ end
+ end
+
+ def endfile()
+ if @outdir != "-"
+ if @path.exist? and @path.read == @out
+ puts "Skipped #{@path} - unchanged" # Dont generate if unchanged
else
- path.open('w') { |f| f << @out }
- puts "Generated #{path}"
+ @path.open('w') { |f| f << @out }
+ puts "Generated #{@path}"
end
end
end
@@ -396,7 +418,7 @@ class Generator
# Append multi-line string to generated code, prefixing each line.
def gen (str)
str.each_line { |line|
- @out << @prefix unless @midline
+ @out << @prefix.last unless @midline
@out << line
@midline = nil
}
@@ -411,23 +433,25 @@ class Generator
end
# Generate code with added prefix.
- def prefix(add)
- save=@prefix
- @prefix+=add
- yield
- @prefix=save
+ def prefix(add, &block)
+ @prefix.push @prefix.last+add
+ if block then yield; endprefix; end
+ end
+
+ def endprefix()
+ @prefix.pop
end
# Generate indented code
def indent(n=1,&block) prefix(@indentstr * n,&block); end
+ alias :endindent :endprefix
# Generate outdented code
def outdent(&block)
- save=@prefix
- @prefix=@prefix[0...-2]
- yield
- @prefix=save
+ @prefix.push @prefix.last[0...-2]
+ if block then yield; endprefix; end
end
+ alias :endoutdent :endprefix
attr_accessor :out
end
diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb
index d3cdcca603..e3462d60d7 100755
--- a/cpp/rubygen/cppgen.rb
+++ b/cpp/rubygen/cppgen.rb
@@ -55,12 +55,20 @@ CppMangle = CppKeywords+Set.new(["string"])
class String
def cppsafe() CppMangle.include?(self) ? self+"_" : self; end
+
def amqp2cpp()
path=split(".")
name=path.pop
- path.map! { |n| n.bars }
- (path << name.caps).join("::")
+ return name.typename if path.empty?
+ path.map! { |n| n.nsname }
+ return "amqp_0_10::"+(path << name.caps).join("::")
end
+
+ alias :typename :caps
+ alias :nsname :bars
+ alias :constname :shout
+ alias :funcname :lcaps
+ alias :varname :lcaps
end
# Hold information about a C++ type.
@@ -119,6 +127,7 @@ class AmqpField
def cpptype() domain.cpptype; end
def bit?() domain.type_ == "bit"; end
def signature() cpptype.param+" "+cppname; end
+ def paramtype() "call_traits<#{type_.amqp2cpp}>::param_type"; end
end
class AmqpMethod
@@ -128,8 +137,40 @@ class AmqpMethod
def body_name() parent.name.caps+name.caps+"Body"; end
end
+class AmqpAction
+ def nsname() name.namespace; end
+ def classname() name.typename; end
+ def funcname() parent.name.funcname + name.caps; end
+
+ def parameters()
+ fields.map { |f| "#{f.paramtype} #{f.cppname}_"}.join(",\n")
+ end
+
+ def arguments()
+ fields.map { |f| "#{f.cppname}_"}.join(",\n")
+ end
+
+ def values()
+ fields.map { |f| "#{f.cppname}"}.join(",\n")
+ end
+
+ def initializers()
+ fields.map { |f| "#{f.cppname}(#{f.cppname}_)}"}.join(",\n")
+ end
+
+end
+
+class AmqpCommand
+ def base() "Command"; end
+end
+
+class AmqpControl
+ def base() "Control"; end
+end
+
class AmqpClass
def cppname() name.caps; end
+ def nsname() name.nsname; end
end
class AmqpDomain
@@ -172,17 +213,20 @@ end
class AmqpStruct
def cpp_pack_type() AmqpDomain.lookup_type(pack()) or CppType.new("uint16_t"); end
- def cpptype() parent.cpptype; end
- def cppname() cpptype.name; end
+ def cpptype() parent.cpptype; end # preview
+ def cppname() cpptype.name; end # preview
+ def classname() name.typename; end
end
class CppGen < Generator
def initialize(outdir, *specs)
super(outdir,*specs)
+ # need to sort classes for dependencies
+ @actions=[] # Stack of end-scope actions
end
# Write a header file.
- def h_file(path)
+ def h_file(path, &block)
path = (/\.h$/ === path ? path : path+".h")
guard=path.upcase.tr('./-','_')
file(path) {
@@ -190,12 +234,12 @@ class CppGen < Generator
gen "#define #{guard}\n"
gen Copyright
yield
- gen "#endif /*!#{guard}*/\n"
+ gen "#endif /*!#{guard}*/\n"
}
end
# Write a .cpp file.
- def cpp_file(path)
+ def cpp_file(path, &block)
path = (/\.cpp$/ === path ? path : path+".cpp")
file(path) do
gen Copyright
@@ -209,10 +253,12 @@ class CppGen < Generator
genl "#include #{header}"
end
- def scope(open="{",close="}", &block)
- genl open; indent(&block); genl close
+ def scope(open="{",close="}", &block)
+ genl open
+ indent &block
+ genl close
end
-
+
def namespace(name, &block)
genl
names = name.split("::")
@@ -231,7 +277,7 @@ class CppGen < Generator
indent { gen "#{bases.join(",\n")}" }
end
genl
- scope("{","};") { yield }
+ scope("{","};", &block)
end
def struct(name, *bases, &block)
@@ -263,6 +309,11 @@ class CppGen < Generator
prefix(" * ",&block)
genl " */"
end
+
+ # Generate code in namespace for each class
+ def each_class_ns()
+ @amqp.classes.each { |c| namespace(c.nsname) { yield c } }
+ end
end
# Fully-qualified class name
diff --git a/cpp/rubygen/generate b/cpp/rubygen/generate
index f7bf334569..4ea8aef425 100755
--- a/cpp/rubygen/generate
+++ b/cpp/rubygen/generate
@@ -1,5 +1,6 @@
#!/usr/bin/env ruby
require 'amqpgen'
+require 'pathname'
#
# Run a set of code generation templates.
@@ -18,17 +19,39 @@ EOS
exit 1
end
-Outdir=ARGV[0]
-Specs=ARGV.grep(/\.xml$/)
-Amqp=AmqpRoot.new(*Specs)
+# Create array of specs by version
+def parse_specs(specs)
+ roots={ }
+ specs.each { |spec|
+ root=AmqpRoot.new(spec)
+ ver=root.version
+ if (roots[ver])
+ roots[ver].merge(root)
+ else
+ roots[ver]=root
+ end
+ }
+ roots
+end
# Run selected templates
if ARGV.any? { |arg| arg=="all" }
- templates=Dir["#{File.dirname __FILE__}/templates/*.rb"]
+ templates=Dir["#{File.dirname __FILE__}/*/*.rb"]
else
templates=ARGV.grep(/\.rb$/)
end
-templates.each { |t| load t }
+
+$outdir=ARGV[0]
+$models=parse_specs(ARGV.grep(/\.xml$/))
+templates.each { |t|
+ ver=Pathname.new(t).dirname.basename.to_s
+ $amqp=$models[ver]
+ if $amqp
+ load t
+ else
+ puts "Warning: skipping #{t}, no spec file for version #{ver}."
+ end
+}
def make_continue(lines) lines.join(" \\\n "); end
@@ -40,7 +63,7 @@ if makefile
generator_files=Dir["**/*.rb"] << File.basename(__FILE__)
Dir.chdir dir
rgen_generator=generator_files.map{ |f| "$(rgen_dir)/#{f}" }
- rgen_srcs=GenFiles.get.map{ |f| "#{Outdir}/#{f}" }
+ rgen_srcs=GenFiles.get.map{ |f| "#{$outdir}/#{f}" }
File.open(makefile, 'w') { |out|
out << <<EOS
diff --git a/cpp/rubygen/templates/amqp_0_10.rb b/cpp/rubygen/templates/amqp_0_10.rb
deleted file mode 100755
index ef779c9015..0000000000
--- a/cpp/rubygen/templates/amqp_0_10.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env ruby
-$: << ".." # Include .. in load path
-require 'cppgen'
-
-class Amqp_0_10 < CppGen
-
- def initialize(outdir, amqp)
- super(outdir, amqp)
- @namespace="qpid::amqp_0_10"
- @filename="qpid/amqp_0_10"
- end
-
- def action_h(a, base)
- struct(a.cppname, "public #{base}") {
- genl "static const uint8_t CODE=#{a.code};"
- a.fields.each { |f|
- genl "#{(f.type_.amqp2cpp)} #{f.cppname};"
- }
- }
- end
-
- def action_cpp(a, base)
-
- end
-
- def gen_amqp_0_10_h
- h_file("#{@filename}.h") {
- namespace(@namespace) {
- @amqp.classes.each { |cl|
- namespace(cl.cppname) {
- struct("ClassInfo") {
- genl "static const uint8_t CODE=#{cl.code};"
- genl "static const char* NAME;"
- }
- cl.commands.each { |c| action_h c, "Command"}
- cl.controls.each { |c| action_h c, "Control"}
- }
- }
- }
- }
- end
-
- def gen_amqp_0_10_cpp
- cpp_file("#{@filename}.cpp") {
- include @filename
-
- namespace(@namespace) {
- @amqp.classes.each { |cl|
- namespace(cl.cppname) {
- genl "static const char* ClassInfo::NAME=\"#{cl.name};"
- }
- }
- }
- }
- end
-
- def generate
- gen_amqp_0_10_h
- gen_amqp_0_10_cpp
- end
-end
-
-Amqp_0_10.new(Outdir, Amqp).generate();
-