class Object

Public Instance Methods

aargh(message, exit_code = nil) click to toggle source
# File bin/specificjson, line 2114
def aargh(message, exit_code = nil)
  $stderr.puts message
  exit exit_code unless exit_code.nil?
end
all_requirements(piece, reqs) click to toggle source
# File bin/specificjson, line 2334
def all_requirements(piece, reqs)
  unless reqs.include? piece['name']
    reqs.push piece['name']
    piece['requires'].each do |r|
      all_requirements($PIECES[r], reqs) unless reqs.include? r
    end
  end
  reqs
end
arrange_needed(needed) click to toggle source
# File bin/specificjson, line 2456
def arrange_needed(needed)
  pools = needed.select { |name| $pools.include? name }
  others = needed.reject { |name| pools.include?(name) }
  others.sort! { |a, b| compare_pieces(a, b) }
  last = others.rindex { |name| $pooled.include? name }
  needed = others.slice!(0, last + 1)
  others.concat pools
  others.sort! { |a, b| compare_pieces(a, b) }
  needed.concat others
  needed
end
check_given(spec, kind, field, error) click to toggle source
# File bin/specificjson, line 2159
def check_given(spec, kind, field, error)
  aargh(error, 4) unless spec[field] != $DEFAULT[kind][field]
end
classify_expression(expr) click to toggle source
# File bin/specificjson, line 2647
def classify_expression(expr)
  # Simple but good enough for now. If expression gets confused with method,
  # add space in any place where it does not affect the meaning.
  return :expression if expr.nil? # Will go unused in this case.
  return :expression if expr.include? ' '
  return :expression if expr.include?('.') || expr.include?('->')
  return :method if expr.end_with? '()'
  :member
end
compare_pieces(a, b) click to toggle source
# File bin/specificjson, line 2413
def compare_pieces(a, b)
  a = $PIECES[a]
  b = $PIECES[b]
  # Group writers at the end.
  if a['writer']
    return 1 unless b['writer']
  else
    return -1 if b['writer']
  end
  areqs = a['all_requires']
  breqs = b['all_requires']
  if areqs.include? b['name']
    return areqs.length <=> breqs.length if breqs.include? a['name']
    return 1
  end
  return -1 if breqs.include? a['name']
  if a['writer'] && b['writer']
    if a['scalar']
      return -1 unless b['scalar']
    else
      return 1 if b['scalar']
    end
  end
  # Neither requires the other. Keep pools and pooled items before others.
  if $pooledreqs.include? a['name']
    return -1 unless $pooledreqs.include? b['name']
  else
    return 1 if $pooledreqs.include? b['name']
  end
  if $pooled.include? a['name']
    return -1 unless $pooled.include? b['name']
  else
    return 1 if $pooled.include? b['name']
  end
  if $pools.include? a['name']
    return -1 unless $pools.include? b['name']
  else
    return 1 if $pools.include? b['name']
  end
  return areqs.length <=> breqs.length unless areqs.length == breqs.length
  a['name'] <=> b['name']
end
default(spec, field, value) click to toggle source
# File bin/specificjson, line 2155
def default(spec, field, value)
  spec[field] = value unless spec.key? field
end
defaults(kind, spec) click to toggle source
# File bin/specificjson, line 2143
def defaults(kind, spec)
  $DEFAULT[kind].each_pair do |field, value|
    if spec.key? field
      if value.is_a?(Array) && !spec[field].is_a?(Array)
        spec[field] = [ spec[field] ]
      end
    else
      spec[field] = value
    end
  end
end
license_block(lic2id) click to toggle source
# File bin/specificjson, line 2484
def license_block(lic2id)
  blocks = []
  lic2id.each_pair do |lic, id|
    blocks.push %(
#if 0
/*
#{id}:

#{$FILECONTENTS[lic]}
*/
#endif
)
  end
  blocks.join("\n")
end
licenses(needed) click to toggle source
# File bin/specificjson, line 2403
def licenses(needed)
  lic2id = { }
  needed.each do |name|
    lic = $PIECES[name]['license_stored']
    next if lic.nil? || lic2id.key?(lic)
    lic2id[lic] = "License #{lic2id.size + 1}"
  end
  lic2id
