Set version to 1.0.1
[voodoo-lang.git] / bin / voodooc
blob8abfe1460877a95b05b5d317d80da9f0867c281d
1 #! /usr/bin/env ruby
3 require 'getoptlong'
5 require 'voodoo'
7 usage="USAGE: voodooc [options] <input file>"
8 help=<<EOT
9 Input file denotes the file to compile. The special name '-' causes
10 voodooc to read from standard input. In that case, the -o option is
11 mandatory.
13 Valid options are:
15 -a <architecture>
16 --arch <architecture>
17 --architecture <architecture>
18 Select target architecture. Use -a help to get a list of
19 supported architectures.
21 -f <format>
22 --format <format>
23 --output-format <format>
24 Select output format. Use -a <architecture> -f help to get a list of
25 supported output formats for architecture.
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.
34 --help
35 Display usage information and exit. No compilation will be performed.
37 -o <output file>
38 --output <output file>
39 --output-file <output file>
40 Set output file name. The special name '-' causes voodooc to write
41 to standard output.
43 --version
44 Display version information and exit. No compilation will be performed.
45 EOT
47 input_file = nil
48 output_file = nil
49 architecture = Voodoo::Config.default_architecture
50 output_format = Voodoo::Config.default_format
51 show_features = false
54 # Process command line
57 opts = GetoptLong.new(
58 ['--help', '-h', GetoptLong::NO_ARGUMENT ],
59 ['--arch', '--architecture', '-a', GetoptLong::REQUIRED_ARGUMENT ],
60 ['--features', GetoptLong::NO_ARGUMENT],
61 ['--output-file', '--output', '-o', GetoptLong::REQUIRED_ARGUMENT ],
62 ['--output-format', '--format', '-f', GetoptLong::REQUIRED_ARGUMENT ],
63 ['--version', GetoptLong::NO_ARGUMENT]
66 # Process options
67 opts.each do |opt, arg|
68 case opt
69 when '--help'
70 puts usage
71 puts help
72 exit
73 when '--arch'
74 architecture = arg.to_sym
75 when '--features'
76 show_features = true
77 when '--output-file'
78 output_file = arg
79 when '--output-format'
80 output_format = arg.to_sym
81 when '--version'
82 puts "#{Voodoo::Config::IMPLEMENTATION_NAME} version " +
83 Voodoo::Config::IMPLEMENTATION_VERSION
84 exit
85 end
86 end
88 if architecture == :help
89 # List supported architectures
90 puts "Supported architectures:"
91 puts Voodoo::CodeGenerator.architectures.map{|arch| arch.to_s}.sort
92 exit
93 end
95 if output_format == :help
96 # List supported output formats
97 puts "Supported output formats for architecture #{architecture}:"
98 puts Voodoo::CodeGenerator.formats(architecture).map{|f| f.to_s}.sort
99 exit
102 # Select code generator based on output format
103 begin
104 generator = Voodoo::CodeGenerator.get_generator :architecture => architecture,
105 :format => output_format
106 rescue NotImplementedError
107 if Voodoo::CodeGenerator.architecture_supported? architecture
108 $stderr.puts "Format #{output_format} is not supported for architecture #{architecture}"
109 $stderr.puts "Supported formats for #{architecture} are:"
110 $stderr.puts Voodoo::CodeGenerator.formats(architecture)
111 else
112 $stderr.puts "Architecture #{architecture} is not supported."
113 $stderr.puts "Supported architectures are:"
114 $stderr.puts Voodoo::CodeGenerator.architectures
116 exit 1
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]}"
124 exit
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"
136 $stderr.puts usage
137 exit 0x80
143 # Compile
146 if input_file == '-'
147 infile = $stdin
148 unless output_file
149 $stderr.puts "The -o option is mandatory when reading from standard input"
150 exit 0x80
152 else
153 infile = open input_file
154 # Set output_file if not already set
155 output_file = generator.output_file_name input_file unless output_file
158 if output_file == '-'
159 outfile = $stdout
160 else
161 outfile = open output_file, 'w'
164 begin
165 parser = Voodoo::Parser.new infile
166 compiler = Voodoo::Compiler.new parser, generator, outfile
168 compiler.compile
169 rescue => e
170 if output_file != '-'
171 File::unlink(output_file) if File::exists?(output_file)
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}"
188 message << error.message
189 $stderr.puts message
190 if error.text != nil
191 $stderr.print "\n #{error.text.gsub("\n", "\n ")}\n"
194 exit 1
195 else
196 raise
198 ensure
199 outfile.close
200 infile.close