diff options
Diffstat (limited to 'cpp/rubygen/cppgen.rb')
-rwxr-xr-x | cpp/rubygen/cppgen.rb | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb deleted file mode 100755 index 7dc21fe1bc..0000000000 --- a/cpp/rubygen/cppgen.rb +++ /dev/null @@ -1,452 +0,0 @@ -#!/usr/bin/ruby -# -# General purpose C++ code generation. -# -require 'amqpgen' -require 'set' - -Copyright=<<EOS -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/// -/// This file was automatically generated from the AMQP specification. -/// Do not edit. -/// - - -EOS - -CppKeywords = Set.new(["and", "and_eq", "asm", "auto", "bitand", - "bitor", "bool", "break", "case", "catch", "char", - "class", "compl", "const", "const_cast", "continue", - "default", "delete", "do", "DomainInfo", "double", - "dynamic_cast", "else", "enum", "explicit", "extern", - "false", "float", "for", "friend", "goto", "if", - "inline", "int", "long", "mutable", "namespace", "new", - "not", "not_eq", "operator", "or", "or_eq", "private", - "protected", "public", "register", "reinterpret_cast", - "return", "short", "signed", "sizeof", "static", - "static_cast", "struct", "switch", "template", "this", - "throw", "true", "try", "typedef", "typeid", - "typename", "union", "unsigned", "using", "virtual", - "void", "volatile", "wchar_t", "while", "xor", - "xor_eq"]) -# Names that need a trailing "_" to avoid clashes. -CppMangle = CppKeywords+Set.new(["std::string"]) - -class String - def cppsafe() CppMangle.include?(self) ? self+"_" : self; end - - def amqp2cpp() - path=split(".") - name=path.pop - return name.typename if path.empty? - path.map! { |n| n.nsname } - return (path << name.caps.cppsafe).join("::") - end - - def typename() caps.cppsafe; end - def nsname() bars.cppsafe; end - def constname() shout.cppsafe; end - def funcname() lcaps.cppsafe; end - def varname() lcaps.cppsafe; end -end - -# preview: Hold information about a C++ type. -# -# new mapping does not use CppType, -# Each amqp type corresponds exactly by dotted name -# to a type, domain or struct, which in turns -# corresponds by name to a C++ type or typedef. -# (see String.amqp2cpp) -# -class CppType - def initialize(name) @name=@param=@ret=name; end - attr_reader :name, :param, :ret, :code - - def retref() @ret="#{name}&"; self; end - def retcref() @ret="const #{name}&"; self; end - def passcref() @param="const #{name}&"; self; end - def code(str) @code=str; self; end - def defval(str) @defval=str; self; end - def encoded() @code end - def ret_by_val() @name; end - - def encode(value, buffer) - @code ? "#{buffer}.put#{@code}(#{value});" : "#{value}.encode(#{buffer});" - end - - def decode(value,buffer) - if @code - if /&$/===param then - "#{buffer}.get#{@code}(#{value});" - else - "#{value} = #{buffer}.get#{@code}();" - end - else - "#{value}.decode(#{buffer});" - end - end - - def default_value() - return @defval ||= "#{name}()" - end - - def to_s() name; end; -end - -class AmqpRoot - # preview; map 0-10 types to preview code generator types - @@typemap = { - "bit"=> CppType.new("bool").code("Octet").defval("false"), - "boolean"=> CppType.new("bool").code("Octet").defval("false"), - "uint8"=>CppType.new("uint8_t").code("Octet").defval("0"), - "uint16"=>CppType.new("uint16_t").code("Short").defval("0"), - "uint32"=>CppType.new("uint32_t").code("Long").defval("0"), - "uint64"=>CppType.new("uint64_t").code("LongLong").defval("0"), - "datetime"=>CppType.new("uint64_t").code("LongLong").defval("0"), - "str8"=>CppType.new("std::string").passcref.retcref.code("ShortString"), - "str16"=>CppType.new("std::string").passcref.retcref.code("MediumString"), - "str32"=>CppType.new("std::string").passcref.retcref.code("LongString"), - "vbin8"=>CppType.new("std::string").passcref.retcref.code("ShortString"), - "vbin16"=>CppType.new("std::string").passcref.retcref.code("MediumString"), - "vbin32"=>CppType.new("std::string").passcref.retcref.code("LongString"), - "map"=>CppType.new("FieldTable").passcref.retcref, - "array"=>CppType.new("Array").passcref.retcref, - "sequence-no"=>CppType.new("SequenceNumber").passcref, - "sequence-set"=>CppType.new("SequenceSet").passcref.retcref, - "struct32"=>CppType.new("std::string").passcref.retcref.code("LongString"), - "uuid"=>CppType.new("Uuid").passcref.retcref, - "byte-ranges"=>CppType.new("ByteRanges").passcref.retcref - } - - # preview: map amqp types to preview cpp types. - def lookup_cpptype(t) t = @@typemap[t] and return t end -end - - -class AmqpElement - # convert my amqp type_ attribute to a C++ type. - def amqp2cpp() - return "ArrayDomain<#{array_type(name).amqp2cpp}> " if type_=="array" - return type_.amqp2cpp - end - - # Does this object have a type-like child named name? - def typechild(name) - child = domain(name) if respond_to? :domain - child = struct(name) if not child and respond_to? :struct - child = type_(name) if not child and respond_to? :type_ - child - end - - # dotted name to a type object - def dotted_typechild(name) - names=name.split('.') - context = self - while context and names.size > 1 - context = context.child_named(names.shift) - end - return context.typechild(names[0]) if context - end - - # preview mapping - type_ attribute to C++ type - def lookup_cpptype(name) - if t = root.lookup_cpptype(name) then return t - elsif c = containing_class.typechild(name) then return c.cpptype - elsif c= root.dotted_typechild(name) then return c.cpptype - else raise "Cannot resolve type-name #{name} from #{self}" - end - end - - def containing_class() - return self if is_a? AmqpClass - return parent && parent.containing_class - end -end - - -class AmqpField - def struct?() - c=containing_class - c.struct(type_) - end - def cpptype() lookup_cpptype(type_) or raise "no cpptype #{type_} for field #{self}" end - def cppname() name.lcaps.cppsafe; end - def bit?() type_ == "bit"; end - def signature() cpptype.param+" "+cppname; end - - def fqtypename() - unless type_.index(".") - c=containing_class - return c.domain(type_).fqtypename if c.domain(type_) - return c.struct(type_).fqclassname if c.struct(type_) - end - return amqp2cpp - end - def paramtype() - /^(int|uint|char|boolean|bit)/ === type_ ? fqtypename : "const #{fqtypename}&" - end - def param_default() "=#{fqtypename}()" end - - # Default value is normally the C++ default but over-ridden in specific cases - def default_value() - defval = cpptype.default_value; - if name == "accept-mode" and parent.name == "transfer" then defval = "1"; end - return defval - end -end - -class AmqpMethod - def cppname() name.lcaps.cppsafe; end - def param_names() fields.map { |f| f.cppname }; end - def signature() fields.map { |f| f.signature }; end - def classname() parent.name; end - def body_name() - classname().caps+name.caps+"Body" - end - def cpp_pack_type() root.lookup_cpptype("uint16") end -end - -module AmqpHasFields - def parameters(with_default=nil) - fields.map { |f| - "#{f.paramtype} #{f.cppname}_#{f.param_default if with_default}" - } - end - def unused_parameters() fields.map { |f| "#{f.paramtype} /*#{f.cppname}_*/"} end - def arguments() fields.map { |f| "#{f.cppname}_"} end - def values() fields.map { |f| "#{f.cppname}"} end - def initializers() fields.map { |f| "#{f.cppname}(#{f.cppname}_)"} end -end - -class AmqpAction - def classname() name.typename; end - def funcname() parent.name.funcname + name.caps; end - def fqclassname() parent.name+"::"+classname; end - def full_code() (containing_class.code.hex << 8)+code.hex; end - include AmqpHasFields -end - -class AmqpType - def cpptype() root.lookup_cpptype(name) end # preview - def typename() name.typename; end # new mapping - def fixed?() fixed_width; end -end - -class AmqpCommand < AmqpAction - def base() "Command"; end -end - -class AmqpControl < AmqpAction - def base() "Control"; end -end - -class AmqpClass - def cppname() name.caps; end # preview - def nsname() name.nsname; end -end - -class AmqpDomain - # preview - def cpptype() lookup_cpptype(type_) end - def cppname() name.caps; end - - # new mapping - def fqtypename() - return containing_class.nsname+"::"+name.typename if containing_class - name.typename - end -end - -class AmqpResult - # preview - def cpptype() - if type_ then lookup_cpptype(type_) - else CppType.new(parent.parent.name.caps+parent.name.caps+"Result").passcref - end - end -end - -class AmqpStruct - include AmqpHasFields - - @@pack_types={ "1"=>"uint8", "2"=>"uint16", "4"=>"uint32"} - def cpp_pack_type() # preview - root.lookup_cpptype(@@pack_types[pack]) - end - def cpptype() CppType.new(cppname).passcref.retcref end - #def cppname() containing_class.cppname+name.caps; end - def cppname() - if parent.kind_of? AmqpResult - parent.parent.parent.name.caps+parent.parent.name.caps+"Result" - else - name.caps - end - end - def fqclassname() containing_class.nsname+"::"+name.typename; end - def classname() name.typename; end - def full_code() (containing_class.code.hex << 8)+code.hex; 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, &block) - path = (/\.h$/ === path ? path : path+".h") - guard=path.upcase.tr('./-','_') - file(path) { - gen "#ifndef #{guard}\n" - gen "#define #{guard}\n" - gen Copyright - yield - gen "#endif /*!#{guard}*/\n" - } - end - - # Write a .cpp file. - def cpp_file(path, &block) - path = (/\.cpp$/ === path ? path : path+".cpp") - file(path) do - gen Copyright - yield - end - end - - def include(header) - header+=".h" unless /(\.h|[">])$/===header - header="\"#{header}\"" unless /(^<.*>$)|(^".*"$)/===header - genl "#include #{header}" - end - - def scope(open="{",close="}", &block) - genl open - indent &block - genl close - end - - def namespace(name, &block) - genl - names = name.split("::") - names.each { |n| genl "namespace #{n} {" } - genl "namespace {" if (names.empty?) - genl - yield - genl - genl('}'*([names.size, 1].max)+" // namespace "+name) - genl - end - - def struct_class(type, name, bases, &block) - gen "#{type} #{name}" - if (!bases.empty?) - genl ":" - indent { gen "#{bases.join(",\n")}" } - end - genl - scope("{","};", &block) - end - - def struct(name, *bases, &block) - struct_class("struct", name, bases, &block); - end - def cpp_class(name, *bases, &block) - struct_class("class", name, bases, &block); - end - def cpp_extern_class(scope, name, *bases, &block) - struct_class("class "+scope, name, bases, &block); - end - - def typedef(type, name) genl "typedef #{type} #{name};\n"; end - - def variant(types) "boost::variant<#{types.join(", ")}>"; end - def variantl(types) "boost::variant<#{types.join(", \n")}>"; end - def blank_variant(types) variant(["boost::blank"]+types); end - def tuple(types) "boost::tuple<#{types.join(', ')}>"; end - - def public() outdent { genl "public:" } end - def private() outdent { genl "private:" } end - def protected() outdent { genl "protected:" } end - - # Returns [namespace, classname, filename] - def parse_classname(full_cname) - names=full_cname.split("::") - return names[0..-2].join('::'), names[-1], names.join("/") - end - - def doxygen_comment(&block) - genl "/**" - 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 - - def signature(ret_name, params, trailer="") - if params.size <= 1 - genl ret_name+"(#{params})"+trailer - else - scope(ret_name+"(",")"+trailer) { genl params.join(",\n") } - end - end - - def function_decl(ret_name, params=[], trailer="") - signature(ret_name, params, trailer+";") - end - - def function_defn(ret_name, params=[], trailer="") - genl - signature(ret_name, params, trailer) - scope() { yield } - end - - def ctor_decl(name, params=[]) function_decl(name, params); end - - def ctor_defn(name, params=[], inits=[]) - signature(name, params, inits.empty? ? "" : " :") - indent { gen inits.join(",\n") } if not inits.empty? - scope() { yield } - end - - def function_call(name, params=[], trailer="") - gen name - list "(",params, ")" - gen trailer - end -end - -# Fully-qualified class name -class FqClass < Struct.new(:fqname,:namespace,:name,:file) - def initialize(fqclass) - names=fqclass.split "::" - super(fqclass, names[0..-2].join('::'), names[-1], names.join("/")) - end -end - |