end
load_piece_file(piece, field, directory) click to toggle source
# File bin/specificjson, line 2119
def load_piece_file(piece, field, directory)
  filename = piece.fetch(field, nil)
  if filename.nil?
    piece[field] = nil
    piece["#{field}_stored"] = nil
    return
  end
  begin
    filename = File.realpath(filename, directory)
    puts filename
    f = File.new(filename, 'r')
    content = IO.read(f)
    f.close
  rescue StandardError
    aargh("Failed to open/read: #{filename}", 3)
  end
  stored = $FILECONTENTS.key(content)
  if stored.nil?
    stored = "c#{$FILECONTENTS.size}"
    $FILECONTENTS[stored] = content
  end
  piece["#{field}_stored"] = stored
end
load_spec(filename, root = nil) click to toggle source
# File bin/specificjson, line 2163
def load_spec(filename, root = nil)
  begin
    unless root.nil?
      filename = File.realpath(filename, root)
      puts filename
    end
    f = File.open(filename, 'r')
    input = IO.read(f)
    f.close
  rescue StandardError
    aargh("Failed to find/read #{filename}", 3)
  end
  begin
    specs = JSON.parse(input)
  rescue StandardError
    begin
      specs = YAML.safe_load(input, aliases: true)
    rescue StandardError
      aargh("#{filename} neither JSON nor YAML.", 3)
    end
  end
  specs
end
make_header(spec, piece_names, generated, lic2id) click to toggle source
# File bin/specificjson, line 2500
def make_header(spec, piece_names, generated, lic2id)
  h = File.new(spec['header'], 'w')
  h.puts %(// Auto-generated file. Do not edit.
#if !defined(#{spec['header'].upcase.sub('.', '_')})
#define #{spec['header'].upcase.sub('.', '_')}

#{license_block(lic2id)}
)
  h.puts %(
#{unique_in_order(piece_names, 'includes').join("\n")}

namespace #{spec['namespace']} {

#{unique_in_order(piece_names, 'declaration').join("\n")}
#{(generated.keys.map { |k| generated[k][:forward].join("\n") }).join("\n")}
)
  prev = nil
  piece_names.each do |name|
    piece = $PIECES[name]
    next if piece['header_stored'].nil?
    lic = piece['license_stored']
    if lic != prev
      h.puts
      h.puts(lic.nil? ? '// Unspecified license.' : "// Under #{lic2id[lic]}.")
      prev = lic
    end
    h.puts
    h.puts "// Origin: #{piece['header']}"
    h.puts(piece['header_content'])
  end
  generated.each_pair do |typename, object|
    h.puts %Q(
// #{typename}
#{object[:extern].join("\n")}

#{object[:typedef].join("\n")}

#{object[:class].join("\n")}
)
  end
  h.puts %Q(
} // namespace #{spec['namespace']}

#endif)
  h.close
  return spec['header']
end
make_source(spec, piece_names, generated, lic2id, header_name) click to toggle source
# File bin/specificjson, line 2548
def make_source(spec, piece_names, generated, lic2id, header_name)
  h = File.new(spec['source'], 'w')
  h.puts %(// Auto-generated file. Do not edit.
#{license_block(lic2id)}

#define INCLUDED_FROM_GENERATED_SOURCE 1
#include "#{header_name}"
#undef INCLUDED_FROM_GENERATED_SOURCE
#{unique_in_order(piece_names, 'source_includes').join("\n")}

using namespace #{spec['namespace']};
)
  prev = nil
  piece_names.each do |name|
    piece = $PIECES[name]
    next if piece['source_stored'].nil?
    lic = piece['license_stored']
    if lic != prev
      h.puts
      h.puts(lic.nil? ? '// Unspecified license.' : "// Under #{lic2id[lic]}.")
      prev = lic
    end
    h.puts
    h.puts "// Origin: #{piece['source']}"
    h.puts(piece['source_content'])
  end
  generated.each_pair do |typename, object|
    h.puts %(
// #{typename}
#{object[:extern_src].join("\n")}
)
  end
  h.close
  return spec['source']
