voodoo 0.7.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|