cauterize 0.0.1.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.rspec +1 -0
- data/.travisci.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +152 -0
- data/Rakefile +38 -0
- data/bin/cauterize +53 -0
- data/c/src/cauterize.c +74 -0
- data/c/src/cauterize.h +46 -0
- data/c/src/cauterize_debug.h +29 -0
- data/c/src/cauterize_util.h +7 -0
- data/c/test/greatest.h +536 -0
- data/c/test/test.c +166 -0
- data/cauterize.gemspec +26 -0
- data/example/Cauterize +44 -0
- data/example/build.sh +4 -0
- data/lib/cauterize/base_type.rb +96 -0
- data/lib/cauterize/builders.rb +27 -0
- data/lib/cauterize/builders/c/buildable.rb +59 -0
- data/lib/cauterize/builders/c/composite.rb +55 -0
- data/lib/cauterize/builders/c/enumeration.rb +41 -0
- data/lib/cauterize/builders/c/fixed_array.rb +62 -0
- data/lib/cauterize/builders/c/group.rb +95 -0
- data/lib/cauterize/builders/c/scalar.rb +31 -0
- data/lib/cauterize/builders/c/variable_array.rb +90 -0
- data/lib/cauterize/c_builder.rb +63 -0
- data/lib/cauterize/cauterize.rb +33 -0
- data/lib/cauterize/composite.rb +50 -0
- data/lib/cauterize/enumeration.rb +77 -0
- data/lib/cauterize/fixed_array.rb +43 -0
- data/lib/cauterize/formatter.rb +59 -0
- data/lib/cauterize/group.rb +56 -0
- data/lib/cauterize/scalar.rb +38 -0
- data/lib/cauterize/snake_case.rb +21 -0
- data/lib/cauterize/variable_array.rb +56 -0
- data/lib/cauterize/version.rb +3 -0
- data/spec/base_type_spec.rb +167 -0
- data/spec/builders/c/buildable_spec.rb +25 -0
- data/spec/builders/c/composite_spec.rb +46 -0
- data/spec/builders/c/enumeration_spec.rb +32 -0
- data/spec/builders/c/fixed_array_spec.rb +36 -0
- data/spec/builders/c/group_spec.rb +112 -0
- data/spec/builders/c/scalar_spec.rb +8 -0
- data/spec/builders/c/variable_array_spec.rb +50 -0
- data/spec/builders_spec.rb +51 -0
- data/spec/c_builder_spec.rb +133 -0
- data/spec/cauterize_spec.rb +8 -0
- data/spec/composite_spec.rb +62 -0
- data/spec/enumeration_spec.rb +104 -0
- data/spec/fixed_array_spec.rb +62 -0
- data/spec/group_spec.rb +104 -0
- data/spec/scalar_spec.rb +36 -0
- data/spec/spec_helper.rb +115 -0
- data/spec/support/shared_examples_for_array_buildables.rb +22 -0
- data/spec/support/shared_examples_for_c_buildables.rb +91 -0
- data/spec/support/shared_examples_for_sane_c_buildables.rb +22 -0
- data/spec/support/shared_examples_for_stubbed_functions.rb +18 -0
- data/spec/test_main.c +13 -0
- data/spec/variable_array_spec.rb +92 -0
- metadata +212 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
module Cauterize
|
2
|
+
module Builders
|
3
|
+
module C
|
4
|
+
class Enumeration < Buildable
|
5
|
+
def render
|
6
|
+
"enum #{@blueprint.name.to_s}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def declare(formatter, sym)
|
10
|
+
formatter << "#{render} #{sym};"
|
11
|
+
end
|
12
|
+
|
13
|
+
def packer_defn(formatter)
|
14
|
+
formatter << packer_sig
|
15
|
+
formatter.braces do
|
16
|
+
formatter << "return CauterizeAppend(dst, (uint8_t*)src, sizeof(*src));"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def unpacker_defn(formatter)
|
21
|
+
formatter << unpacker_sig
|
22
|
+
formatter.braces do
|
23
|
+
formatter << "return CauterizeRead(src, (uint8_t*)dst, sizeof(*dst));"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def enum_defn(formatter)
|
28
|
+
formatter << render
|
29
|
+
formatter.braces do
|
30
|
+
@blueprint.values.values.each do |v|
|
31
|
+
formatter << "#{v.name.to_s.up_snake} = #{v.value},"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
formatter.append(";")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Cauterize::Builders.register(:c, Cauterize::Enumeration, Cauterize::Builders::C::Enumeration)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Cauterize
|
2
|
+
module Builders
|
3
|
+
module C
|
4
|
+
class FixedArray < Buildable
|
5
|
+
def render
|
6
|
+
# HEY! PAY ATTENTION!
|
7
|
+
# Keep in mind that there's no sane way to "render" an array in C
|
8
|
+
# that doesn't involve an identifier.
|
9
|
+
ty_bldr.render
|
10
|
+
end
|
11
|
+
|
12
|
+
def declare(formatter, sym)
|
13
|
+
formatter << "#{ty_bldr.render} #{sym}[#{@blueprint.array_size}]; /* #{@blueprint.name} */"
|
14
|
+
end
|
15
|
+
|
16
|
+
def packer_defn(formatter)
|
17
|
+
formatter << packer_sig
|
18
|
+
formatter.braces do
|
19
|
+
formatter << "CAUTERIZE_STATUS_T err;"
|
20
|
+
formatter << "size_t i;"
|
21
|
+
formatter.blank_line
|
22
|
+
|
23
|
+
# store each used item in the array
|
24
|
+
formatter << "for (i = 0; i < #{@blueprint.array_size}; i++)"
|
25
|
+
formatter.braces do
|
26
|
+
formatter << "if (CA_OK != (err = #{ty_bldr.packer_sym}(dst, &src[i]))) { return err; }"
|
27
|
+
end
|
28
|
+
formatter.blank_line
|
29
|
+
|
30
|
+
formatter << "return CA_OK;"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def unpacker_defn(formatter)
|
35
|
+
formatter << unpacker_sig
|
36
|
+
formatter.braces do
|
37
|
+
formatter << "CAUTERIZE_STATUS_T err;"
|
38
|
+
formatter << "size_t i;"
|
39
|
+
formatter.blank_line
|
40
|
+
|
41
|
+
# store each used item in the array
|
42
|
+
formatter << "for (i = 0; i < #{@blueprint.array_size}; i++)"
|
43
|
+
formatter.braces do
|
44
|
+
formatter << "if (CA_OK != (err = #{ty_bldr.unpacker_sym}(src, &dst[i]))) { return err; }"
|
45
|
+
end
|
46
|
+
formatter.blank_line
|
47
|
+
|
48
|
+
formatter << "return CA_OK;"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def ty_bldr
|
55
|
+
@ty_bldr ||= Builders.get(:c, @blueprint.array_type)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
Cauterize::Builders.register(:c, Cauterize::FixedArray, Cauterize::Builders::C::FixedArray)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Cauterize
|
2
|
+
module Builders
|
3
|
+
module C
|
4
|
+
class Group < Buildable
|
5
|
+
def initialize(blueprint)
|
6
|
+
super(blueprint)
|
7
|
+
@tag_enum = blueprint.tag_enum
|
8
|
+
end
|
9
|
+
|
10
|
+
def render
|
11
|
+
"struct #{@blueprint.name.to_s}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def declare(formatter, sym)
|
15
|
+
formatter << "#{render} #{sym};"
|
16
|
+
end
|
17
|
+
|
18
|
+
def packer_defn(formatter)
|
19
|
+
enum_builder = Builders.get(:c, @tag_enum)
|
20
|
+
formatter << packer_sig
|
21
|
+
formatter.braces do
|
22
|
+
formatter << "CAUTERIZE_STATUS_T err;"
|
23
|
+
|
24
|
+
# pack the tag
|
25
|
+
formatter << "if (CA_OK != (err = #{enum_builder.packer_sym}(dst, &src->tag))) { return err; }"
|
26
|
+
|
27
|
+
# pack the fields
|
28
|
+
formatter << "switch (src->tag)"
|
29
|
+
formatter.braces do
|
30
|
+
@blueprint.fields.values.each do |field|
|
31
|
+
bldr = Builders.get(:c, field.type)
|
32
|
+
formatter.backdent "case #{@blueprint.enum_sym(field.name)}:"
|
33
|
+
formatter << "if (CA_OK != (err = #{bldr.packer_sym}(dst, &src->data.#{field.name}))) { return err; }"
|
34
|
+
formatter << "break;"
|
35
|
+
end
|
36
|
+
|
37
|
+
formatter.backdent "default:"
|
38
|
+
formatter << "return CA_ERR_INVALUD_TYPE_TAG;"
|
39
|
+
formatter << "break;"
|
40
|
+
end
|
41
|
+
formatter << "return CA_OK;"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def unpacker_defn(formatter)
|
46
|
+
enum_builder = Builders.get(:c, @tag_enum)
|
47
|
+
formatter << unpacker_sig
|
48
|
+
formatter.braces do
|
49
|
+
formatter << "CAUTERIZE_STATUS_T err;"
|
50
|
+
|
51
|
+
# unpack the tag
|
52
|
+
formatter << "if (CA_OK != (err = #{enum_builder.unpacker_sym}(src, &dst->tag))) { return err; }"
|
53
|
+
|
54
|
+
# pack the fields
|
55
|
+
formatter << "switch (dst->tag)"
|
56
|
+
formatter.braces do
|
57
|
+
@blueprint.fields.values.each do |field|
|
58
|
+
bldr = Builders.get(:c, field.type)
|
59
|
+
formatter.backdent "case #{@blueprint.enum_sym(field.name)}:"
|
60
|
+
formatter << "if (CA_OK != (err = #{bldr.unpacker_sym}(src, &dst->data.#{field.name}))) { return err; }"
|
61
|
+
formatter << "break;"
|
62
|
+
end
|
63
|
+
|
64
|
+
formatter.backdent "default:"
|
65
|
+
formatter << "return CA_ERR_INVALUD_TYPE_TAG;"
|
66
|
+
formatter << "break;"
|
67
|
+
end
|
68
|
+
formatter << "return CA_OK;"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def struct_proto(formatter)
|
73
|
+
formatter << (render + ";")
|
74
|
+
end
|
75
|
+
|
76
|
+
def struct_defn(formatter)
|
77
|
+
formatter << render
|
78
|
+
formatter.braces do
|
79
|
+
Builders.get(:c, @tag_enum).declare(formatter, "tag")
|
80
|
+
formatter << "union"
|
81
|
+
formatter.braces do
|
82
|
+
@blueprint.fields.values.each do |field|
|
83
|
+
Builders.get(:c, field.type).declare(formatter, field.name)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
formatter.append(" data;")
|
87
|
+
end
|
88
|
+
formatter.append(";")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
Cauterize::Builders.register(:c, Cauterize::Group, Cauterize::Builders::C::Group)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Cauterize
|
2
|
+
module Builders
|
3
|
+
module C
|
4
|
+
class Scalar < Buildable
|
5
|
+
def render
|
6
|
+
@blueprint.name.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def declare(formatter, sym)
|
10
|
+
formatter << "#{render} #{sym};"
|
11
|
+
end
|
12
|
+
|
13
|
+
def packer_defn(formatter)
|
14
|
+
formatter << packer_sig
|
15
|
+
formatter.braces do
|
16
|
+
formatter << "return CauterizeAppend(dst, (uint8_t*)src, sizeof(*src));"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def unpacker_defn(formatter)
|
21
|
+
formatter << unpacker_sig
|
22
|
+
formatter.braces do
|
23
|
+
formatter << "return CauterizeRead(src, (uint8_t*)dst, sizeof(*dst));"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Cauterize::Builders.register(:c, Cauterize::Scalar, Cauterize::Builders::C::Scalar)
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Cauterize
|
2
|
+
module Builders
|
3
|
+
module C
|
4
|
+
class VariableArray < Buildable
|
5
|
+
def render
|
6
|
+
"struct #{@blueprint.name}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def declare(formatter, sym)
|
10
|
+
formatter << "struct #{@blueprint.name} #{sym};"
|
11
|
+
end
|
12
|
+
|
13
|
+
def packer_defn(formatter)
|
14
|
+
size_type_builder = Builders.get(:c, @blueprint.size_type)
|
15
|
+
array_type_builder = Builders.get(:c, @blueprint.array_type)
|
16
|
+
|
17
|
+
formatter << packer_sig
|
18
|
+
formatter.braces do
|
19
|
+
formatter << "CAUTERIZE_STATUS_T err;"
|
20
|
+
formatter << "size_t i;"
|
21
|
+
formatter.blank_line
|
22
|
+
# check the length
|
23
|
+
formatter << "if (src->length > ARRAY_SIZE(src->data)) { return CA_ERR_INVALID_LENGTH; }"
|
24
|
+
|
25
|
+
# store the length
|
26
|
+
formatter << "if (CA_OK != (err = #{size_type_builder.packer_sym}(dst, &src->length))) { return err; }"
|
27
|
+
formatter.blank_line
|
28
|
+
|
29
|
+
# store each used item in the array
|
30
|
+
formatter << "for (i = 0; i < src->length; i++)"
|
31
|
+
formatter.braces do
|
32
|
+
formatter << "if (CA_OK != (err = #{array_type_builder.packer_sym}(dst, &src->data[i]))) { return err; }"
|
33
|
+
end
|
34
|
+
formatter.blank_line
|
35
|
+
|
36
|
+
formatter << "return CA_OK;"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def unpacker_defn(formatter)
|
41
|
+
size_type_builder = Builders.get(:c, @blueprint.size_type)
|
42
|
+
array_type_builder = Builders.get(:c, @blueprint.array_type)
|
43
|
+
|
44
|
+
formatter << unpacker_sig
|
45
|
+
formatter.braces do
|
46
|
+
formatter << "CAUTERIZE_STATUS_T err;"
|
47
|
+
formatter << "size_t i;"
|
48
|
+
formatter.blank_line
|
49
|
+
|
50
|
+
# read the length
|
51
|
+
formatter << "if (CA_OK != (err = #{size_type_builder.unpacker_sym}(src, &dst->length))) { return err; }"
|
52
|
+
formatter.blank_line
|
53
|
+
|
54
|
+
# check the length
|
55
|
+
formatter << "if (dst->length > ARRAY_SIZE(dst->data)) { return CA_ERR_INVALID_LENGTH; }"
|
56
|
+
formatter.blank_line
|
57
|
+
|
58
|
+
|
59
|
+
# store each used item in the array
|
60
|
+
formatter << "for (i = 0; i < dst->length; i++)"
|
61
|
+
formatter.braces do
|
62
|
+
formatter << "if (CA_OK != (err = #{array_type_builder.unpacker_sym}(src, &dst->data[i]))) { return err; }"
|
63
|
+
end
|
64
|
+
formatter.blank_line
|
65
|
+
|
66
|
+
formatter << "return CA_OK;"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def struct_proto(formatter)
|
71
|
+
formatter << (render + ";")
|
72
|
+
end
|
73
|
+
|
74
|
+
def struct_defn(formatter)
|
75
|
+
formatter << render
|
76
|
+
formatter.braces do
|
77
|
+
at_builder = Builders.get(:c, @blueprint.array_type)
|
78
|
+
st_builder = Builders.get(:c, @blueprint.size_type)
|
79
|
+
|
80
|
+
st_builder.declare(formatter, "length")
|
81
|
+
formatter << "#{at_builder.render} data[#{@blueprint.array_size}];"
|
82
|
+
end
|
83
|
+
formatter.append(";")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
Cauterize::Builders.register(:c, Cauterize::VariableArray, Cauterize::Builders::C::VariableArray)
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Cauterize
|
2
|
+
class CBuilder
|
3
|
+
attr_reader :h, :c
|
4
|
+
|
5
|
+
def initialize(h_file, c_file, name="cauterize")
|
6
|
+
@h = h_file
|
7
|
+
@c = c_file
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def build
|
12
|
+
build_h
|
13
|
+
build_c
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def build_h
|
19
|
+
f = default_formatter
|
20
|
+
|
21
|
+
excluder = @name.up_snake + "_H_#{Time.now.to_i}"
|
22
|
+
f << "#ifndef #{excluder}"
|
23
|
+
f << "#define #{excluder}"
|
24
|
+
f.blank_line
|
25
|
+
f << %Q{#include <cauterize.h>}
|
26
|
+
f << %Q{#include <stdint.h>}
|
27
|
+
f.blank_line
|
28
|
+
|
29
|
+
instances = BaseType.all_instances
|
30
|
+
builders = instances.map {|i| Builders.get(:c, i)}
|
31
|
+
|
32
|
+
builders.each { |b| b.enum_defn(f) }
|
33
|
+
builders.each { |b| b.struct_proto(f) }
|
34
|
+
builders.each { |b| b.struct_defn(f) }
|
35
|
+
builders.each { |b| b.packer_proto(f) }
|
36
|
+
builders.each { |b| b.unpacker_proto(f) }
|
37
|
+
|
38
|
+
f.blank_line
|
39
|
+
f << "#endif /* #{excluder} */"
|
40
|
+
|
41
|
+
File.open(@h, "wb") do |fh|
|
42
|
+
fh.write(f.to_s)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_c
|
47
|
+
f = default_formatter
|
48
|
+
|
49
|
+
f << %Q{#include <cauterize_util.h>}
|
50
|
+
f << %Q{#include "#{@name}.h"}
|
51
|
+
|
52
|
+
instances = BaseType.all_instances
|
53
|
+
builders = instances.map {|i| Builders.get(:c, i)}
|
54
|
+
|
55
|
+
builders.each { |b| b.packer_defn(f) }
|
56
|
+
builders.each { |b| b.unpacker_defn(f) }
|
57
|
+
|
58
|
+
File.open(@c, "wb") do |fh|
|
59
|
+
fh.write(f.to_s)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "require_all"
|
2
|
+
|
3
|
+
lib_path = File.dirname(__FILE__) + "/.."
|
4
|
+
require_all Dir[lib_path + "/**/*.rb"]
|
5
|
+
|
6
|
+
module Cauterize
|
7
|
+
# Genearte the C code corresponding to the generated configuration
|
8
|
+
def self.generate_c(target_dir, desc_file)
|
9
|
+
Object.new.extend(Cauterize).instance_exec do
|
10
|
+
# this magic allows us to emit useful exception messages when evaling the
|
11
|
+
# file. if your description file has errors, you'll be able to find them
|
12
|
+
# because of this magic.
|
13
|
+
p = Proc.new {}
|
14
|
+
eval(File.read(desc_file), p.binding, desc_file)
|
15
|
+
end
|
16
|
+
output_prefix = get_name || "generated_interface"
|
17
|
+
|
18
|
+
FileUtils.mkdir_p(target_dir)
|
19
|
+
h_file = File.join(target_dir, "#{output_prefix}.h")
|
20
|
+
c_file = File.join(target_dir, "#{output_prefix}.c")
|
21
|
+
|
22
|
+
builder = Cauterize::CBuilder.new(h_file, c_file, output_prefix)
|
23
|
+
builder.build
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.get_name
|
27
|
+
@@description_name
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_name(desc_name)
|
31
|
+
@@description_name = desc_name
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# composite.rb
|
2
|
+
#
|
3
|
+
# Composites correspond to C structs.
|
4
|
+
|
5
|
+
module Cauterize
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def composite(name)
|
9
|
+
c = composites[name] || composites[name] = Composite.new(name)
|
10
|
+
yield c if block_given?
|
11
|
+
return c
|
12
|
+
end
|
13
|
+
|
14
|
+
def composite!(name, &blk)
|
15
|
+
if composites[name]
|
16
|
+
raise Exception.new("Composite with name #{name} already exists.")
|
17
|
+
else
|
18
|
+
composite(name, &blk)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def composites
|
23
|
+
@composites ||= {}
|
24
|
+
end
|
25
|
+
|
26
|
+
class CompositeField
|
27
|
+
attr_reader :name, :type
|
28
|
+
def initialize(field_name, type_name)
|
29
|
+
@name = field_name
|
30
|
+
@type = BaseType.find_type!(type_name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Composite < BaseType
|
35
|
+
attr_reader :fields
|
36
|
+
|
37
|
+
def initialize(name)
|
38
|
+
super
|
39
|
+
@fields = {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def field(name, type)
|
43
|
+
if @fields[name]
|
44
|
+
raise Exception.new("Field name #{name} already used.")
|
45
|
+
else
|
46
|
+
@fields[name] = CompositeField.new(name, type)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|