cauterize 0.0.1.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +24 -0
  2. data/.rspec +1 -0
  3. data/.travisci.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +152 -0
  7. data/Rakefile +38 -0
  8. data/bin/cauterize +53 -0
  9. data/c/src/cauterize.c +74 -0
  10. data/c/src/cauterize.h +46 -0
  11. data/c/src/cauterize_debug.h +29 -0
  12. data/c/src/cauterize_util.h +7 -0
  13. data/c/test/greatest.h +536 -0
  14. data/c/test/test.c +166 -0
  15. data/cauterize.gemspec +26 -0
  16. data/example/Cauterize +44 -0
  17. data/example/build.sh +4 -0
  18. data/lib/cauterize/base_type.rb +96 -0
  19. data/lib/cauterize/builders.rb +27 -0
  20. data/lib/cauterize/builders/c/buildable.rb +59 -0
  21. data/lib/cauterize/builders/c/composite.rb +55 -0
  22. data/lib/cauterize/builders/c/enumeration.rb +41 -0
  23. data/lib/cauterize/builders/c/fixed_array.rb +62 -0
  24. data/lib/cauterize/builders/c/group.rb +95 -0
  25. data/lib/cauterize/builders/c/scalar.rb +31 -0
  26. data/lib/cauterize/builders/c/variable_array.rb +90 -0
  27. data/lib/cauterize/c_builder.rb +63 -0
  28. data/lib/cauterize/cauterize.rb +33 -0
  29. data/lib/cauterize/composite.rb +50 -0
  30. data/lib/cauterize/enumeration.rb +77 -0
  31. data/lib/cauterize/fixed_array.rb +43 -0
  32. data/lib/cauterize/formatter.rb +59 -0
  33. data/lib/cauterize/group.rb +56 -0
  34. data/lib/cauterize/scalar.rb +38 -0
  35. data/lib/cauterize/snake_case.rb +21 -0
  36. data/lib/cauterize/variable_array.rb +56 -0
  37. data/lib/cauterize/version.rb +3 -0
  38. data/spec/base_type_spec.rb +167 -0
  39. data/spec/builders/c/buildable_spec.rb +25 -0
  40. data/spec/builders/c/composite_spec.rb +46 -0
  41. data/spec/builders/c/enumeration_spec.rb +32 -0
  42. data/spec/builders/c/fixed_array_spec.rb +36 -0
  43. data/spec/builders/c/group_spec.rb +112 -0
  44. data/spec/builders/c/scalar_spec.rb +8 -0
  45. data/spec/builders/c/variable_array_spec.rb +50 -0
  46. data/spec/builders_spec.rb +51 -0
  47. data/spec/c_builder_spec.rb +133 -0
  48. data/spec/cauterize_spec.rb +8 -0
  49. data/spec/composite_spec.rb +62 -0
  50. data/spec/enumeration_spec.rb +104 -0
  51. data/spec/fixed_array_spec.rb +62 -0
  52. data/spec/group_spec.rb +104 -0
  53. data/spec/scalar_spec.rb +36 -0
  54. data/spec/spec_helper.rb +115 -0
  55. data/spec/support/shared_examples_for_array_buildables.rb +22 -0
  56. data/spec/support/shared_examples_for_c_buildables.rb +91 -0
  57. data/spec/support/shared_examples_for_sane_c_buildables.rb +22 -0
  58. data/spec/support/shared_examples_for_stubbed_functions.rb +18 -0
  59. data/spec/test_main.c +13 -0
  60. data/spec/variable_array_spec.rb +92 -0
  61. 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