end
parserpool_substitutions(needed, namespace) click to toggle source
# File bin/specificjson, line 2348
def parserpool_substitutions(needed, namespace)
  $pools = []
  $pooled = []
  needed.each do |name|
    piece = $PIECES[name]
    $pools.push(name) unless piece['poolindexes'].nil? && piece['poolparsers'].nil? && piece['poolparsertypes'].nil?
    $pooled.push(name) unless piece['pooled'].nil?
    %w[header source].each do |field|
      fc = piece["#{field}_stored"]
      next if fc.nil?
      piece["#{field}_content"] = String.new($FILECONTENTS[fc])
      next if 'specjson' == namespace
      until piece["#{field}_content"].sub!('specjson::', "#{namespace}::").nil?
      end
    end
  end
  poolvals = {
    'poolindexes' => [],
    'poolparsers' => [],
    'poolparsertypes' => []
  }
  $pooled.each_index do |k|
    piece = $PIECES[$pooled[k]]
    poolvals['poolindexes'].push $pooled[k]
    poolvals['poolparsers'].push piece['parsername']
    poolvals['poolparsertypes'].push "#{piece['parsername']}::Type"
    [ 'header', 'source' ].each do |field|
      fc = piece["#{field}_stored"]
      next if fc.nil?
      until piece["#{field}_content"].sub!(piece['pooled'], k.to_s).nil?
      end
    end
  end
  poolvals.each_pair { |k, v| poolvals[k] = v.join(', ') }
  $pools.each do |name|
    piece = $PIECES[name]
    %w[header source].each do |field|
      fc = piece["#{field}_stored"]
      next if fc.nil?
      poolvals.each_pair do |fld, value|
        until piece["#{field}_content"].sub!(piece[fld], value).nil?
        end
      end
    end
  end
  $pooledreqs = []
  $pooled.each do |name|
    piece = $PIECES[name]
    piece['all_requires'].each do |p|
      $pooledreqs.push p unless p == name
    end
  end
  $pooledreqs.uniq!
end
unique_in_order(piece_names, field) click to toggle source
# File bin/specificjson, line 2468
def unique_in_order(piece_names, field)
  values = []
  piece_names.each do |name|
    piece = $PIECES[name]
    next if piece[field].nil?
    if piece[field].is_a? String
      values.push(piece[field]) unless values.include? piece[field]
    else
      piece[field].each do |line|
        values.push(line) unless values.include? line
      end
    end
  end
  values
end
write_function(spec, typename) click to toggle source
# File bin/specificjson, line 2657
def write_function(spec, typename)
  object = spec['types'][typename]
  all_req = true
  object.each_value do |desc|
    all_req = false unless desc['required']
  end
  lines = [ %(
#if !defined(INCLUDED_FROM_GENERATED_SOURCE)
template<typename Sink>
void Write(Sink& S, const #{typename}& Value, std::vector<char>& Buffer) {
    char c = '{';
    S.write(&c, 1);) ]
  lines.push('    bool separated = true;') unless all_req
  prev_req = nil
  fields = object.keys
  # If write order is ever something other than the key one, change it here.
  fields.each do |field|
    desc = object[field]
    fill = ''
    unless desc['required']
      lines.push "    if (Value.#{desc['checker']}) {"
      fill = '    '
    end
    unless prev_req.nil?
      if all_req || prev_req
        lines.push "#{fill}    c = ',';"
        lines.push "#{fill}    S.write(&c, 1);"
      elsif !prev_req.nil?
        lines.push "#{fill}    if (!separated) {"
        lines.push "#{fill}        c = ',';"
        lines.push "#{fill}        S.write(&c, 1);"
        lines.push "#{fill}    }"
      end
    end
    lines.push "#{fill}    Write(S, #{typename}_#{field}, Buffer);"
    lines.push "#{fill}    c = ':';"
    lines.push "#{fill}    S.write(&c, 1);"
    lines.push "#{fill}    Write(S, Value.#{desc['accessor']}, Buffer);"
    lines.push("#{fill}    separated = false;") unless all_req || field == fields.last
    lines.push('    }') unless desc['required']
    prev_req = desc['required']
  end
  lines.push %(    c = '}';
    S.write(&c, 1);
}
#endif // INCLUDED_FROM_GENERATED_SOURCE
)
  lines.join("\n")
end