-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4cf2ecc
commit 40b8d76
Showing
1 changed file
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
# frozen_string_literal: true | ||
|
||
# Mimic many of the functions of the C++ cmdline object | ||
class IWCmdline # rubocop:disable Metrics/ClassLength | ||
def initialize(opts) | ||
@_count = Hash.new(0) # count of how many times each argument encountered | ||
|
||
opts.freeze | ||
|
||
return unless opts.length.positive? | ||
|
||
@_unrecognised_options = [] | ||
|
||
okargs = {} | ||
|
||
opts.split('-').each do |opt| | ||
next if opt.empty? | ||
|
||
opt.gsub!(/ /, '') # spaces cannot be part of this | ||
|
||
if opt =~ /\S+=\S+/ # of the form option=requirement | ||
a = opt.split('=') | ||
okargs[a[0]] = a[1] | ||
else | ||
okargs[opt] = '' | ||
end | ||
end | ||
|
||
starts_with_dash = Regexp.new('^-+') | ||
|
||
@_option_value = {} | ||
|
||
iptr = 0 | ||
while iptr < ARGV.size | ||
opt = ARGV[iptr].to_s | ||
|
||
# important design decision: should it stop grabbing arguments once | ||
# it encounters a non-option? | ||
|
||
unless starts_with_dash.match(opt) | ||
iptr += 1 | ||
break | ||
end | ||
|
||
break if opt == '-' && iptr == ARGV.size - 1 | ||
|
||
opt = opt.gsub(/^-+/, '') | ||
|
||
unless okargs.key?(opt) | ||
@_unrecognised_options.push(opt) | ||
ARGV.delete_at(iptr) | ||
next | ||
end | ||
|
||
if @_count.key?(opt) | ||
@_count[opt] += 1 | ||
else | ||
@_count[opt] = 1 | ||
@_option_value[opt] = [] | ||
end | ||
|
||
qualifiers = okargs[opt] | ||
|
||
ARGV.delete_at(iptr) | ||
|
||
next unless qualifiers.length.positive? | ||
|
||
if qualifiers == 's' | ||
tmp = ARGV.delete_at(iptr) | ||
@_option_value[opt].push(tmp) | ||
next | ||
end | ||
|
||
if %w[i int].include?(qualifiers) | ||
tmp = ARGV.delete_at(iptr) | ||
raise "Invalid integer qualifier for -#{opt} option '#{tmp}'" unless tmp =~ /^-*\d+$/ | ||
|
||
@_option_value[opt].push(tmp.to_i) | ||
next | ||
end | ||
|
||
if %w[u uint].include?(qualifiers) | ||
tmp = ARGV.delete_at(iptr) | ||
raise "Invalid unsigned integer qualifier for -#{opt} option '#{tmp}'" unless tmp =~ /^\d+$/ | ||
|
||
@_option_value[opt].push(tmp.to_i) | ||
next | ||
end | ||
|
||
if qualifiers == 'ipos' | ||
tmp = ARGV.delete_at(iptr) | ||
unless tmp =~ /^\d+$/ && tmp.to_i.positive? | ||
raise "Invalid positive integer qualifier for -#{opt} option '#{tmp}'" | ||
end | ||
|
||
@_option_value[opt].push(tmp.to_i) | ||
next | ||
end | ||
|
||
if %w[f float].include?(qualifiers) | ||
tmp = ARGV.delete_at(iptr) | ||
begin | ||
f = Float(tmp) | ||
rescue ArgumentError | ||
raise "Invalid float for '-#{opt}', '#{tmp}'\n" | ||
end | ||
@_option_value[opt].push(tmp.to_f) | ||
next | ||
end | ||
|
||
if qualifiers == 'fraction' | ||
tmp = ARGV.delete_at(iptr) | ||
begin | ||
f = Float(tmp) | ||
rescue ArgumentError | ||
raise "Invalid fraction for '-#{opt}', '#{tmp}'\n" | ||
end | ||
raise "Invalid fraction '#{f}'" unless f >= 0.0 && f <= 1.0 | ||
|
||
@_option_value[opt].push(f) | ||
next | ||
end | ||
|
||
if qualifiers == 'sfile' | ||
tmp = ARGV.delete_at(iptr) | ||
raise "Must specify file name for option '-#{opt}'" unless tmp | ||
raise "Missing or empty file '#{tmp}'" unless FileTest.size?(tmp) | ||
|
||
@_option_value[opt].push(tmp) | ||
next | ||
end | ||
|
||
if qualifiers == 'xfile' | ||
tmp = ARGV.delete_at(iptr) | ||
raise "Must specify file name for option '-#{opt}'" unless tmp | ||
raise "Missing or empty file '#{tmp}'" unless FileTest.executable_real?(tmp) | ||
|
||
@_option_value[opt].push(tmp) | ||
next | ||
end | ||
|
||
if qualifiers == 'dir' | ||
tmp = ARGV.delete_at(iptr) | ||
raise "Must specify file name for option '-#{opt}'" unless tmp | ||
raise "Missing or invalid directory file '#{tmp}'" unless FileTest.directory?(tmp) | ||
|
||
@_option_value[opt].push(tmp) | ||
next | ||
end | ||
|
||
if qualifiers == 'close' | ||
gotclose = false | ||
closing_option = Regexp.new("^-+#{opt}$") | ||
tokens = [] | ||
while iptr < ARGV.size | ||
tmp2 = ARGV.delete_at(iptr) | ||
if closing_option.match(tmp2) | ||
gotclose = true | ||
break | ||
end | ||
tokens.push(tmp2) | ||
end | ||
raise "No closing -#{opt}" unless gotclose | ||
|
||
@_option_value[opt].push(tokens.join(' ')) | ||
next | ||
end | ||
|
||
$stderr.print "IWCmdline:initialize:invalid qualifier '#{qualifiers}' for option '#{opt}', value discarded\n" | ||
ARGV.delete_at(iptr) # just discard it???! | ||
end | ||
end | ||
|
||
def debug_print; end | ||
|
||
def unrecognised_options_encountered | ||
!@_unrecognised_options.empty? | ||
end | ||
|
||
def unrecognised_options | ||
@_unrecognised_options | ||
end | ||
|
||
def option_present(opt) | ||
@_count.key?(opt) | ||
end | ||
|
||
def option_count(opt) | ||
return 0 unless @_count.key?(opt) | ||
|
||
@_count[opt] | ||
end | ||
|
||
def value(opt, ndx = 0) | ||
return false unless @_option_value.key?(opt) | ||
|
||
tmp = @_option_value[opt] | ||
|
||
tmp[ndx] | ||
end | ||
|
||
def value_or_empty_string(opt) | ||
return '' unless @_option_value.key?(opt) | ||
|
||
tmp = @_option_value[opt] | ||
|
||
tmp[0] | ||
end | ||
|
||
def values(opt) | ||
# $stderr.print "Do we have '#{opt}' " << (@_option_value.key?(opt)).to_s << "\n" | ||
|
||
return [] unless @_option_value.key?(opt) | ||
|
||
@_option_value[opt] | ||
end | ||
|
||
def number_of_these_options_set(opt) | ||
rc = 0 | ||
opt.each do |o| | ||
rc += 1 if @_option_value.key?(o) | ||
end | ||
|
||
rc | ||
end | ||
|
||
# We may decide to combine two options. | ||
|
||
def combine_options(o1, o2) # rubocop:disable Naming/MethodParameterName | ||
# $stderr.print "Combining '#{o1}' with '#{o2}'\n" | ||
return unless @_option_value.key?(o1) && @_option_value.key?(o2) | ||
|
||
if !@_option_value.key?(o1) | ||
@_option_value[o1] = [] | ||
elsif !@_option_value.key?(o2) | ||
@_option_value[o2] = [] | ||
end | ||
|
||
tmp = @_option_value[o1] | @_option_value[o2] | ||
|
||
@_option_value[o1] = tmp | ||
@_option_value[o2] = tmp | ||
@_count[o1] = tmp.size | ||
@_count[o2] = tmp.size | ||
end | ||
|
||
def values_as_array(opt, separator) | ||
return [] unless @_option_value.key?(opt) | ||
|
||
rc = [] | ||
|
||
@_option_value[opt].each do |o| | ||
f = o.split(separator) | ||
f.each do |x| | ||
rc.push(x) | ||
end | ||
end | ||
|
||
rc | ||
end | ||
end |