cauterize 0.0.1.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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