text:
require 'iconv'
require 'pathname'
require 'rexml/document'
require 'set'

require 'bridgesupportparser.so'

module Bridgesupportparser
    def self.add_blockattrs(hash)
	@blockattrs = @blockattrs0.nil? ? hash : @blockattrs0.merge(hash)
    end

    def self.blockattr?(k)
	@blockattrs ||= @blockattrs0 || {}
	@blockattrs.has_key?(k)
    end

    # This lambda (returned by Bridgesupportparser::custom_recursive_merge_64)
    # can be used to merge 64-bit attributes into 32-bit attributes, when
    # passed to Parser#set_custom_recursive_merge.
    @custom_recursive_merge_64 = lambda do |k, a0, a1|
	m = k.to_s.match(/^(.*)64$/)
	if m
	    k0 = m[1].to_sym
	    return if a0.include?(k0) && a0[k0].eql?(a1[k])
	end
	a0[k] = a1[k]
    end

    def self.custom_recursive_merge_64
	@custom_recursive_merge_64
    end

    def self.rename_attrs64
	{
	    :_ctype => :_ctype64,
	    :declared_type => :declared_type64,
	    :sel_of_type => :sel_of_type64,
	    :type => :type64,
	    :value => :value64,
	}
    end

    class MergingArray < Array
	attr_reader :name

	def initialize(name = 'MergingArray', *args)
	    super(*args)
	    @name = name
	end

	def []=(n, v)
	    if self[n].nil?
		super
	    else
		if self[n].respond_to?(:recursive_merge!)
		    self[n].recursive_merge!(v)
		else
		    if !self[n].eql?(v)
			warn "MergingArray:#{@name}[#{n}]: #{self[n]} => #{v}"
			super
		    end
		end
	    end
	    self[n]
	end

	def recursive_merge!(ary)
	    (self.length >= ary.length ? self : ary).each_index do |i|
		self[i] = ary[i] unless ary[i].nil?
	    end
	end
    end

    class MergingHash < Hash
	attr_reader :name

	def initialize(name = 'MergingHash', *args)
	    super(*args)
	    @name = name
	end

	def []=(k, v)
	    if self.include?(k)
		if self[k].respond_to?(:recursive_merge!)
		    #print "MergingHash: k=#{k} v=#{v.inspect} #{self[k].inspect}" #DEBUG
		    self[k].recursive_merge!(v)
		    #puts " => #{self[k].inspect}" #DEBUG
		else
		    if !self[k].eql?(v)
			warn "MergingHash:#{@name}[#{k}]: #{self[k]} => #{v}"
			super
		    end
		end
	    else
		super
	    end
	    self[k]
	end

	def recursive_merge!(m)
	    m.each { |k, v| self[k] = v }
	end
    end

    class MergingSequence < MergingArray
	attr_reader :name

	def initialize(name, *argv)
	    super
	    @index = 0
	end

	def <<(a)
	    a[:_index] = @index
	    super
	    @index += 1
	end
    end

    class MergingSet < Set
	alias_method :orig_add, :add
	attr_reader :name
	def initialize(name = 'MergingSet', *args)
	    super(*args)
	    @name = name
	end

	def add(x)
	    found = self.any? do |s|
		if s.eql?(x)
		    s.recursive_merge!(x) if s.respond_to?(:recursive_merge!)
		    true
		else
		    false
		end
	    end
	    self.orig_add(x) if !found
	end

	def recursive_merge!(enum)
	    enum.each { |e| add(e) }
	end
    end

    class Base # abstract
	attr_reader :attrs

	class << self
	    attr_reader :attr_transform, :element_name

	    def attrmap
		@attrmap ||= (@attrmap0 || {})
	    end

	    def blockattr?(k)
		@blockattrs ||= @blockattrs0 || {}
		return true if Bridgesupportparser.blockattr?(k)
		@blockattrs.has_key?(k)
	    end

	    # By default, attributes are blocked if their names begin with
	    # underscore, or if the blockattr? method returns true for that key.
	    # The set_attr_transform method provides a more general approach
	    # to determining what attributes will be displayed.  It is passed
	    # a Proc instance, and this Proc will be passed two argument.  The
	    # first argument is the attribute hash to process, while the second
	    # argument is lambda that given a key, will call the class-specific
	    # blockattr? method (which can be ignored if unneeded).  The Proc
	    # instance should return a new hash (or array of arrays of key/value
	    # pairs) that will substitute for the original attribute hash.  If
	    # the return is nil or an empty hash/array, no xml will be generate.
	    def set_attr_transform(t)
		@attr_transform = t
	    end
	end

	@@valmap = {
	    'false' => false,
	    'true' => true,
	}

	def self.add_blockattrs(hash)
	    @blockattrs = @blockattrs0.nil? ? hash : @blockattrs0.merge(hash)
	end

	def initialize(parser, name)
	    @parser = parser
	    @_name = "<#{self.class}>#{(name and !name.empty?) ? name : '<anonymous>'}"
	    @attrs = MergingHash.new(@_name)
	    @parser.add_attrs(@attrs)
	    self[:name] = name if name and !name.empty?
	end

	def initialize_copy(orig)
	    @attrs = orig.attrs.dup
	    @parser.add_attrs(@attrs)
	end

	# default accessors (mutators not supported)
	def method_missing(sym)
	    self[sym]
	end

	def [](k)
	    @attrs[k]
	end

	def []=(k, v)
	    if self.class.attrmap.include?(k)
		key, val = self.class.attrmap[k].call(k, v)
	    else
		key, val = k, v
	    end
	    val = @@valmap.fetch(val, val);
	    @attrs[key] = val unless val.nil?
	end

	def <=>(x)
	    self[:name] <=> x[:name]
	end

	def delete(k)
	    @attrs.delete(k)
	end

	def each(&block)
	    if block
		@attrs.each &block
	    end
	end

	def element
	    attr_transform = self.class.attr_transform
	    if attr_transform.nil?
		attrs = @attrs.select { |k, v| k.to_s[0] != ?_ && !self.class.blockattr?(k)}
	    else
		klass = self.class
		attrs = attr_transform.call(@attrs, lambda { |a| klass.blockattr?(a) })
	    end
	    #puts "Base: #{self.name} attrs=#{attrs.inspect}" #DEBUG
	    return nil if attrs.nil? || attrs.empty?
	    e = REXML::Element.new(self.class.element_name)
	    attrs.each { |k, v| e.attributes[k.to_s] = v }
	    e
	end

	def eql?(o)
	    self[:name] == o[:name]
	end

	def hash
	    self[:name].hash
	end

	def recursive_merge!(m)
	    custom_recursive_merge = @parser.custom_recursive_merge
	    #puts "Bridgesupportparser::Base.recursive_merge!: #{@attrs.inspect} #{m.attrs.inspect} custom_recursive_merge=#{custom_recursive_merge.inspect}" #DEBUG
	    if custom_recursive_merge.nil?
		@attrs.recursive_merge!(m.attrs)
	    else
		m.attrs.each_key { |k| custom_recursive_merge.call(k, @attrs, m.attrs) }
	    end
	end

	def type # avoid deprecation warning for Object#type
	    self[:type]
	end
    end

    class CFTypeInfo < Base
	@element_name = 'cftype'

	def initialize(parser, name, enc, attrs = nil, func = nil)
	    super(parser, name)
	    self[:type] = enc if enc and !enc.empty?
	    attrs.each { |k, v| self[k] = v } if attrs
	    self[:gettypeid_func] = func if func and !func.empty?
	end
    end

    class FunctionAliasInfo < Base
	@element_name = 'function_alias'

	def initialize(parser, name, orig)
	    super(parser, name)
	    self[:original] = orig
	end
    end

    class OpaqueInfo < Base
	@element_name = 'opaque'

	def initialize(parser, name, enc)
	    super(parser, name)
	    self[:type] = enc if enc and !enc.empty?
	end
    end

    class ValueInfo < Base # abstract
	@element_name = 'enum'

	def initialize(parser, name, value)
	    super(parser, name)
	    self[:value] = value unless value.nil?
	end
    end

    class EnumInfo < ValueInfo
	@element_name = 'enum'
    end

    class NumberInfo < ValueInfo
	@element_name = 'enum'
    end

    class NumberFuncCallInfo < ValueInfo
	@element_name = 'enum'

	def initialize(parser, name)
	    super(parser, name, nil)
	end
    end

    class StringInfo < ValueInfo
	@element_name = 'string_constant'
	@@iconv = Iconv.new('UTF-8', 'MACROMAN')

	def initialize(parser, name, value, nsstring = false)
	    # make sure the string is UTF-8.  If not, assume it is MacRoman
	    # and convert to UTF-8
	    begin
		value.unpack('U*') # throws exception if not UTF-8
	    rescue
		value = @@iconv.iconv(value)
	    end
	    super(parser, name, value)
	    self[:nsstring] = true if nsstring
	end
    end

    class VarInfoBase < Base #abstract
	def initialize(parser, name, type, enc, attrs = nil, funcptr = nil)
	    super(parser, name)
	    if type
		self[:_ctype] = type
		t = type.gsub( /\[[^\]]*\]/, '*' )
		re = /\b(__)?const\b/
		if t.match(re)
		    # don't set :const if the const is only part of the arguments
		    # to a function pointer
		    self[:const] = true if t.sub(/\(.*/, '').match(re)
		    t.gsub!(re, '')
		end
		t.gsub!(/<[^>]*>/, '')
		t.gsub!(/\b(in|out|inout|oneway|const)\b/, '')
		t.gsub!(/\b(__private_extern__|restrict)\b/, '')
		t.strip!
		t.squeeze!(' ')
		t.sub!(/\s+(\*+)$/, '\1')
		raise "empty type (was '#{type}')" if t.empty?
		self[:declared_type] = t
	    end
	    #self[:type] = enc if enc
	    if enc
		if enc =~ /^\^*\{\?=/
		    # An unnamed structure typedef.  Use the typedef name
		    # from declared_type.
		    td = self[:declared_type].gsub(/[^\w]/, '')
		    enc.sub!(/^(\^*)\{\?=/, "\\1{_#{td}=")
		    self[:_type_override] = true
		elsif t
		    case t
		    when /^(BOOL|Boolean)$/
			# the encoding should already be 'B' (custom header files)
			self[:_type_override] = true
		    when /^(BOOL|Boolean)\s*\*$/
			# the encoding should already be '^B' (custom header files)
			self[:_type_override] = true
		    end
		end
		self[:type] = enc
	    end
	    attrs.each { |k, v| self[k] = v } if attrs
	    if funcptr
		@funcptr = funcptr
		self[:function_pointer] = true
	    end
	end

	def element
	    e = super
	    return nil if e.nil?
	    if function_pointer?
		f = @funcptr.element
		#puts "VarInfo: #{self.name} funcptr=#{@funcptr} f=#{f.inspect}" #DEBUG
		f.each_element { |el| e.add_element(el) } if f
	    end
	    e
	end

	def function_pointer
	    @funcptr
	end

	def function_pointer?
	    self[:function_pointer]
	end

	def recursive_merge!(m)
	    super
	    if function_pointer?
		@funcptr.recursive_merge!(m.function_pointer) if m.function_pointer?
	    elsif m.function_pointer?
		@funcptr = m.function_pointer
	    end
	end

	def pointer_type?
	    self.type && self.type[0] == ?^
	end
    end

    class VarInfo < VarInfoBase
	@attrmap0 = {
	    :nonnull => lambda {|k, v| [:null_accepted, !v]},
	}
	@element_name = 'constant'

	def initialize(parser, name, type, enc, attrs = nil, funcptr = nil)
	    super
	    parser.all_varinfos << self
	end
    end

    class ArgInfo < VarInfo
	@attrmap0 = {
	    :nonnull => lambda {|k, v| [:null_accepted, !v]},
	}
	@element_name = 'arg'
    end

    class FieldInfo < VarInfoBase
	attr_accessor :resolved
	@attrmap0 = {
	    :nonnull => lambda {|k, v| [:null_accepted, !v]},
	}
	@element_name = 'field'
    end

    class RetvalInfo < VarInfo
	@attrmap0 = {
	    :nonnull => lambda {|k, v| [:null_accepted, !v]},
	}
	@element_name = 'retval'
    end

    class RetvalPtrInfo < VarInfo
	@attrmap0 = {
	    :nonnull => lambda {|k, v| [:null_accepted, !v]},
	}
	@element_name = 'retval'
    end

    class ObjCArgInfo < ArgInfo
	@attrmap0 = {
	    :in => lambda {|k, v| [:type_modifier, "n"]},
	    :_index => lambda {|k, v| [:index, v]},
	    :inout => lambda {|k, v| [:type_modifier, "N"]},
	    :nonnull => lambda {|k, v| [:null_accepted, !v]},
	    :out => lambda {|k, v| [:type_modifier, "o"]},
	}
	@element_name = 'arg'

	def initialize(parser, name, type, enc, mod, attrs = nil, funcptr = nil)
	    super(parser, name, type, enc, attrs, funcptr)
	    if mod
		self[:type_modifier] = mod
		self[:_override] = true
	    end
	end
    end

    class ObjCRetvalInfo < VarInfo
	@attrmap0 = {
	    :nonnull => lambda {|k, v| [:null_accepted, !v]},
	}
	@element_name = 'retval'
    end

    class CallableInfo < Base # abstract
	attr_reader :argc, :args, :ret

	def initialize(parser, name, ret, args, attrs, variadic)
	    super(parser, name)
	    @ret = ret if ret
	    @args = args if args
	    @argc = @args.size if args
	    self[:variadic] = true if variadic
	    return unless attrs
	    attrs.each do |k, v|
		prefix, key = k.to_s.split(':', 2)
		if(!key.nil?)
		    case prefix
		    when 'return_value'
			@ret[key.intern] = v
		    end
		    next
		end
		case k
		when :format
		    which, str, first = v.split(',')
		    arg = @args[str.to_i - 1]
		    arg[:printf_format] = true unless arg.nil?
		when :nonnull
		    v.split(',').each do |n|
			arg = @args[n.to_i]
			arg[:null_accepted] = false unless arg.nil?
		    end
		else
		    self[k] = v
		end
	    end
	end

	def each_argument(&block)
	    if @args && block
		@args.each &block
	    end
	end

	def recursive_merge!(m)
	    super
	    @ret.recursive_merge!(m.ret) if m.ret
	    if @argc < m.argc
		warn "CallableInfo::recursive_merge!:#{@_name}:argc: #{@argc} => #{m.argc}"
		@argc = m.argc
	    end
	    @args.recursive_merge!(m.args) if m.args
	end

	def variadic?
	    self[:variadic] == true
	end
    end

    class FuncInfo < CallableInfo
	@element_name = 'function'

	def initialize(parser, name, ret, args, attrs, variadic, inline=false)
	    super(parser, name, ret, args, attrs, variadic)
	    self[:name] = name if name and !name.empty?
	    self[:inline] = true if inline
	end

	def <=>(x)
	    self[:name] <=> x[:name]
	end

	def dylib_wrapper(prefix = '_dw_')
	    lines = []
	    args = []
	    targs = []
	    i = 0
	    @args.each do |a|
		ai = "_a#{i}"
		args << ai
		targs << "#{a._ctype} #{ai}"
		i += 1
	    end
	    name = "#{prefix}#{self[:name]}"
	    proto = "#{@ret._ctype} #{name}(#{targs.join(', ')})"
	    lines << "#{proto} __asm(\"_#{self[:name]}\");"
	    lines << "#{proto} {"
	    cline = "    "
	    cline << "return " unless @ret.type == 'v'
	    cline << "#{self[:name]}(#{args.join(', ')});"
	    lines << cline
	    lines << "}\n"
	    lines.join("\n")
	end

	def element
	    # Function pointers may have no attributes at all, so could get
	    # optimized away.  Since the element is only use to hold the
	    # arguments to be passed to another element, we just create a
	    # dummy element, if needed
	    e = super || REXML::Element.new('DUMMY')
	    @args.each { |a| e.add_element(a.element) }
	    rete = @ret.element
	    e.add_element(rete) unless rete.nil?
	    e
	end

	def eql?(o)
	    self[:name] == o[:name]
	end

	def hash
	    self[:name].hash
	end

	def inline?
	    self[:inline] == true
	end
    end

    class MethodInfo < CallableInfo
	attr_reader :seltype

	@arg_select = nil
	@ret_select = nil
	class << self
	    attr_reader :arg_select, :ret_select

	    def set_arg_select(p)
		@arg_select = p
	    end

	    def set_ret_select(p)
		@ret_select = p
	    end
	end

	@attrmap0 = {
	    :name => lambda {|k, v| [:selector, v]},
	}
	@element_name = 'method'

	def initialize(parser, selector, menc, ret, args, attrs, is_class, variadic)
	    super(parser, selector, ret, args, attrs, variadic)
	    self[:class_method] = true if is_class
	    @seltype = menc
	end

	def <=>(o)
	    cmp = self[:selector] <=> o[:selector]
	    return cmp unless cmp == 0
	    return 0 if self[:class_method] == o[:class_method]
	    return -1 if self[:class_method]
	    return 1
	end

	def class_method?
	    self[:class_method] == true
	end

	def element
	    arg_select = self.class.arg_select
	    if arg_select.nil?
		args = @args
	    else
		args = @args.select { |a| arg_select.call(a) }
	    end
	    ret_select = self.class.ret_select
	    if ret_select.nil?
		ret = @ret
	    else
		ret = @ret if ret_select.call(@ret)
	    end
	    eargs = args.collect { |a| a.element }.compact
	    #puts "args.empty?=#{args.empty?} ret.nil?=#{ret.nil?}" #DEBUG
	    return nil if eargs.empty? && ret.nil? && self[:type].nil? && !self[:_override]
	    e = super
	    eargs.each { |a| e.add_element(a) }
	    if ret
		rete = ret.element
		e.add_element(rete) if rete
	    end
	    e
	end

	def eql?(o)
	    self[:selector] == o[:selector] && self[:class_method] == o[:class_method]
	end

	def hash
	    self[:selector].hash
	end
    end

    class ObjCContainerInfo # abstract
	attr_reader :methods, :name, :protocols

	class << self
	    attr_reader :element_name
	end

	def initialize(parser, name, methods, protocols)
	    @parser = parser
	    @name = name
	    @methods = methods
	    @protocols = protocols
	end

	def concat(a)
	    @methods.recursive_merge!(a.methods)
	end

	def dup_methods
	    methods = Bridgesupportparser::MergingSet.new(@methods.name)
	    @methods.each { |m| methods << m.dup }
	    @methods = methods
	end

	def each_method(&block)
	    if @methods && block
		@methods.each &block
	    end
	end

	def each_protocol(&block)
	    if @protocols && block
		@protocols.each &block
	    end
	end

	def element
	    methods = @methods.sort.collect { |m| m.element } .compact
	    return nil if methods.empty?
	    e = REXML::Element.new(self.class.element_name)
	    e.attributes['name'] = @name
	    methods.each { |m| e.add_element(m) }
	    e
	end

	def recursive_merge!(m)
	    @methods.recursive_merge!(m.methods)
	    if @protocols
		@protocols.merge(m.protocols) if m.protocols
	    elsif m.protocols
		@protocols = m.protocols
	    end
	end
    end

    class ObjCCategoryInfo < ObjCContainerInfo
	attr_reader :klass
	@element_name = 'informal_protocol'

	def initialize(parser, name, klass, methods=Bridgesupportparser::MergingSet.new("category #{name} for #{klass}"), protocols=Set.new)
	    super(parser, name, methods, protocols)
	    @klass = klass
	end
    end

    class ObjCInterfaceInfo < ObjCContainerInfo
	@element_name = 'class'
    end

    class ObjCProtocolInfo < ObjCContainerInfo
    end

    class StructInfo < Base
	attr_accessor :resolved
	attr_reader :fields

	class << self
	    attr_accessor :block_fields
	end

	@block_fields = false
	@element_name = 'struct'

	def initialize(parser, name, encoding, fields)
	    super(parser, name)
	    self[:name] = name if name and !name.empty?
	    if encoding and !encoding.empty?
		if encoding =~ /^\{\?=/
		    enc = encoding.dup #DEBUG
		    # An unnamed structure typedef.  Use the StructInfo name
		    # for compatibility with previous gen_bridge_metadata.
		    encoding.sub!(/^\{\?=/, "{_#{name}=")
		    #puts "StructInfo: #{name} \"#{enc}\" => \"#{encoding}\"" #DEBUG
		end
		self[:type] = encoding
	    end
	    @fields = fields
	end

	def each_field(&block)
	    if @fields && block
		@fields.each &block
	    end
	end

	def element
	    e = super
	    return nil if e.nil?
	    if !self.class.block_fields
		@fields.each { |f| e.add_element(f.element) }
	    end
	    e
	end

	def recursive_merge!(m)
	    super
	    @fields.recursive_merge!(m.fields) if m.fields
	end

	def rename(n)
	    self.delete(:name) # to avoid recursive_merge! warnings
	    self[:name] = n
	end
    end

    class Parser
	attr_reader :all_attrs, :all_categories, :all_cftypes, :all_enums, :all_funcs, :all_func_aliases, :all_informal_protocols, :all_interfaces, :all_macronumbers, :all_macronumberfunccalls, :all_macrostrings, :all_opaques, :all_protocols, :all_structs, :all_varinfos, :all_vars, :custom_recursive_merge, :every_cftype, :special_method_encodings, :special_type_encodings

	# These values must match those in bridgesupport.cpp
	CONTENT = '__9_OxQk__4__c_0_n_T_3_n_t_'
	CONTENTEND = '__9_OxQk__4__3_0_F_'
	CONTENTMETHOD = CONTENT + '_m_3_T_h_0_d_'
	CONTENTTYPE = CONTENT + '_t_Y_p_3_'

	# There doesn't seem to be a foolproof way to determine if a typedef
	# whose name ends in "Ref" is a CFType or not.  So assuming that each
	# system framework is consistent, we create a list (stored in a hash)
	# for framework names where such typedefs are not CFTypes.
	DISABLE_CFTYPES = {
	    'CarbonCore' => true,
	    'JavaScriptCore' => true,
	}
	# This regexp extracts system framework names (including nested ones)
	FRAMEWORK_RE = Regexp.new('/System/Library/(?:Private)?Frameworks/(?:.*/)?([^/]*)\.framework/')

	def initialize(incs, paths, special_methods, special_types, defines = nil, incdirs = nil, sysroot = '/')
	    @all_attrs = []
	    @parsepaths = incs
	    puts "incs:\n#{incs.join("\n")}" if $DEBUG #DEBUG
	    puts "paths:\n#{paths.join("\n")}" if $DEBUG #DEBUG
	    if $DEBUG #DEBUG
		puts "incdirs:"
		incdirs.each { |i| puts "#{i[3..-1]} #{i[0,1]} #{i[1,1]} #{i[2,1]}" }
	    end #DEBUG
	    a = []
	    @special_methods = special_methods
	    @special_types = special_types
	    unless @special_methods.nil?
		@special_methods.each_index do |i|
		    t = @special_methods[i].sub(/^\s*[-+]/, '').sub(/;\s*$/, '').strip
		    a << "@interface #{CONTENTMETHOD}_#{i}\n" \
			+ "- #{t};\n" \
			+ "@end"
		end
		@special_method_encodings = []
	    end
	    unless @special_types.nil?
		@special_types.each_index { |i| a << "#{@special_types[i]} #{CONTENTTYPE}_#{i};\n" }
		@special_type_encodings = []
	    end
	    @parsecontent = a.join("\n") + "\n"
	    puts "parsecontent:\n#{@parsecontent}" if $DEBUG
	    #@parsedefines = ['__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__=1070']
	    #@parsedefines.concat(defines) unless defines.nil?
	    @parsedefines = defines;
	    @parseincdirs = incdirs
	    @parsesysroot = sysroot
	    # Allow header files in the directory hierarchies.  For framework
	    # directories, allow sub-framework headers.  The basename of the
	    # header must also match.
	    @parse_select = Set.new
	    @parse_select_basenames = {}
	    select = Set.new
	    paths.each do |p|
		select << Pathname.new(p).realpath.parent.to_s
		@parse_select_basenames[File.basename(p)] = true
	    end
	    select.each { |p| @parse_select << p.sub(/\.framework\/.*/, '.framework') }
	    #puts "@parse_select:\n#{@parse_select.to_a.join("\n")}" #DEBUG
	    #puts "@parse_select_basenames:\n#{@parse_select_basenames.keys.join("\n")}" #DEBUG
	    @parsepathcache = {CONTENT => [true, true]}
	    @all_categories = {}
	    @all_cftypes = Bridgesupportparser::MergingHash.new('all_cftypes')
	    @all_enums = Bridgesupportparser::MergingHash.new('all_enums')
	    @all_funcs = Bridgesupportparser::MergingHash.new('all_funcs')
	    @all_func_aliases = Bridgesupportparser::MergingHash.new('all_func_aliases')
	    @all_informal_protocols = Bridgesupportparser::MergingHash.new('all_informal_protocols')
	    @all_interfaces = Bridgesupportparser::MergingHash.new('all_interfaces')
	    @all_macronumbers = Bridgesupportparser::MergingHash.new('all_macronumbers')
	    @all_macrostrings = Bridgesupportparser::MergingHash.new('all_macrostrings')
	    @all_macronumberfunccalls = Bridgesupportparser::MergingHash.new('all_macronumberfunccalls')
	    @all_opaques = Bridgesupportparser::MergingHash.new('all_opaques')
	    @all_protocols = Bridgesupportparser::MergingHash.new('all_protocols')
	    @all_structs = Bridgesupportparser::MergingHash.new('all_structs')
	    @all_varinfos = []
	    @all_vars = Bridgesupportparser::MergingHash.new('all_vars')
	    @every_cftype = {}
	    @only_classes = {}
	end

	#######
	private
	#######

	def __xattr__(x)
	    "__attribute__((__annotate__(\"xattr:#{x}\")))"
	end

	# The difference between recursivefunc() and recursivefuncptr() is that
	# the first is called for functions (proper), and their return values
	# are instances of RetvalInfo.  recursivefunc() calls recursivefuncptr()
	# if an argument or return value is a function pointer, and its return
	# value will be an instance of RetvalPtrInfo.  recursivefuncptr() may
	# call itself recursively.
	def recursivefuncptr(f)
	    return nil if f.nil?
	    func, rettype, retenc, retattrs, retfunc, fattrs, variadic, inline = f.info
	    #puts "#{func} #{rettype} #{retenc} retattrs=#{retattrs.inspect} fattrs=#{fattrs.inspect} retfunc=#{!retfunc.nil?} variadic=#{variadic} inline=#{inline}" #DEBUG
	    ret = Bridgesupportparser::RetvalPtrInfo.new(self, nil, rettype, retenc, retattrs, recursivefuncptr(retfunc))
	    args = Bridgesupportparser::MergingSequence.new('recursivefuncptr')
	    f.each_argument do |name, type, enc, attrs, funcptr|
		# While we can generate recursive function pointers, some
		# BridgeSupport users (like MacRuby) can't deal with them.
		# So we avoid the recursion for now
		#args << Bridgesupportparser::ArgInfo.new(self, name, type, enc, attrs, recursivefuncptr(funcptr))
		args << Bridgesupportparser::ArgInfo.new(self, name, type, enc, attrs, nil)
	    end
	    Bridgesupportparser::FuncInfo.new(self, func, ret, args, fattrs, variadic, inline)
	end

	def recursivefunc(f)
	    return nil if f.nil?
	    func, rettype, retenc, retattrs, retfunc, fattrs, variadic, inline = f.info
	    #puts "#{func} #{rettype} #{retenc} retattrs=#{retattrs.inspect} fattrs=#{fattrs.inspect} retfunc=#{!retfunc.nil?} variadic=#{variadic} inline=#{inline}" #DEBUG
	    ret = Bridgesupportparser::RetvalInfo.new(self, nil, rettype, retenc, retattrs, recursivefuncptr(retfunc))
	    args = Bridgesupportparser::MergingSequence.new('recursivefunc')
	    f.each_argument do |name, type, enc, attrs, funcptr|
		args << Bridgesupportparser::ArgInfo.new(self, name, type, enc, attrs, recursivefuncptr(funcptr))
	    end
	    Bridgesupportparser::FuncInfo.new(self, func, ret, args, fattrs, variadic, inline)
	end

	def make_method(m)
	    sel, menc, rettype, retenc, retattrs, retfunc, mattrs, classmeth, variadic = m.info
	    ret = Bridgesupportparser::ObjCRetvalInfo.new(self, nil, rettype, retenc, retattrs, recursivefuncptr(retfunc))
	    args = Bridgesupportparser::MergingSequence.new("#{sel}.args")
	    m.each_argument do |name, type, enc, mod, attrs, funcptr|
		args << Bridgesupportparser::ObjCArgInfo.new(self, name, type, enc, mod, attrs, recursivefuncptr(funcptr))
	    end
	    Bridgesupportparser::MethodInfo.new(self, sel, menc, ret, args, mattrs, classmeth, variadic)
	end

	def make_opaque_or_struct(tname, name, decl)
	    if decl
		sname, senc = decl.info # "sname" is the same as "name"
		@all_structs[tname] = make_struct(tname, senc, decl)
	    else
		# promote forward reference to pointer to struct
		@all_opaques[tname] = Bridgesupportparser::OpaqueInfo.new(self, tname, "^{#{name}=}")
	    end
	end

	def make_struct(sname, senc, struct)
	    fields = Bridgesupportparser::MergingSequence.new(sname)
	    struct.each_field do |name, type, enc, attrs, funcptr|
		fields << Bridgesupportparser::FieldInfo.new(self, name, type, enc, attrs, recursivefuncptr(funcptr))
	    end
	    Bridgesupportparser::StructInfo.new(self, sname, senc, fields)
	end

	def recurse_append_protocol(a, b, seen)
	    b.each_protocol do |p|
		#puts ">p>#{p} seen=#{seen[p] ? 'yes' : 'no'}" #DEBUG
		if !seen[p]
		    seen[p] = 1
		    proto = @all_protocols[p]
		    #proto.methods.sort.each {|m| puts ">p>#{m.selector}"} #DEBUG
		    #puts '>p>----------' #DEBUG
		    if proto.nil?
			warn "Unknown protocol: #{p} for interface #{a.name}" if $DEBUG
		    else
			a.concat(proto)
			recurse_append_protocol(a, proto, seen)
		    end
		end
	    end
	end

	def inParseTree?(path)
	    x = @parsepathcache[path]
	    return x unless x.nil?
	    # allow header files in the directory hierarchies that match
	    # the basenames
	    p = Pathname.new(path).realpath.parent.to_s
	    len = p.length
	    i = @parse_select.any? do |d|
		dlen = d.length
		intree = case (dlen <=> len)
		when 1
		    false
		when 0
		    p == d
		else
		    p[dlen] == ?/ && p[0...dlen] == d
		end
		intree && @parse_select_basenames[File.basename(path)]
	    end
	    m = FRAMEWORK_RE.match(p)
	    c = (!m || DISABLE_CFTYPES[m[1]]) ? true : false
	    @parsepathcache[path] = [i, c]
	end

	def splitName(name)
	    idx = name.rindex('_')
	    return name if idx.nil?
	    [name[0,idx], name[(idx+1)..-1]]
	end

	def validName(name)
	    !name.nil? and !name.empty?
	end

	def _parse(triple)
	    #realp = Pathname.new(path).realpath
	    #dir = File.dirname(realpath(path))
	    #puts triple #DEBUG
	    Bridgesupportparser::BridgeSupportParser.parse(@parsepaths, @parsecontent, triple, @parsedefines, @parseincdirs, @parsesysroot, $DEBUG) do |top|
		next if @only_classes[top.class]
		intree, disableCFTypes = inParseTree?(top.path)
		case top
		when Bridgesupportparser::ATypedef
		    tname, ttype, tattrs = top.info
		    #puts "ATypedef: #{tname} #{ttype} intree=#{intree}" #DEBUG
		    next unless validName(tname)
		    i = 0
		    top.walk_types do |name, type, decl, attr|
			case i
			when 0
			    case type
			    when 'Struct'
				break unless intree
				make_opaque_or_struct(tname, name, decl)
				break # only direct structs, no pointers to structs
			    when 'Pointer'
				# do another loop
			    when 'Typedef'
				if name == 'CFTypeRef'
				    @every_cftype[tname] = 1
				    break
				end
				i = 10 # do case "else"
			    else
				break
			    end
			when 1
			    #puts "Typedef 1: name=#{tname} type=#{type} attrs=#{tattrs.inspect}" #DEBUG
			    break if type == 'Pointer'
			    if tname =~ /Ref$/ && !disableCFTypes
				# assume this is a CFType.
				@all_cftypes[tname] = Bridgesupportparser::CFTypeInfo.new(self, tname, top.encoding, tattrs) if intree
				@every_cftype[tname] = 1
			    elsif type == 'Struct'
				next unless intree
				make_opaque_or_struct(tname, name, decl)
			    end
			    break
			else
			    #puts "ATypedef:walk_types #{name} #{type}" #DEBUG
			    case type
			    when 'Struct'
				break unless intree
				make_opaque_or_struct(tname, name, decl)
				break # only direct structs, no pointers to structs
			    when 'Typedef'
				if name == 'CFTypeRef'
				    @every_cftype[tname] = 1
				    break
				end
			    else
				break
			    end
			end
			i += 1
		    end
		    next
		end
		next unless intree
		case top
		when Bridgesupportparser::AnEnum
		    # enum = top.info # don't need enum name
		    top.each_value { |name, val| @all_enums[name] = Bridgesupportparser::EnumInfo.new(self, name, val) if validName(name) }
		when Bridgesupportparser::AFunction
		    fname, rettype, retenc, retattrs, retfunc, fattrs, variadic, inline = top.info
		    @all_funcs[fname] = recursivefunc(top) if validName(fname)
		when Bridgesupportparser::AMacroFunctionAlias
		    faname, val = top.info
		    @all_func_aliases[faname] = Bridgesupportparser::FunctionAliasInfo.new(self, faname, val) if validName(faname)
		when Bridgesupportparser::AMacroNumber
		    nname, val = top.info
		    next unless validName(nname)
		    @all_macronumbers[nname] = Bridgesupportparser::NumberInfo.new(self, nname, val) if validName(nname)
		when Bridgesupportparser::AMacroNumberFuncCall
		    nname = top.info
		    next unless validName(nname)
		    @all_macronumberfunccalls[nname] = Bridgesupportparser::NumberFuncCallInfo.new(self, nname) if validName(nname)
		when Bridgesupportparser::AMacroString
		    sname, val, objcstr = top.info
		    next unless validName(sname)
		    val.sub!(/^"/, '')
		    val.sub!(/"$/, '')
		    @all_macrostrings[sname] = Bridgesupportparser::StringInfo.new(self, sname, val, objcstr)
		when Bridgesupportparser::AnObjCCategory
		    klass, cname = top.info
		    #next unless validName(cname) # allow any name, including extensions
		    #puts "*** adding category #{cname} for #{klass}" #DEBUG
		    methods = Bridgesupportparser::MergingSet.new("category #{cname} for #{klass}")
		    top.each_method { |m| methods << make_method(m) }
		    protocols = Set.new
		    top.each_protocol { |p| protocols.add(p) }
		    if klass == 'NSObject'
			@all_informal_protocols[cname] = Bridgesupportparser::ObjCCategoryInfo.new(self, cname, klass, methods, protocols)
		    else
			(@all_categories[klass] ||= Bridgesupportparser::MergingHash.new("category #{cname} for #{klass}"))[cname] = Bridgesupportparser::ObjCCategoryInfo.new(self, cname, klass, methods, protocols)
		    end
		when Bridgesupportparser::AnObjCInterface
		    iname = top.info
		    content, idx = splitName(iname)
		    if content == CONTENTMETHOD
			top.each_method do |m|
			    sel, menc, rettype, retenc, retattrs, retfunc, mattrs, classmeth, variadic = m.info
			    @special_method_encodings[idx.to_i] = menc
			    break
			end
			next
		    end
		    next unless validName(iname) && iname != CONTENTEND
		    #puts "*** adding interface #{iname}" #DEBUG
		    methods = Bridgesupportparser::MergingSet.new("interface #{iname}")
		    top.each_method { |m| methods << make_method(m) }
		    protocols = Set.new
		    top.each_protocol { |p| protocols.add(p) }
		    @all_interfaces[iname] = Bridgesupportparser::ObjCInterfaceInfo.new(self, iname, methods, protocols)
		when Bridgesupportparser::AnObjCProtocol
		    pname = top.info
		    next unless validName(pname)
		    #puts "*** adding protocol #{pname}" #DEBUG
		    methods = Bridgesupportparser::MergingSet.new("protocol #{pname}")
		    top.each_method { |m| methods << make_method(m) }
		    protocols = Set.new
		    top.each_protocol { |p| protocols.add(p) }
		    @all_protocols[pname] = Bridgesupportparser::ObjCProtocolInfo.new(self, pname, methods, protocols)
		when Bridgesupportparser::AStruct
		    sname, senc = top.info
		    @all_structs[sname] = make_struct(sname, senc, top) if validName(sname)
		when Bridgesupportparser::AVar
		    vname, vtype, venc, attrs, funcptr = top.info
		    content, idx = splitName(vname)
		    if content == CONTENTTYPE
			@special_type_encodings[idx.to_i] = venc
			next
		    end
		    # We currently can't deal with globals that are function
		    # pointers, so just ignore any
		    #@all_vars[vname] = Bridgesupportparser::VarInfo.new(self, vname, vtype, venc, attrs, recursivefuncptr(funcptr)) if validName(vname)
		    @all_vars[vname] = Bridgesupportparser::VarInfo.new(self, vname, vtype, venc, attrs) if validName(vname) && funcptr.nil?
		end
	    end
	end

	def matchingbrace(str, off)
	    while true
		off = str.index(/[{}]/, off + 1)
		if str[off] == ?{
		    off = matchingbrace(str, off)
		else
		    break
		end
	    end
	    off
	end

	######
	public
	######

	def add_attrs(a)
	    @all_attrs << a
	end

	def addXML(root)
	    @all_structs.sort.each do |k, struct|
		e = struct.element
		root.add_element(e) unless e.nil?
	    end
	    @all_cftypes.sort.each do |k, cftype|
		e = cftype.element
		root.add_element(e) unless e.nil?
	    end
	    @all_opaques.sort.each do |k, opaque|
		e = opaque.element
		root.add_element(e) unless e.nil?
	    end
	    @all_vars.sort.each do |k, var|
		e = var.element
		root.add_element(e) unless e.nil?
	    end
	    @all_macrostrings.sort.each do |k, str|
		e = str.element
		root.add_element(e) unless e.nil?
	    end
	    enums = @all_enums.merge(@all_macronumbers)
	    @all_macronumberfunccalls.each { |k, v| enums[k] = v unless v.value.nil? }
	    enums.sort.each do |k, enum|
		e = enum.element
		root.add_element(e) unless e.nil?
	    end
	    @all_funcs.sort.each do |k, func|
		e = func.element
		root.add_element(e) unless e.nil?
	    end
	    @all_func_aliases.sort.each do |k, a|
		e = a.element
		root.add_element(e) unless e.nil?
	    end
	    @all_interfaces.sort.each do |k, interface|
		e = interface.element
		root.add_element(e) unless e.nil?
	    end
	    $bsp_informal_protocols = true
	    @all_informal_protocols.sort.each do |k, ip|
		e = ip.element
		root.add_element(e) unless e.nil?
	    end
	    $bsp_informal_protocols = nil
	end

	def each_attrs
	    if block_given?
		@all_attrs.each { |a| yield a }
	    end
	end

	def mergeWith64!(p64)
	    p64.rename_attrs(Bridgesupportparser.rename_attrs64)
	    set_custom_recursive_merge(Bridgesupportparser::custom_recursive_merge_64)
	    recursive_merge!(p64)
	end

	def parse(triple)
	    menc, tenc = _parse(triple)

#	    # Merge all category and protocol methods (recursively)
#	    @all_interfaces.each do |name, interf|
#		#puts ">#{name}" #DEBUG
#		cseen = {}
#		pseen = {}
#		recurse_append_protocol(interf, interf, pseen);
#		categ = @all_categories[name]
#		if categ
#		    categ.each_value do |c|
#			#puts ">c>#{c.name} seen=#{cseen[c.name] ? 'yes' : 'no'}" #DEBUG
#			if !cseen[c.name]
#			    cseen[c.name] = 1
#			    #c.methods.sort.each {|m| puts ">c>#{m.selector}"} #DEBUG
#			    #puts '>c>----------' #DEBUG
#			    interf.concat(c)
#			    recurse_append_protocol(interf, c, pseen);
#			end
#		    end
#		end
#	    end

	    # Merge categories into interfaces, creating as needed
	    @all_categories.each do |iname, h|
		interf = (@all_interfaces[iname] ||= Bridgesupportparser::ObjCInterfaceInfo.new(self, iname, Bridgesupportparser::MergingSet.new("interface #{iname}"), Set.new))
		h.each_value { |c| interf.concat(c) }
	    end

	    # Create a NSObject interface, if it doesn't already exist
	    nsobjcreated = false
	    nsobj = @all_interfaces['NSObject']
	    if nsobj.nil?
		nsobj = Bridgesupportparser::ObjCInterfaceInfo.new(self, 'NSObject', Bridgesupportparser::MergingSet.new("interface NSObject"), Set.new)
		nsobjcreated = true
	    end
	    # Merge all informal protocol methods into the NSObject interface.
	    @all_informal_protocols.each_value { |p| nsobj.concat(p) }
	    # For formal protocols, to emulate the previous gen_bridge_metadata
	    # behavior, protocol methods get merged into the NSObject interface.
	    # We also create a separate informal protocol with the methods of
	    # the formal protocol.
	    @all_protocols.each_value do |p|
		nsobj.concat(p)
		(@all_informal_protocols[p.name] ||= Bridgesupportparser::ObjCCategoryInfo.new(self, p.name, 'NSObject')).concat(p)
	    end
	    @all_interfaces['NSObject'] = nsobj if nsobjcreated && nsobj.methods.length > 0

	    # Go through the cftypes and for those without the gettypeid_func
	    # attribute, make up the standard name, and check against the
	    # known functions
	    @all_cftypes.each do |name, cftype|
		if !cftype.gettypeid_func
		    func = name.sub(/Ref$/, 'GetTypeID')
		    #puts "Trying #{func} for #{name}: #{@all_funcs[func]}" #DEBUG
		    if @all_funcs.has_key?(func)
			cftype[:gettypeid_func] = func
		    elsif func.sub!(/Mutable/, '')
			cftype[:gettypeid_func] = func if @all_funcs.has_key?(func)
		    end
		end
	    end

	    # For functions returning a cftype, with "Create" or "Copy" in
	    # the name, add the "already_retained" attribute to return value
	    @all_funcs.each do |name, func|
		ret = func.ret
		next unless ret.type != 'v'
		next if @every_cftype[ret.declared_type].nil?
		ret[:already_retained] = true if /(Create|Copy)/.match(name)
	    end

	    # Walk through all the type attributes and replace
	    # '^v' with '@' for cftypes
	    each_attrs do |a|
		dt = a[:declared_type]
		next if dt.nil? || @every_cftype[dt].nil?
		if a[:type] == '^v'
		    a.delete(:type) # delete to avoid recursive_merge! warning
		    a[:type] = '@'
		end
	    end

	    # For each method in each informal protocol, set the method "type"
	    # to the method encoding (we need to call dup_methods, so to
	    # avoid having "type" show up in NSObject methods, which are shared)
	    @all_informal_protocols.each do |name, ip|
		ip.dup_methods
		ip.each_method { |m| m[:type] = m.seltype }
	    end

	    # For each structure that has a nested anonymous-structure typedef,
	    # with structure name showing as '?', we replace the '?' with the
	    # type from the corresponding field.  We have to make multiple
	    # passes over the structures, until no more changes can be made.
	    anyunresolved = true
	    tagged_structs = {}
	    while anyunresolved
		anyunresolved = false
		@all_structs.each do |structname, struct|
		    next if struct.resolved
		    unless struct.type.match(/"\^*\{\?/)
			struct.resolved = true
			#puts "struct #{structname} already resolved" #DEBUG
			next
		    end
		    unresolved = false
		    struct.each_field do |f|
			next if f.resolved
			sname = f.declared_type.sub(/\s*\*$/, '')
			s = @all_structs[sname]
			if s
			    if s.resolved
				#resolvedtype = s.type.gsub(/"[^"]*"/, '')
				#puts "struct #{structname} field #{f.name} type=\"#{f.type}\" resolvedtype=\"#{resolvedtype}\"" #DEBUG
				#f.type[f.type.index(/\{/)..-1] = resolvedtype[resolvedtype.index(/\{/)..-1]
				f.type[f.type.index(/\{/)..-1] = s.type[s.type.index(/\{/)..-1]
				f.resolved = s.type.sub(/^\^*/, '')
				#puts "struct #{structname} field #{f.name} => #{f.type} (#{f.resolved})" #DEBUG
			    else
				unresolved = true
				#puts "struct #{structname} field #{f.name}: struct #{s.name} still unresolved" #DEBUG
			    end
			else
			    f.resolved = true
			end
		    end
		    if unresolved
			anyunresolved = true
			#puts "struct #{structname} remains unresolved" #DEBUG
		    else
			origtype = struct.type.dup
			struct.each_field do |f|
			    #puts "struct #{structname} field #{f.name} resolved=#{f.resolved}" #DEBUG
			    next if f.resolved == true
			    left = struct.type.index(/"#{f.name}"\^*\{/)
			    left = struct.type.index(/\{/, left.nil? ? 0 : left)
			    right = matchingbrace(struct.type, left)
			    #puts ">struct #{structname} field #{f.name} => #{f.resolved}" #DEBUG
			    #puts ">left=#{left} right=#{right} before=#{struct.type}" #DEBUG
			    struct.type[left..right] = f.resolved
			    #puts ">after=#{struct.type}" #DEBUG
			end
			if struct.type != origtype
			    tagged_structs[structname] = struct.type.sub(/^\^*/, '').gsub(/"[^"]*"/, '')
			    #puts ">>>Resolved: #{structname}" #DEBUG
			    #puts "\"#{origtype}\" =>" #DEBUG
			    #puts "\"#{struct.type}\"" #DEBUG
			end
			struct.resolved = true
			#puts "struct #{structname} is now resolved" #DEBUG
		    end
		end
	    end
	    #puts '=== tagged_structs ==='; tagged_structs.each {|k,v| puts "#{k}: #{v}"} #DEBUG
	    # Now walk through all the VarInfo instances, and replace with
	    # the new tagged structs
	    if tagged_structs.length > 0
		@all_varinfos.each do |v|
		    name = v.declared_type.sub(/\s*\*$/, '')
		    t = tagged_structs[name]
		    if t
			v.type[v.type.index(/\{/)..-1] = t
			v[:_type_override] = true
		    end
		end
	    end

	    if $DEBUG #DEBUG
		puts "@parsepathcache:" #DEBUG
		@parsepathcache.sort.each { |k, v| puts "#{k} => #{v.inspect}" } #DEBUG
	    end #DEBUG
	end

	def recursive_merge!(p)
	    # purge members that occur in 32-bit (self) and not in 64-bit (p)
	    # (@all_categories is a special case)

	    @all_categories.delete_if { |k, v| !p.all_categories.has_key?(k) }
	    @all_categories.each do |k, v|
		pp = p.all_categories[k]
		v.delete_if { |kk, vv| !pp.has_key?(kk) }
		v.recursive_merge!(pp)
	    end

	    @all_cftypes.delete_if { |k, v| !p.all_cftypes.has_key?(k) }
	    @all_cftypes.recursive_merge!(p.all_cftypes)
	    @all_enums.delete_if { |k, v| !p.all_enums.has_key?(k) }
	    @all_enums.recursive_merge!(p.all_enums)
	    @all_funcs.delete_if { |k, v| !p.all_funcs.has_key?(k) }
	    @all_funcs.recursive_merge!(p.all_funcs)
	    @all_func_aliases.delete_if { |k, v| !p.all_func_aliases.has_key?(k) }
	    @all_func_aliases.recursive_merge!(p.all_func_aliases)
	    @all_informal_protocols.delete_if { |k, v| !p.all_informal_protocols.has_key?(k) }
	    @all_informal_protocols.recursive_merge!(p.all_informal_protocols)
	    @all_interfaces.delete_if { |k, v| !p.all_interfaces.has_key?(k) }
	    @all_interfaces.recursive_merge!(p.all_interfaces)
	    @all_macronumbers.delete_if { |k, v| !p.all_macronumbers.has_key?(k) }
	    @all_macronumbers.recursive_merge!(p.all_macronumbers)
	    @all_macrostrings.delete_if { |k, v| !p.all_macrostrings.has_key?(k) }
	    @all_macrostrings.recursive_merge!(p.all_macrostrings)
	    @all_macronumberfunccalls.delete_if { |k, v| !p.all_macronumberfunccalls.has_key?(k) }
	    @all_macronumberfunccalls.recursive_merge!(p.all_macronumberfunccalls)
	    @all_opaques.delete_if { |k, v| !p.all_opaques.has_key?(k) }
	    @all_opaques.recursive_merge!(p.all_opaques)
	    @all_protocols.delete_if { |k, v| !p.all_protocols.has_key?(k) }
	    @all_protocols.recursive_merge!(p.all_protocols)
	    @all_structs.delete_if { |k, v| !p.all_structs.has_key?(k) }
	    @all_structs.recursive_merge!(p.all_structs)
	    @all_vars.delete_if { |k, v| !p.all_vars.has_key?(k) }
	    @all_vars.recursive_merge!(p.all_vars)
	end

	def rename_attrs(h)
	    @all_attrs.each do |attrs|
		h.each { |k, v| attrs[v] = attrs.delete(k) if attrs.include?(k) }
	    end
	end

	# By default, we rely on MergingHash's recursive_merge! method
	# to merge the attributes.  If set_custom_recursive_merge is passed
	# a lambda, that lambda will be responsible for merging each
	# attribute.  The arguments passed to the lambda are:
	#     key, self_attrs, other_attrs
	# where "key" is the current key symbol to merge, "self_attrs" is
	# the (MergingHash) attributes we are merging into, and
	# "other_attrs" is the (MergingHash) attributes we are merging.
	def set_custom_recursive_merge(m)
	    #puts "set_custom_recursive_merge=#{m.inspect}" #DEBUG
	    @custom_recursive_merge = m
	end
#####################################################
#################### DEBUGGING ######################
#####################################################

	def writeXML(file, version, doctype = false, indent = 4)
	    xml = REXML::Document.new
	    xml << REXML::XMLDecl.new
	    xml << REXML::DocType.new(['signatures', 'SYSTEM', '"file://localhost/System/Library/DTDs/BridgeSupport.dtd"']) if doctype
	    xml.add_element('signatures')
	    root = xml.root
	    root.attributes['version'] = version
	    addXML(root)
	    xml.write(file, indent)
	    file.print "\n"
	end

	#######
	private
	#######

	def dumpargs(func, indent = 0)
	    i = '  ' * indent
	    func.each_argument do |a|
		puts "#{i}#{a.name}: attrs=#{a.attrs.inspect}"
		dumpfunc(a.function_pointer, indent + 1) if a.function_pointer?
	    end
	end

	def dumpcateg(categ, indent = 0)
	    i = '  ' * indent
	    puts "---------\n" if indent == 0
	    protolist("#{i}#{categ.klass} (#{categ.name}): protocols=", categ)
	    dumpmeths(categ, indent + 1)
	end

	def dumpfields(struct, indent = 0)
	    i = '  ' * indent
	    struct.each_field do |f|
		puts "#{i}#{f.name}: attrs=#{f.attrs.inspect}"
		dumpfunc(f.function_pointer, indent + 1) if f.function_pointer?
	    end
	end

	def dumpfunc(func, indent = 0)
	    i = '  ' * indent
	    puts "---------\n" if indent == 0
	    puts "#{i}#{func.name}: retattrs=#{func.ret.attrs.inspect} attrs=#{func.attrs.inspect} variadic=#{func.variadic?} inline=#{func.inline?}"
	    dumpfunc(func.ret.function_pointer, indent + 1) if func.ret.function_pointer?
	    dumpargs(func, indent + 1)
	end

	def dumpmeths(container, indent = 0)
	    i = '  ' * indent
	    container.each_method do |meth|
		puts "#{i}#{meth.selector}: retattrs=#{meth.ret.attrs.inspect} attrs=#{meth.attrs.inspect} class_method=#{meth.class_method?} variadic=#{meth.variadic?}"
		dumpfunc(meth.ret.function_pointer, indent + 1) if meth.ret.function_pointer?
		dumpargs(meth, indent + 1)
	    end
	end

	def protolist(str, container)
	    print str
	    container.each_protocol { |p| print " #{p}" }
	    print "\n"
	end

	def dumpinterf(interf, indent = 0)
	    i = '  ' * indent
	    puts "---------\n" if indent == 0
	    protolist("#{i}#{interf.name}: protocols=", interf)
	    dumpmeths(interf, indent + 1)
	end

	def dumpproto(proto, indent = 0)
	    i = '  ' * indent
	    puts "---------\n" if indent == 0
	    protolist("#{i}#{proto.name}: protocols=", proto)
	    dumpmeths(proto, indent + 1)
	end

	def dumpstruct(struct, indent = 0)
	    i = '  ' * indent
	    puts "---------\n" if indent == 0
	    puts "#{i}#{struct.name}: attrs=#{struct.attrs.inspect}"
	    dumpfields(struct, indent + 1)
	end

	######
	public
	######

	def dump
	    puts "================ categories ==============="
	    @all_categories.sort.each { |k, v| v.sort.each { |c, categ| dumpcateg(categ) }}
	    puts "================ cftypes ==============="
	    @all_cftypes.sort.each { |k, t| puts "#{t.name} attrs=#{t.attrs.inspect}" }
	    puts "================ every cftype ==============="
	    @every_cftype.sort.each { |t, v| puts t }
	    puts "================ enum ==============="
	    @all_enums.sort.each { |name, e| puts "#{name}: \"#{e.value}\" attrs=#{e.attrs.inspect}" }
	    puts "================ funcs ==============="
	    @all_funcs.sort.each { |k, func| dumpfunc(func) }
	    puts "================ informal protocols ==============="
	    @all_informal_protocols.sort.each { |k, categ| dumpcateg(categ) }
	    puts "================ macrofunctionaliases ==============="
	    @all_func_aliases.sort.each { |n, v| puts "#{n}: #{v.original}" }
	    puts "================ macronumbers ==============="
	    @all_macronumbers.sort.each { |n, v| puts "#{n}: #{v.value} attrs=#{v.attrs.inspect}" }
	    puts "================ macronumberfunccalls ==============="
	    @all_macronumberfunccalls.sort.each { |n, v| puts "#{n}: attrs=#{v.attrs.inspect}" }
	    puts "================ macrostrings ==============="
	    @all_macrostrings.sort.each { |n, v| puts "#{n}: \"#{v.value}\" nsstring=#{v.nsstring} attrs=#{v.attrs.inspect}" }
	    puts "================ protocols ==============="
	    @all_protocols.sort.each { |k, proto| dumpproto(proto) }
	    puts "================ interfaces ==============="
	    @all_interfaces.sort.each { |k, interf| dumpinterf(interf) }
	    puts "================ structs ==============="
	    @all_structs.sort.each { |k, struct| dumpstruct(struct) }
	    @all_opaques.sort.each { |opaque, v| puts "opaque: #{opaque}" }
	    puts "================ special method_encodings ==============="
	    unless @special_method_encodings.nil?
		 @special_methods.each_index { |i| puts "#{@special_methods[i]} => #{@special_method_encodings[i]}" }
	    end
	    puts "================ special_type_encodings ==============="
	    unless @special_type_encodings.nil?
		 @special_types.each_index { |i| puts "#{@special_types[i]} => #{@special_type_encodings[i]}" }
	    end
	    puts "================ vars ==============="
	    @all_vars.sort.each do |k, v|
		puts "#{v.name}: attrs=#{v.attrs.inspect}"
		dumpfunc(v.function_pointer, 1) if v.function_pointer?
	    end
	end

	def only_parse_class(c)
	    @only_classes[c] = 1
	end
#####################################################
    end # class Parser
end # module Bridgesupportparser

redpajama_set_name: RedPajamaGithub


text:
#ifndef _ANDROID_USER_CONFIG_H
#define _ANDROID_USER_CONFIG_H

#include "android/avd/info.h"
#include <stdint.h>

/* a structure used to model the user-configuration settings
 *
 * At the moment, this is only used to store the last position
 * of the emulator window and a unique 64-bit UUID. We might
 * add more AVD-specific preferences here in the future.
 *
 * By definition, these settings should be optional and we
 * should be able to work without them, unlike the AVD
 * configuration information found in config.ini
 */
typedef struct AUserConfig   AUserConfig;

/* Create a new AUserConfig object from a given AvdInfo */
AUserConfig*   auserConfig_new( AvdInfo*  info );

/* Retrieve the unique UID for this AVD */
uint64_t       auserConfig_getUUID( AUserConfig*  uconfig );

/* Retrieve the stored window position for this AVD */
void           auserConfig_getWindowPos( AUserConfig*  uconfig, int  *pX, int  *pY );

/* Change the stored window position for this AVD */
void           auserConfig_setWindowPos( AUserConfig*  uconfig, int  x, int  y );

/* Save the user configuration back to the content directory.
 * Should be used in an atexit() handler. This will effectively
 * only save the user configuration to disk if its content
 * has changed.
 */
void           auserConfig_save( AUserConfig*  uconfig );

/* */

#endif /* _ANDROID_USER_CONFIG_H */


text:
Preliminary runway rehab at Yampa Valley Regional Airport begins later in July
Tom Ross
Steamboat Springs — The contracts have been signed with United Construction and preliminary work leading to the rehabilitation and widening of the runway at Yampa Valley Regional Airport is expected to begin in late July with the help of an additional $1.44 million in funding from the Federal Aviation Administration.
Routt County manager Tom Sullivan said Monday the work scheduled to begin later this month is off-runway and will involve excavation of a new vehicle service road. It will begin at the terminal and run all of the way around the east end of the 10,000-foot runway to the Aircraft Rescue and Fire Fighting Building.
It's an improvement to the airport in Hayden, 22 miles west of Steamboat Springs, that was sought by the FAA. The road will eliminate the need for service vehicles to cross the runway in order to reach service buildings on the south side of the runway, Sullivan said.
The major runway work involves tearing up the old asphalt and widening the runway itself by 50 feet but won't begin until the spring of 2015.
Yampa Valley Regional Airport serves both Moffat and Routt counties and is busiest from December into early April when direct jet flights from cities like Seattle, San Francisco, Los Angeles, Dallas, Houston, Atlanta, Washington D.C., Newark, Chicago and Minneapolis land there.
The work of reconstructing the runway was delayed from this summer and fall until April to May 2015 because the FAA was unable to finalize grant funding documents and contracts until June of this year instead of February as anticipated.
The result is that the runway will be closed to commercial and general aviation for about 60 days next spring during major construction.
Airport manager Dave Ruppel met with FAA officials in Denver three times late in 2013 to persuade them to allow his airport to spread the runway project over two calendar years, something the FAA is generally opposed to, Sullivan said in November 2013.
The need for additional federal funding arose in April of this year when the low bid from United of $17.58 million came in 30 percent over the engineering estimate of $13.44 million.
Routt County and the FAA partially closed the gap by significantly scaling back the $3 million vehicle service road, which now, is not scheduled to be paved.
"We're going to be excavating that road this summer and filling it with asphalt millings," taken from the runway next spring, Sullivan said. "It's not going to be paved."
The county will be required to pay a 10 percent match on the FAA grant that will cover the large majority of the runway work. Another grant of about $2 million from the Colorado Department of Transportation's aeronautical division in support of the project will require a 5 percent county match.
To reach Tom Ross, call 970-871-4205, email tross@SteamboatToday.com or follow him on Twitter @ThomasSRoss1
Group Homes Staff at Horizons in CRAIG
Join our Team! Do you want to make a difference in the lives of individuals with IDD? Horizons is hiring…
Engineer I, II, III or Senior (IRC34425) at Tri-State in CRAIG
Engineer I, II, III or Senior (IRC34425) Craig Station has an opening for an Engineer I, II, III or Senior…
The Porches
Shuttle Driver Needed at The Porches in STEAMBOAT SPRINGS
Looking for a weekend job? A few days and nights available. Drive our safe reliable shuttles and enjoy sharing Steamboat…
Casey's Pond
House Manager, RN/LPN, CNA, Care Partner, Housekeeper, Culinary at Casey's Pond in STEAMBOAT SPRINGS
Come be part of our thriving community! House Manager RN/LPN CNA Care Partner Housekeeper Culinary HR@caseyspond.org caseyspond.org/careers EOE
Steamboat Pilot & Today
Carrier at Steamboat Pilot & Today in STEAMBOAT SPRINGS
I'LL PAY YOU $360 FOR YOUR TIME AND GAS The Steamboat Pilot & Today is seeking a responsible individual(s) to…
Shift Nurse Positions at The Foundry in STEAMBOAT SPRINGS
Shift Nurse Position Available Entry level nursing position. FT, PT, PRN RN licensure Required Extensive benefits & opportunities for advancement…
Pacific Spas & Pools
Water Care Specialist at Pacific Spas & Pools in STEAMBOAT SPRINGS
Pacific Spas & Pools looking for a self motivated water care specialist. Exp a plus, not required. Pay based on…

redpajama_set_name: RedPajamaCommonCrawl


How long does Vitamin D3 supplement take to show effect?
5 days are very early to notice any improvement in your symptoms.Vitamins and supplement need time to show their effect.The level of Vit D in your blood will increase gradually withe the intake of Vit D supplement and your symptoms will start to improve.
This may take few weeks up to few months.You need to be patient.
Vitamin D deficiency can cause symptoms like bone pain,muscle weakness,fatigue ,loss of appetite, weight loss etc.
So your chest pain might be a symptoms of Vit D deficiency due to muscle and bone pain.Vit D deficiency can cause dry mouth and this can make swallowing difficult.
It would be good to discuss these symptoms with your treating doctor for proper evaluation.A detailed medical history and physical examination are necessary to exclude other causes for your symptoms.
Can i have panadol to relife my pain ll it be k if i take with vitamin d supplement?
Yes,you can use Panadol to ease the pain.Panadol contains paracetamol.It doesn't interact with Vitamin D supplement .


Resveratrol no longer famed source of health benefits in wine?
There's nothing like sipping a nice glass of wine or a indulging in a decadent piece of dark chocolate, and enjoying it much more knowing you are drinking and eating to your health. But what is it that makes these substances so healthy for us?
The bacteria that populate the human gastrointestinal tract help digest dark chocolate, releasing anti-inflammatory compounds, according to a new study.
A new study shows that enjoying dark chocolate leads to a reduction in abdominal size. Participants ate about 500 calories worth of dark chocolate per day.
Is there a way to become more calm and contented? A research study conducted by a Swinburne University team has revealed that the answer to this question is dark chocolate. Eating more dark chocolate can make you calmer and more contented.
People who love dark chocolate will be pleased to hear that it helps lower the risk of heart disease and high cholesterol. According to new research, eating dark chocolate each day will help keep the doctor away.
Regular chocolate consumption can help keep a person slim according to new research. The study found that those who consumed chocolate regularly had a lower body mass index than those who did not eat chocolate.


he chirping of the birds welcome you in the morning. After a leisurely breakfast, the cruise begins its journey at 10:00 AM towards Thakazhi through Mancompu. The houseboat halts at Pullincunnu dock where the guests get down sightseeing. Some of the attractions include Pullincunnu church, Kottaram temple, and St. Mary's Church. Next, visit the local statue carving unit and observe the artisans busy in their work. Explore and shop at the local market of Champakulam. You also see Champakulam chundan Vallam- a boat that has been the winner of various snake boat races. Pullangadi and Pindithodu are charmers too. The day's journey comes to an end at Thakazhi where it is anchored.


Batik is an art and craft which is inherited from ancient Java tradition in Indonesia. In Javanesse tik means dots. Batik is made by drawing lines, dots, or arch of the resist with a tool called a canting ( a pen-like tool use to apply liquid hot wax).
To create Batik, First the wax need to be applied over the pencilled-in outline of pattern, the part covered in wax resist the dye and remain the original colour. Next step the cloth is dyed in the first dye bath, then the second wax is applied. The next process, the cloth is dyed in the second dye bath. The last process, the cloth would be boiled in order to remove the wax.
There are several Batik patterns that have been used since the beginning of Batik creation. Each pattern has the meaning and some of them show the status symbol of the wearer. For example Sida Mukti pattern, Sida means to become or to have done which express the hope to achieve spiritual happyness. Sekar Jagad means a beauty and grace that impresses people, or Truntum that was created by a queen in Java in seventeen century. Truntum means everlasting love that continues grow. There are at least twenty known base patterns with various meaning.
Several designers have developed Batik in a contemporary style. The contemporary Batik Indonesia patterns use animal, myth, flower or combined with a classic style. Young people like to wear contemporary Batik. Because of its unique pattern, Batik is now printed not just on traditional cotton or silk but also in leather or in hard material such as ceramic and wood.
There are numbers of public figure that have publically worn Batik such as : Nelson Mandela, Bill Clinton, Bill Gates, Carlos Santana, Julia Robert, Reese Whitterspoon, Heidy Klum. Oscar de la Renta used batik as the base of one of his design that was worn by Jesica Alba.


text:
community_resource_list_fall_2021.docx
Resilience Building : "Help Now" Activities
50 Ways to Take a Break
6 Ways to Practice Grounding
Department of Prevention & Intervention (DPI) Resources
DPI Home Page
Social emotional wellness & Support
Trauma-informed practices to support students who are experiencing or have experienced childhood trauma are more urgent than ever. Here are five essential trauma-informed practices: 1.) Set up a welcoming virtual classroom. 2.) Practice self-care and work from your strengths. 3.) It's all about relationships. 4.) Use consistent routines coupled with positive interactions.
department of prevention & Intervention VOL. II It's important to keep in mind that while we're all in this together, each person has unique life circumstances that may cause more or less acute concern. Leading with compassion and empathy is more critical than ever.
department of prevention & Intervention VOL. III May is Mental Health Awareness Month, and it has never been more important than this year. Until now, there were still some people who believed that mental health wasn't everyone's concern.
department of prevention & Intervention VOL. IV Think about a time you felt nervous or worried. What did you do to make yourself feel better? The rapid changes to day-to-day life can lead to fear and anxiety for students, families and educators.
Supporting the SEL needs of students and families is perhaps one of the most urgent concerns facing school systems right now. The reality is that while schools are closed, students may be experiencing abuse, neglect, community violence, and a host of other stressors.
department of prevention & Intervention VOL. VI The following is a list of ideas that teachers can utilize to provide closure for students at the end of the school year. It includes ideas for activities, links and circle prompt questions by grade level bands. Please download the document below.
department of prevention & Intervention VOL. VII What is your favorite genre of music? What is the best thing that happened to you this year? If you can go anywhere at this moment, where would it be? For many parents, talking to their children about the nationwide protests following the death of George Floyd may seem daunting.


2.能够听懂一些指令,把物品放到相应的位置上,如:Put your Chinese book in your desk.
T: It is too heavy.(做出拿书包时,很沉重的样子) How about Zoom?Now let's sing and answer : Is Zoom's schoolbag heavy?
Question: Is Zoom's schoolbag heavy?
T: My schoolbag is heavy. Zoom's schoolbag heavy,too.
T: Boys and girls.What's in my schoolbag? Guess.
T: Let's see. (打开书包,拿出一个铅笔盒) What's this?
S: It's a pencil case.
T: What's in my pencil case?
T: (顺手从书包里拿出一本英语书) Boys and girls. Look!
S: English book. An English book!
S: Chinese book \a Chinese book!
T: Boys and girls. What's in my schoolbag ?Let's count.
T & S: An English book, a Chinese book,two maths book and five story books.
T: What's in your schoolbag ?
Put your Chinese book in your desk.
Put your pencil box on your English book.
Put your maths book under your schoolbag.
Put your eraser near your pencile box.
T: Play the tape recorder.
11 、Listen to the tape carefully, point the words and repeat.
1、listen to the tape and repeat after it for 15 minutes.
3、用Put your ______on your _________的形式与同学说一说,玩一玩.
What's in your schoolbag ?


Curb appeal! Beautiful 3 bedroom/2 bath all brick home on corner lot in Morris Brandon school district. Great floorplan with updates throughout the home. Finished lower level with built-in bar area, bonus room and play area. Large Master bedroom with sitting area. Fenced in professionally landscaped yard. Fresh paint and beautiful hardwood floors make this home shine.


text:
module KeteTrackableItems
end


text:
Better versions of your favourite games
Article / By Matt
It never ceases to amaze me that Monopoly is always one of the best selling board games and board game apps. It is a game with no decision making and one where you are at the whims of the dice for 2-4 hours at a time. But it's ok, I don't blame you if you love it, you just might not know that there are better options out there. Over the last 20 years board games have come a long way and thankfully the last 5 years have seen digital ports of these great new games hitting our devices in swathes. So if you're sitting there enjoying a game of Monopoly on your phone I'm here to tell you about the better versions of your favourite games available to download right now.
If you're a fan of Monopoly
Lets start with the big one. In theory Monopoly is an economic set collection and trading game and while this is true it is a dull and broken game. The problem with Monopoly is that the only question it ever asks you is "do you have enough money in your hand to be able to buy the street you just landed on?" It's not a decision you have to make, it is simply a yes or no question and a matter of book keeping; play Monopoly enough times and it becomes clear that you have to buy everything you can as soon as you can. It's this lack of decision making and reliance on the random roll of a dice that makes it a dull and infuriating game to play.
So if you're looking for a board game app to replace your beloved Monopoly then look no further than Catan, the digital version of the classic gateway game Settlers of Catan. Catan borrows from some of the mechanisms you're familiar with from Monopoly such as set collection, trading and upgrading cities to increase your production not to mention it is all determined by dice rolling; however it achieves this in a way that has you making impactful decisions at nearly every turn. You've collected a set that lets you buy a development card but doing so will mean you can't afford to build a new settlement, building that new settlement means you can't extend your road and get the victory points for the longest road. It's an exercise in understanding the opportunity cost of your decisions all wrapped up in a game which is barely more difficult to understand than Monopoly.
As a next step, Catan is a simple transition from Monopoly and the apps available for it do a great job of walking you through everything. I guarantee that once you have played a Catan app you will be uninstalling Monopoly and preaching to the world about this new world of board gaming you have taken your first tentative steps into.
READ CATAN CLASSIC REVIEW
If you're a fan of Cluedo
Unlike Monopoly, Cluedo isn't an intrinsically broken game. I enjoy the logic based deduction as you work your way methodically through rooms, murder weapons and suspects and although it's a game that rewards good book keeping along with an element of luck it's still a fun board game. However if you're looking to take that flavour in a more interesting direction than you should take a look at Mysterium where you are psychic detectives trying to uncover the murderer, room and weapon, sound familiar.
What makes Mysterium an interesting evolution from Cluedo is that it moves from the realm of a logic puzzle to a game of feelings and opinion. Rather than asking yes or no questions and getting a definitive answer clues in Mysterium are provided by one player who is a ghost. The clues come in the form of vague and unrelated pictures which the ghost player will choose the convey a feeling about either the suspect, room or weapon; does the picture of a blue city walls surrounding a distant mountain refer to blue back ground of the rope murder weapon or does that triangular gap in the mountains refer to the widows peak on one of the suspects. What the ghost might see in one of these picture cards might be something completely different to what you see in it and this is where the game is at it's best.
If you like deduction games and are looking for a new interesting take on it then Mysterium is the next step for all you Cluedo lovers out there. I would be remiss if I didn't issue you with a word of warning with the Mysterium board game app however; this is a game that works wonderfully as a multiplayer experience against humans, trying to predict what another human is seeing in the vague cards is where the joy of this game lies. When playing the app against an AI you lose that a bit as it just isn't as enjoyable trying to predict what a computer is trying to get across. The app version of Mysterium is a great way to learn the game but doesn't work as well as a solo game against the computer. Despite this it's a great next step for anyone who loves playing Cluedo against their friends and wants a modern spin on this classic game.
READ MYSTERIUM REVIEW
If you're a fan of Chess
Far be it from me to slate the game of Chess, any game that can find it's origins in the 9th century and still be being played today deserves a bit of respect. I've played Chess since I was 7 years old and have enjoyed countless bouts, mainly against my Grandpa but more recently against all of my friends thanks to the hundreds of chess apps out there. So with all that said, why am I trying to find a better version of a Chess app for you to play and how can you improve on centuries of gameplay perfection?
Well the one thing I will say about Chess, even on an app, is that it can really go on a long time. The back and fourth and complex decision making can stretch a game out anywhere from 30 minutes to 2 hours depending on who's playing and how proficient they are. I simply rarely have that kind of time to sit on my phone playing a game and if I do I want to play something else. That's where the board game app Santorini comes in; Chess like decision making finished in about 10 minutes. The base game offers a true head to head competition of movement and building but the addition of the option God cards which provide a game modifier for each player provide an unique level of tactics to each game. Thanks to the limited number of moves a player can make on each turn thanks to there only being 2 pieces per player on the board means you never have the analysis paralysis you often see with the slew of options in Chess.
If you're looking for a game of Chess for people who don't like Chess then you can't go far wrong than downloading Santorini and challenging your friend to a quick bout.
READ SANTORINI REVIEW
If you're a fan of Risk
I'm going to cheat here, but it's for your own benefit. When I came to put together this list of board game apps and started thinking about better versions the choice for Risk was an obvious one for me. Twilight Struggle takes the dudes on a world map mechanic and ramps it up to the max by adding in a tonne of new mechanics, loads more win conditions and a plethora of added complexity. It's this ramping up of difficulty that has lead me to offer two options for better versions of the game of Risk rather than just one.
Twilight Struggle has two of you competing as opposing sides of the Cold War, spreading your influence along the regions of the globe, playing events which benefit you or even your opponent as well as juggling both the space race and the DEFCON tracker, trying to be the first to put a man on the moon, avoiding causing a nuclear disaster while also playing a tug of war of influence. It is like Risk on steroids and I wholeheartedly recommend it as a better version of Risk. The trouble is, it's definitely not a game for beginners or even intermediate players. It requires you to understand multiple mechanisms you may not be used to in a board game and most importantly be able to juggle multiple ways to win which is something that most players haven't had experience of. Therefore I decided to add a second option of game for fans of Risk and that is the board game app Eight Minute Empire.
Eight Minute Empire is an area control game similar to Risk in which you are recruiting and moving your soldiers around a map trying to be the player with the most countries and continents under your control. It is a simple and quick game to play but has enough strategy to keep fans of Risk entertained despite it's significantly quicker play time. Eight Minute Empire doesn't rely on dice based combat in the same way Risk does and so the frustration of luck of the dice is removed and you are left to battle it out on strategy alone.
Both Twilight Struggle and Eight Minute Empire make great additions to your digital board game collection and if you don't feel ready for the step up to Twilight Struggle you can still enjoy Eight Minute Empire and get a better version of Risk on the go.
READ TWILIGHT STRUGGLE REVIEW
READ EIGHT MINUTE EMPIRE REVIEW
If you're a fan of Dominoes
Don't get me wrong, Dominoes isn't a bad game; it's fun to find creative ways to make multiples of 5 and wrack up big scores and it is a refined and sleek game. With all that being said there is a card game I prefer and that is 6 Nimmt (called 6 Takes if you're looking for the app version).
6 Nimmt is another numbers game where players simultaneous choose a card and play it onto one of 5 rows of cards in numerical order. If you are forced to play the 6th card in a row then you have to pick up all of the cards in that row which adds to your score at the end of the round. The player with the lowest score when one loser hits an agreed losing number wins the game. It's elegantly simple in the same way Dominoes is however the addition of simultaneous play adds a much needed feel of poker to the proceedings. Trying to anticipate cards your opponents will play and attempt to force hem to take the 6th card in a row is exciting and adds a layer of risk with each card you play. It's the feel of dominoes with the added risk of simultaneous play which means it's a game I pick up far more often than I ever would pick up Dominoes, and if that's not a sign of a game being better I don't know what is.
READ 6 TAKES REVIEW
If you're a fan of Battleships
Similar to Monopoly, Battleships is a flawed game due to the fact it is a game that is devoid of any real decision making once your initial set up has been decided. From turn one it's a case of running down the clock hoping that you're the first one to accidentally hit on some boats before your opponent; the decision making has gone and the game loses all enjoyment.
Step forward King and Assassins a board game of hidden identity and underhand tactics for two players beautifully ported to a board game app. One player plays as the king, moving around the board with his guards attempting to get safely around the grid into his castle. The second player controls 3 assassins as well as the remaining towns people, the twist is that the assassins look like towns people and as such the King is unaware of who is coming to kill him. It's a fantastic to and fro of bluffs and double bluffs as the Assassin player throws wave after wave of towns people towards the King in the hope that he can slip an Assassin passed the guards undetected.
If you're looking for a two player game of guessing and bluffing across a grid then you should forego your Battleships and download King and Assassins to enjoy a far better game of hidden tactics rather than aimless guessing.
If you're a fan of Connect 4
I used to compete in Connect 4 tournaments as a child and so it will always hold a special place in my heart as a fun game. However once you have figured out a couple of basic moves the game follows very similar patterns every time you play. So much so that I used to win a lot thanks to the fact the other kids my age hadn't sussed these moves out yet.
When I found the app version of Quarto I was delighted that I'd found a short game with far more decision making that I ever found in a game of Connect 4 but with a very similar feel. Quarto consists of a 4 x 4 board and 16 pieces each of which are either short, tall, light, dark, square, round, hollow or solid. Players take it in turns to select one of the pieces which the opponent must then place on the board. This continues until a player creates a line of 4 pieces which all share one of the attributes.
The rules are easy to pick up but the tactics involved can be mind bending at times. Games run along at a pace but give you plenty to think about. It really feels like a game of Chess meets Connect 4.
If you're a fan of Yahtzee
Who doesn't love a roll and write game, I know I do. Yahtzee was my first introduction to this genre as I'm sure it is for a lot of people however it has moved on a lot since and some games now do this mechanism much better, one of which is Ganz Schon Clever.
Ganz Schon Clever has you rolling dice and selecting which you will be using to tick off boxes on your board. The more boxes you tick off the better your score will be. Each colour of dice has a different method of scoring as well as varying rewards for you depending on how many boxes you tick off. It's basically the same as Yahtzee but with rewards that let you collect more dice throughout the game.
The app version of Ganz Schon Clever has been an ever present on my phone as I'm addicted to trying to best my previous scores and I am always left with the feeling that I could have done better. This is a feeling I just don't get with Yahtzee where often on a turn there is only ever one good option; compare this to Ganz Schon Clever where each turn there are multiple good options and so you are sacrificing one thing for another. This is the key to why it is a better game than Yahtzee and why I'd recommend upgrading your Yahtzee app to Ganz Schon Clever.
READ GANZ SCHON CLEVER REVIEW
So there you have it, a list of better versions of your favourite games. This is in no way a slight on these much loved games, they have a special place in all of our hearts and childhoods however now's a great chance to find some new games to enjoy and hopefully they can find a way into your hearts going forward.


Zendaya Coleman stopped by InStyle's offices yesterday to chat about her upcoming gig hosting the Radio Disney Music Awards on Saturday, April 25, but our conversation with the 18-year-old singer, actress, and red carpet force quickly turned to one of her favorite topics: fashion. And much to our delight, the shoe-obsessed star exclusively revealed some major news: She's designing her first-ever line of footwear with her stylist, Law Roach, set to launch just in time for back-to-school season this year.
Virgin wool has two definitions. First, it is the wool taken from a lamb's first shearing. This is the softest and finest wool produced. Second, virgin wool can refer to wool that has never been used, processed, or woven before. This type of virgin wool can come from an adult sheep.
365 days. 365 outfits. 365 dollars.
Young American designer, inspired by the movie "Julie & Julia" in which a woman tries on a new dish every day, decided to launch her own fashion project. Its initial period is one year during which the designer Marissa Lynch will stop doing traditional clothing shopping and will wear only made by her clothes.


Shooting on the go news can be tricky. To get that money shot you need a camera with an interchangeable lens. Having a variety of lenses prepares you for any type of scenario.
The ability to zoom in or out is essential to capturing details both small and large.
A great lens to have is a 70mm-300mm. This size is perfect for capturing wide and tight shots from a distance. Don't forget to use a tripod or stabilization, it is necessary to reduce shake.
Another key lens is the 17mm- 24mm. This wide lens allows you to get super close to subjects and also capture them entirely. You can zoom in while the shot still remains fairly wide. A wider lens also lets you shoot footage in areas with less light.
A great feature to look for when buying lenses is Image stabilization. The IS dramatically reduces shake when shooting handheld. It all depends on what you are shooting. The IS is optional.
Shooting with a smartphone? There are several options to choose from.
The most versatile lenses are lens attachment clips by Gizmon and Olloclip. These systems have a variety of clips that offer different lenses like, a 180 degree fish-eye, 10x magnification and a wide lens, which doubles as a phones focal length.
Another great option is The mophie outride. It offers a wide lens and has a built-in case, which provides extra support and comfort.
Choosing a great lens is all about personal preference. No matter what camera you shoot with, just remember to capture a variety of quality shots.


Of the more recent architectural styles, one has developed into what can be considered the current vernacular, and that is red brick with sandstone quoins. Some of the earliest examples are to be found in Weaver's Cottages and the Wesley Chapel (1775). Edward Bradby felt that the cottages probably pre-dated the chapel. Today, despite some minor concrete and glass excursions between 1960 and 1970, we seem to feel more comfortable with housing development that resembles that red brick and sandstone quoin style of the late 1700s. We can see the predominant style, and pseudo representations of it, in some our newer developments from 1950 onward.


The Superintendent is the chief executive officer for the school district with the authority to manage, supervise, and evaluate all affairs of the system within the policies established by the Board of Education.
The Superintendent administers the development and maintenance of an educational program designed to meet the needs of the community and carries out policies of the Board. Additionally, she assists the Board in developing long-range plans, formulates school objectives, policies, plans, and programs, conducts periodic audits of the total school program, and advises the Board on recommendations for the educational advancement of the schools. Additionally the Superintendent administers the HR and communication functions.
The Director of Business is provides the necessary financial, accounting, and record keeping services to facilitate the best possible educational program. He also is the District Treasurer.
The Director of Special Education oversees district special needs programs and services and works with the Superintendent to assure quality programs for students. She oversees social workers, psychologists, and nurses and develops and monitors the IDEA grant.


Compile ahead of time. It's fine?
Static (ahead-of-time) compilation of code appeared in Oracle JDK 9. We have already discussed why this is necessary, and the scope of the current implementation. Now it makes sense to talk about the technical details. What information is generated by the AOT and how it is generated, how compiled AOT code interacts with Hotspot? What you can do with AOT-code by external tools, and how to infiltrate into the compilation process? And of course, what grips to twist, and what will be the performance with AOT?
Java SE performance engineer at Oracle for last 4 years. Previous years of experience with Java demonstrated that performance issues hinder applications of any scale.


Story; The Story is good enough. Sixty years ago, our moon was destroyed by an Alien Force. We won the war, but Earth is just about unlivable.
Visuals; This is a Beautiful Movie. Good Directing, Great Cinematography. Great Production Design.
Jack (Tom Cruise); Cruise is s Good Actor… He does a good job.
Julia (Olga Kurylenko); This actress also did a good job.
Victoria (Andrea Riseborough); This actress is also good.
Additional Characters; Morgan Freeman is in it, but it's not much of a Character/Role. Also Nikoloj Coster-Waldau from "Game Of Thrones" (Jamie). His character in "Game Of Thrones" is brilliant, but his character in this film is almost nothing.
The Drones; The Drones are actually the most interesting characters beyond Cruise, and the Two Girls… They are a very cool part of this film.
Overall Rating; Reading this Review, it may not be obvious, but this is a very good film. Like I say, the Visuals are Stunning, and the Story is Good Enough to keep your interest. Reflecting upon it, I'd say the Production Value and overall feeling, and look of the film, as well as the music, really make it a cool experience to watch.
"What can she do…" He mustard out, as he turned back to Rud and Nef dishing out orders. Jono spoke before Jenna could reply. "She's a Refugee from Ona Sir… Jenna brought her aboard." Jenna looked at her brother Jono like she had just been turned into her Mother for steeling marbles from the Boys at School. She then turned her attention back to Captain Fire. "She's Honest… Sir." This seemed to grab the Captain's attention once more. "Honest eh… How refreshing… Have her assist the Cook, we will be needing sustenance soon". With this Captain Fire left the Bridge to inspect the rest of the ship, for they would be traveling for quite some time before making space port again.
"This is Rud and Nef…" Jenna gestured to them.
Dancer pulled her suit over her shoulders. This was the first time she had worn it since being rescued from the storm, and she could feel her whole body tensing as the tight rubbery fabric stretched around her. It felt unnatural. It was almost like she had never worn a spacesuit before and her body was having to adjust to the sensation of having something cling to every crevice and bulge of her body. She ran a hand along her thigh, flattening down an invisible crease, and forced herself to take a few deep breaths.


Peckham is a district in south London. It lies within the London Borough of Southwark and is close to New Cross and Camberwell.
Our independent price comparison engine can compare van hire prices in London Peckham to help you find the cheapest van rental deal out there.
The south London district of Peckham was once a rural village by the River Peck. As London expanded and more housing was built for workers in the London docks during the 19th century, Peckham gradually became an integral part of London.
Peckham has undergone substantial regeneration and investment in the last 20 years - as well as much new housing, the Peckham Library and South London Gallery have been built to help encourage public arts in the area.


We provide event budgets, flexible planning and marketing strategies. Specialist services include the provision of taxation advice for industry performers and event contractors.
At the heart of a successful event is a fluid budget that can highlight opportunities for revenue growth and pinpoint areas in which costs must be kept under control. By employing professionals who understand how events work Events Central can help others budget for their events and even help with grant sourcing and applications.
We also assist professionals who have earned significant income through their natural talents and work with those individuals to provide taxation advice and retain as much of their hard earned income as possible. Many actors or singers make relatively large sums of money when they embark on a professional career and it is important to work with good quality advisers who will work in the interests of the individual.
We build sustainable relationships with our clients so that we are the "go to" people whenever a financial issue arises. The provision of flexible budgets provides organizers with the data they need to make crucial decisions about their event.
Contact us today to arrange a no obligation discussion to see how we can assist you to spend more of your time performing or organizing without compromising your income.


Confirming her ownership of the foodie profile (@onionringsworldwide) on 'The Tonight Show Starring Jimmy Fallon' on Thursday (15.06.2017), she said: "I naively didn't realise that it would be a thing that I was going to different places and trying the onion rings at each of those places. I think they're underrated as well. I don't think they get enough credit."
The 20-year-old singer - real name Ella Yelich-O'Connor - spilled that the now-deleted profile which consisted of four pictures of onion rings with reviews was made as she believes the deep-fried vegetable snack doesn't "get enough credit".
The 'Green Light' hitmaker left a trail of evidence that the account belonged to her earlier this week when her and her team were among the 24 people following the account.
The bio on the account read "Every onion ring I encounter. Rated" followed by four pictures of the greasy snack, each with a review and a rating out of five.
One of the captions on a picture read: "Bit of a heavy, dry mouth feel. 2/5."
Lorde also gave a big thumbs down to fast food chain Burger King's own onion rings, which were a taste disappointment for her.
She wrote: "I didn't actually know Burger King did onion rings, and good thing I didn't because they are not good. 1/5."


Dairy firm Dairy Crest has said that it expects its profit for the half year 'to be slightly ahead of the same period last year', when it announces its interim results on 7 November.
The group has issued a pre-close trading statement for the half year to 30 September, in which it said that it expects group revenue to be up on the same period last year, driven largely by its two main brands, Cathedral City and Clover.
It said that Cathedral City is 'going from strength to strength', and is expected to 'deliver good growth against strong volumes a year ago'.
Clover is set to deliver both volume and revenue growth, meanwhile, continuing the 'positive performance' the brand recorded last year.
Its Frylight brand, however, is expected to show a decrease in volume, as a result of the hot summer.
The company said that it remains focused on innovation, and is aiming to deliver 10% of its revenues from products developed within the past three years.
In the 2017/18 financial year, some 14% of revenues came from recent innovations.
"Our Cathedral City and Clover brands continue to drive the business forward, supported by an exciting pipeline of new product developments," commented Mark Allen, the company's chief executive.
Allen added that the company's balance sheet is "in good shape and we are moving forward with the first phase of the expansion at Davidstow.


Anton Tonkoy & Olga Zakirova are extremely co-operative, flexible and hardworking.
I would surely like to recommend Anton Tonkoy & Olga Zakirova to Employers and wish them a very bright future and full success in all their endeavors.
We are happy to inform Anton Tonkoy & Olga Zakirova got Contract for Cruise Ship "Norwegian Jewel" as a leading Dance couple for the entertainment team. They started their exiting trip from Miami, Florida, USA on JAN 2006.
From 9 March 2006 Anton Tonkoy & Olichka Zakirova start work for Cruise Ship "Norwegian Dawn" as a leading Latin Dance couple for the entertainment team.
Congratulations. Anton & Olga been chosen to be a Featured Ballroom Dancer for Royal Caribbean International.
Congratulations. Anton & Olga been chosen to be a part of AZAMARA cast as Featured Dance Act/Activity Staff.


If you have been looking for a place to go on an adventurous vacation, Belize might just be the destination of your dreams. Aside from the warm weather, a welcoming atmosphere, and stunning natural beauty, this Central American nation is also full of exciting things to do.
Whether you are visiting Belize on a honeymoon, family vacation, with your partner, or on your own, you simply cannot miss out on the Black Hole Drop. This 300-foot sinkhole, nicknamed the "Mother of all Caves," provides excitement and stunning views in equal measure. When you visit, you will be able to rappel down the hole into the lush canopy of trees that lines the bottom. Once you reach the bottom, you will be able to take in the sights and grab a bite to eat before starting the climb back out of the sinkhole.
If you prefer your adventures to be water-based, you and your group can go cave tubing. You will hop into an inner tube and make your way down the beautiful rivers and creeks of Belize, passing through some ancient caves along the way. Your cave tubing adventure will bring you past pristine underground waterfalls, a crystal cathedral, and an ancient Maya spiritual center.
Of course, if you and your party would like to see some wildlife on your Belizean adventure, you can take a trip into the jungle. More specifically, you can go to Caves Branch Jungle Lodge. Here, you will be able to grab your binoculars and see how many of the more than 300 bird species that live in the area that you can spot.
While you are at Caves Branch, you can also take a tour of the beautiful on-site botanical gardens. Featuring tons of native Belizean flora and fauna, these gardens are the perfect spot to smell the lemongrass and see the cacao.
During your vacation in Belize, you will no doubt need somewhere to stay. While you could choose to stay in a traditional hotel, more adventurous travelers prefer to stay in one of the luxurious tree houses at Caves Branch Jungle Lodge. Each tree house features electric lights and fans, hot and cold water, bug screens, beautiful art, electrical outlets, and carpentry made from the finest local materials. To learn more about the tree houses or to make a booking, you can visit www.BelizeTreeHouses.com.


text:
Tony Martin,
Total quality VP,
Tony Martin, Total Quality VP at Boeing Defense, Space & Security
https://potomacofficersclub.com/wp-content/uploads/2021/12/tony-martin-total-quality.mp3
Tony Martin is the vice president of total quality for Boeing Defense, Space & Security. He has been holding his current leadership position for over two years.
Martin oversees a team that is responsible for improving quality performance across BDS and ensuring that products meet quality, reliability and safety standards. He also works across the company to guide the implementation of quality and compliance improvements. He was the senior director of operations for the 787 Dreamliner program before taking on his current leadership role. In that position, he oversaw the structural build, integration, functional test and delivery for the aircraft's mid-body, according to his LinkedIn profile.
He has over 35 years of experience in the aviation industry, all of which are with Boeing. The industry veteran started his professional career in 1986 as an industrial engineer and senior manager for the aerospace company. He was promoted to director of operations for the H-47 Chinook helicopter program in July 2008, a position in which he oversaw a $130 million factory renovation. Other leadership roles that Martin held include director of Charleston Machining and Emergent Operations for the 787 program and director of operations for V-22 Osprey assembly and composites.
The Boeing VP holds a master's degree from Villanova University and a bachelor's degree from Wichita State University.
Tags: Boeing Boeing Defense Space & Security Executive Profiles LinkedIn quality assurance Tony Martin Villanova University Wichita State University
Sheri Murphy, Vice President of Quality Assurance and Continuous Improvement at American Systems
Five Quality Assurance Executives to Watch in GovCon
Tina Cao, Director of Finance and Business Operations at Leidos
Philip Knoll, Finance Director at Deltek
Michael Hardesty, Chief Accounting Officer at Northrop Grumman


Boseda Olawoye is a Nottingham (UK) based Freelance Engagement Curator and Creative Engagement Manager for Threshold Studios. Bo has developed and managed creative learning programmes within galleries, on the street and inner city areas since 2001. Her approach to engagement always has a strong focus on "creative collaboration" empowering people through art to explore social justice and political issues that affect everyone.
She has previously worked for The Bonington Gallery at Nottingham Trent University, Nottingham Contemporary, Tate Modern London, Backlit Gallery/Artist Studios and New Art Exchange.
As a freelancer she has developed community projects, discussed her practice, and chaired discussions at institutions and public spaces across the UK. These include Goldsmiths & Birkbeck University of London, The University of Wolverhampton, Nottingham University, Mark Devereux Projects Manchester and idle women Lancashire.