voodoo 0.7.0 → 1.0.0
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.
- data/bin/voodooc +71 -16
- data/lib/voodoo/compiler.rb +41 -13
- data/lib/voodoo/config.rb +5 -0
- data/lib/voodoo/generators/amd64_nasm_generator.rb +4 -0
- data/lib/voodoo/generators/arm_elf_generator.rb +33 -0
- data/lib/voodoo/generators/arm_gas_generator.rb +927 -0
- data/lib/voodoo/generators/common_code_generator.rb +19 -6
- data/lib/voodoo/generators/gas_elf_generator.rb +2 -2
- data/lib/voodoo/generators/i386_nasm_generator.rb +6 -1
- data/lib/voodoo/generators/mips_gas_generator.rb +14 -4
- data/lib/voodoo/generators/nasm_elf_generator.rb +1 -1
- data/lib/voodoo/generators/nasm_generator.rb +6 -10
- data/lib/voodoo/parser.rb +307 -128
- data/lib/voodoo/validator.rb +391 -0
- metadata +13 -11
- data/lib/voodoo/generators/generator_api1.rb +0 -95
data/bin/voodooc
CHANGED
@@ -24,17 +24,31 @@ Valid options are:
|
|
24
24
|
Select output format. Use -a <architecture> -f help to get a list of
|
25
25
|
supported output formats for architecture.
|
26
26
|
|
27
|
+
--features
|
28
|
+
Lists the features supported by this implementation. The features
|
29
|
+
are listed in the format <feature name><tab><version>, ordered
|
30
|
+
by feature name. The program exits after printing the list of
|
31
|
+
features; no compilation is performed.
|
32
|
+
|
33
|
+
-h
|
34
|
+
--help
|
35
|
+
Display usage information and exit. No compilation will be performed.
|
36
|
+
|
27
37
|
-o <output file>
|
28
38
|
--output <output file>
|
29
39
|
--output-file <output file>
|
30
40
|
Set output file name. The special name '-' causes voodooc to write
|
31
41
|
to standard output.
|
42
|
+
|
43
|
+
--version
|
44
|
+
Display version information and exit. No compilation will be performed.
|
32
45
|
EOT
|
33
46
|
|
34
47
|
input_file = nil
|
35
48
|
output_file = nil
|
36
49
|
architecture = Voodoo::Config.default_architecture
|
37
50
|
output_format = Voodoo::Config.default_format
|
51
|
+
show_features = false
|
38
52
|
|
39
53
|
#
|
40
54
|
# Process command line
|
@@ -43,8 +57,10 @@ output_format = Voodoo::Config.default_format
|
|
43
57
|
opts = GetoptLong.new(
|
44
58
|
['--help', '-h', GetoptLong::NO_ARGUMENT ],
|
45
59
|
['--arch', '--architecture', '-a', GetoptLong::REQUIRED_ARGUMENT ],
|
60
|
+
['--features', GetoptLong::NO_ARGUMENT],
|
46
61
|
['--output-file', '--output', '-o', GetoptLong::REQUIRED_ARGUMENT ],
|
47
|
-
['--output-format', '--format', '-f', GetoptLong::REQUIRED_ARGUMENT ]
|
62
|
+
['--output-format', '--format', '-f', GetoptLong::REQUIRED_ARGUMENT ],
|
63
|
+
['--version', GetoptLong::NO_ARGUMENT]
|
48
64
|
)
|
49
65
|
|
50
66
|
# Process options
|
@@ -56,10 +72,16 @@ opts.each do |opt, arg|
|
|
56
72
|
exit
|
57
73
|
when '--arch'
|
58
74
|
architecture = arg.to_sym
|
75
|
+
when '--features'
|
76
|
+
show_features = true
|
59
77
|
when '--output-file'
|
60
78
|
output_file = arg
|
61
79
|
when '--output-format'
|
62
80
|
output_format = arg.to_sym
|
81
|
+
when '--version'
|
82
|
+
puts "#{Voodoo::Config::IMPLEMENTATION_NAME} version " +
|
83
|
+
Voodoo::Config::IMPLEMENTATION_VERSION
|
84
|
+
exit
|
63
85
|
end
|
64
86
|
end
|
65
87
|
|
@@ -77,19 +99,6 @@ if output_format == :help
|
|
77
99
|
exit
|
78
100
|
end
|
79
101
|
|
80
|
-
# Get input file name
|
81
|
-
if ARGV.length == 1
|
82
|
-
input_file = ARGV[0]
|
83
|
-
else
|
84
|
-
if ARGV.length < 1
|
85
|
-
$stderr.puts "no input files"
|
86
|
-
else
|
87
|
-
$stderr.puts "Too many arguments"
|
88
|
-
end
|
89
|
-
$stderr.puts usage
|
90
|
-
exit 0x80
|
91
|
-
end
|
92
|
-
|
93
102
|
# Select code generator based on output format
|
94
103
|
begin
|
95
104
|
generator = Voodoo::CodeGenerator.get_generator :architecture => architecture,
|
@@ -107,6 +116,28 @@ rescue NotImplementedError
|
|
107
116
|
exit 1
|
108
117
|
end
|
109
118
|
|
119
|
+
# If requested, show features and exit
|
120
|
+
if show_features
|
121
|
+
generator.features.to_a.sort{|x,y| x[0].to_s <=> y[0].to_s}.each do |feature|
|
122
|
+
puts "#{feature[0]}\t#{feature[1]}"
|
123
|
+
end
|
124
|
+
exit
|
125
|
+
end
|
126
|
+
|
127
|
+
# Get input file name
|
128
|
+
if ARGV.length == 1
|
129
|
+
input_file = ARGV[0]
|
130
|
+
else
|
131
|
+
if ARGV.length < 1
|
132
|
+
$stderr.puts "no input files"
|
133
|
+
else
|
134
|
+
$stderr.puts "Too many arguments"
|
135
|
+
end
|
136
|
+
$stderr.puts usage
|
137
|
+
exit 0x80
|
138
|
+
end
|
139
|
+
|
140
|
+
|
110
141
|
|
111
142
|
#
|
112
143
|
# Compile
|
@@ -135,11 +166,35 @@ begin
|
|
135
166
|
compiler = Voodoo::Compiler.new parser, generator, outfile
|
136
167
|
|
137
168
|
compiler.compile
|
138
|
-
rescue
|
169
|
+
rescue => e
|
139
170
|
if output_file != '-'
|
140
171
|
File::unlink(output_file) if File::exists?(output_file)
|
141
172
|
end
|
142
|
-
|
173
|
+
|
174
|
+
# If e is a compiler error, iterate over all child errors and
|
175
|
+
# print user-friendly messages. Else, re-raise so that the default
|
176
|
+
# handling is performed.
|
177
|
+
if e.kind_of? Voodoo::Compiler::Error
|
178
|
+
e.errors.each do |error|
|
179
|
+
message = ''
|
180
|
+
if error.start_line != nil
|
181
|
+
message << "#{error.start_line}: "
|
182
|
+
if error.input_name != nil
|
183
|
+
message = "#{error.input_name}:#{message}"
|
184
|
+
else
|
185
|
+
message = "line #{message}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
message << error.message
|
189
|
+
$stderr.puts message
|
190
|
+
if error.text != nil
|
191
|
+
$stderr.print "\n #{error.text.gsub("\n", "\n ")}\n"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
exit 1
|
195
|
+
else
|
196
|
+
raise
|
197
|
+
end
|
143
198
|
ensure
|
144
199
|
outfile.close
|
145
200
|
infile.close
|
data/lib/voodoo/compiler.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'voodoo/parser'
|
2
|
+
|
1
3
|
module Voodoo
|
2
4
|
# Voodoo compiler driver.
|
3
5
|
# The compiler driver reads input from a parser (see
|
@@ -7,6 +9,20 @@ module Voodoo
|
|
7
9
|
# An example of its usage can be found on the main page for the
|
8
10
|
# Voodoo module.
|
9
11
|
class Compiler
|
12
|
+
class Error < StandardError
|
13
|
+
def initialize errors
|
14
|
+
@errors = errors
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :errors
|
18
|
+
|
19
|
+
def message
|
20
|
+
msg = ""
|
21
|
+
@errors.each {|e| msg << e.message << "\n"}
|
22
|
+
msg
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
10
26
|
# Initialize a compiler.
|
11
27
|
#
|
12
28
|
# Parameters:
|
@@ -23,23 +39,35 @@ module Voodoo
|
|
23
39
|
# Perform the compilation.
|
24
40
|
def compile
|
25
41
|
section = :code
|
42
|
+
errors = []
|
26
43
|
while true
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
section
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
begin
|
45
|
+
statement = @parser.parse_top_level
|
46
|
+
|
47
|
+
break if statement == nil
|
48
|
+
next if statement.empty?
|
49
|
+
|
50
|
+
case statement[0]
|
51
|
+
when :section
|
52
|
+
section = statement[1]
|
53
|
+
else
|
54
|
+
@generator.add section, statement
|
55
|
+
end
|
56
|
+
|
57
|
+
rescue Parser::ParseError => e
|
58
|
+
errors << e
|
59
|
+
if errors.length >= 100
|
60
|
+
raise Error.new(errors)
|
61
|
+
end
|
39
62
|
end
|
63
|
+
|
40
64
|
end
|
41
65
|
|
42
|
-
|
66
|
+
if errors.empty?
|
67
|
+
@generator.write @output
|
68
|
+
else
|
69
|
+
raise Error.new(errors)
|
70
|
+
end
|
43
71
|
end
|
44
72
|
end
|
45
73
|
end
|
data/lib/voodoo/config.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Voodoo
|
2
2
|
# Methods to get and set configuration parameters
|
3
3
|
module Config
|
4
|
+
IMPLEMENTATION_NAME = 'Voodoo Compiler'
|
5
|
+
IMPLEMENTATION_VERSION = '1.0.0'
|
6
|
+
|
4
7
|
# Class that holds configuration parameters
|
5
8
|
class Configuration
|
6
9
|
def initialize
|
@@ -35,6 +38,8 @@ module Voodoo
|
|
35
38
|
case arch
|
36
39
|
when 'x86_64', 'amd64'
|
37
40
|
:amd64
|
41
|
+
when 'arm'
|
42
|
+
:arm
|
38
43
|
when 'i386', 'i686'
|
39
44
|
:i386
|
40
45
|
when 'mips'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'voodoo/generators/arm_gas_generator'
|
4
|
+
require 'voodoo/generators/gas_elf_generator'
|
5
|
+
|
6
|
+
module Voodoo
|
7
|
+
# Generator that produces ELF objects for arm
|
8
|
+
class ARMELFGenerator < DelegateClass(ARMGasGenerator)
|
9
|
+
def initialize params = {}
|
10
|
+
@asmgenerator = ARMGasGenerator.new params
|
11
|
+
super(@asmgenerator)
|
12
|
+
@elfgenerator = GasELFGenerator.new @asmgenerator
|
13
|
+
end
|
14
|
+
|
15
|
+
def output_file_name input_name
|
16
|
+
@elfgenerator.output_file_name input_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def output_file_suffix
|
20
|
+
@elfgenerator.output_file_suffix
|
21
|
+
end
|
22
|
+
|
23
|
+
def write io
|
24
|
+
@elfgenerator.write io
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Register class for arm
|
29
|
+
Voodoo::CodeGenerator.register_generator ARMELFGenerator,
|
30
|
+
:architecture => :arm,
|
31
|
+
:format => :elf
|
32
|
+
|
33
|
+
end
|