diff options
author | Markus Roberts <Markus@reality.com> | 2010-07-09 18:05:04 -0700 |
---|---|---|
committer | Markus Roberts <Markus@reality.com> | 2010-07-09 18:05:04 -0700 |
commit | 9ee56f2e67be973da49b1d3f21de1bf87de35e6f (patch) | |
tree | ddab8c01509f47664c52c8a6b165bb5a974f138f /lib/puppet/external | |
parent | 051bd98751d9d4bc97f93f66723d9b7a00c0cfb4 (diff) | |
download | puppet-9ee56f2e67be973da49b1d3f21de1bf87de35e6f.tar.gz puppet-9ee56f2e67be973da49b1d3f21de1bf87de35e6f.tar.xz puppet-9ee56f2e67be973da49b1d3f21de1bf87de35e6f.zip |
Code smell: Inconsistent indentation and related formatting issues
* Replaced 163 occurances of
defined\? +([@a-zA-Z_.0-9?=]+)
with
defined?(\1)
This makes detecting subsequent patterns easier.
3 Examples:
The code:
if ! defined? @parse_config
becomes:
if ! defined?(@parse_config)
The code:
return @option_parser if defined? @option_parser
becomes:
return @option_parser if defined?(@option_parser)
The code:
if defined? @local and @local
becomes:
if defined?(@local) and @local
* Eliminate trailing spaces.
Replaced 428 occurances of ^(.*?) +$ with \1
1 file was skipped.
test/ral/providers/host/parsed.rb because 0
* Replace leading tabs with an appropriate number of spaces.
Replaced 306 occurances of ^(\t+)(.*) with
Tabs are not consistently expanded in all environments.
* Don't arbitrarily wrap on sprintf (%) operator.
Replaced 143 occurances of
(.*['"] *%)
+(.*)
with
Splitting the line does nothing to aid clarity and hinders further refactorings.
3 Examples:
The code:
raise Puppet::Error, "Cannot create %s: basedir %s is a file" %
[dir, File.join(path)]
becomes:
raise Puppet::Error, "Cannot create %s: basedir %s is a file" % [dir, File.join(path)]
The code:
Puppet.err "Will not start without authorization file %s" %
Puppet[:authconfig]
becomes:
Puppet.err "Will not start without authorization file %s" % Puppet[:authconfig]
The code:
$stderr.puts "Could not find host for PID %s with status %s" %
[pid, $?.exitstatus]
becomes:
$stderr.puts "Could not find host for PID %s with status %s" % [pid, $?.exitstatus]
* Don't break short arrays/parameter list in two.
Replaced 228 occurances of
(.*)
+(.*)
with
3 Examples:
The code:
puts @format.wrap(type.provider(prov).doc,
:indent => 4, :scrub => true)
becomes:
puts @format.wrap(type.provider(prov).doc, :indent => 4, :scrub => true)
The code:
assert(FileTest.exists?(daily),
"Did not make daily graph for %s" % type)
becomes:
assert(FileTest.exists?(daily), "Did not make daily graph for %s" % type)
The code:
assert(prov.target_object(:first).read !~ /^notdisk/,
"Did not remove thing from disk")
becomes:
assert(prov.target_object(:first).read !~ /^notdisk/, "Did not remove thing from disk")
* If arguments must wrap, treat them all equally
Replaced 510 occurances of
lines ending in things like ...(foo, or ...(bar(1,3),
with
\1
\2
3 Examples:
The code:
midscope.to_hash(false),
becomes:
assert_equal(
The code:
botscope.to_hash(true),
becomes:
# bottomscope, then checking that we see the right stuff.
The code:
:path => link,
becomes:
* Replaced 4516 occurances of ^( *)(.*) with
The present code base is supposed to use four-space indentation. In some places we failed
to maintain that standard. These should be fixed regardless of the 2 vs. 4 space question.
15 Examples:
The code:
def run_comp(cmd)
puts cmd
results = []
old_sync = $stdout.sync
$stdout.sync = true
line = []
begin
open("| #{cmd}", "r") do |f|
until f.eof? do
c = f.getc
becomes:
def run_comp(cmd)
puts cmd
results = []
old_sync = $stdout.sync
$stdout.sync = true
line = []
begin
open("| #{cmd}", "r") do |f|
until f.eof? do
c = f.getc
The code:
s.gsub!(/.{4}/n, '\\\\u\&')
}
string.force_encoding(Encoding::UTF_8)
string
rescue Iconv::Failure => e
raise GeneratorError, "Caught #{e.class}: #{e}"
end
else
def utf8_to_pson(string) # :nodoc:
string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
string.gsub!(/(
becomes:
s.gsub!(/.{4}/n, '\\\\u\&')
}
string.force_encoding(Encoding::UTF_8)
string
rescue Iconv::Failure => e
raise GeneratorError, "Caught #{e.class}: #{e}"
end
else
def utf8_to_pson(string) # :nodoc:
string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
string.gsub!(/(
The code:
end
}
rvalues: rvalue
| rvalues comma rvalue {
if val[0].instance_of?(AST::ASTArray)
result = val[0].push(val[2])
else
result = ast AST::ASTArray, :children => [val[0],val[2]]
end
}
becomes:
end
}
rvalues: rvalue
| rvalues comma rvalue {
if val[0].instance_of?(AST::ASTArray)
result = val[0].push(val[2])
else
result = ast AST::ASTArray, :children => [val[0],val[2]]
end
}
The code:
#passwdproc = proc { @password }
keytext = @key.export(
OpenSSL::Cipher::DES.new(:EDE3, :CBC),
@password
)
File.open(@keyfile, "w", 0400) { |f|
f << keytext
}
becomes:
# passwdproc = proc { @password }
keytext = @key.export(
OpenSSL::Cipher::DES.new(:EDE3, :CBC),
@password
)
File.open(@keyfile, "w", 0400) { |f|
f << keytext
}
The code:
end
def to_manifest
"%s { '%s':\n%s\n}" % [self.type.to_s, self.name,
@params.collect { |p, v|
if v.is_a? Array
" #{p} => [\'#{v.join("','")}\']"
else
" #{p} => \'#{v}\'"
end
}.join(",\n")
becomes:
end
def to_manifest
"%s { '%s':\n%s\n}" % [self.type.to_s, self.name,
@params.collect { |p, v|
if v.is_a? Array
" #{p} => [\'#{v.join("','")}\']"
else
" #{p} => \'#{v}\'"
end
}.join(",\n")
The code:
via the augeas tool.
Requires:
- augeas to be installed (http://www.augeas.net)
- ruby-augeas bindings
Sample usage with a string::
augeas{\"test1\" :
context => \"/files/etc/sysconfig/firstboot\",
changes => \"set RUN_FIRSTBOOT YES\",
becomes:
via the augeas tool.
Requires:
- augeas to be installed (http://www.augeas.net)
- ruby-augeas bindings
Sample usage with a string::
augeas{\"test1\" :
context => \"/files/etc/sysconfig/firstboot\",
changes => \"set RUN_FIRSTBOOT YES\",
The code:
names.should_not be_include("root")
end
describe "when generating a purgeable resource" do
it "should be included in the generated resources" do
Puppet::Type.type(:host).stubs(:instances).returns [@purgeable_resource]
@resources.generate.collect { |r| r.ref }.should include(@purgeable_resource.ref)
end
end
describe "when the instance's do not have an ensure property" do
becomes:
names.should_not be_include("root")
end
describe "when generating a purgeable resource" do
it "should be included in the generated resources" do
Puppet::Type.type(:host).stubs(:instances).returns [@purgeable_resource]
@resources.generate.collect { |r| r.ref }.should include(@purgeable_resource.ref)
end
end
describe "when the instance's do not have an ensure property" do
The code:
describe "when the instance's do not have an ensure property" do
it "should not be included in the generated resources" do
@no_ensure_resource = Puppet::Type.type(:exec).new(:name => '/usr/bin/env echo')
Puppet::Type.type(:host).stubs(:instances).returns [@no_ensure_resource]
@resources.generate.collect { |r| r.ref }.should_not include(@no_ensure_resource.ref)
end
end
describe "when the instance's ensure property does not accept absent" do
it "should not be included in the generated resources" do
@no_absent_resource = Puppet::Type.type(:service).new(:name => 'foobar')
becomes:
describe "when the instance's do not have an ensure property" do
it "should not be included in the generated resources" do
@no_ensure_resource = Puppet::Type.type(:exec).new(:name => '/usr/bin/env echo')
Puppet::Type.type(:host).stubs(:instances).returns [@no_ensure_resource]
@resources.generate.collect { |r| r.ref }.should_not include(@no_ensure_resource.ref)
end
end
describe "when the instance's ensure property does not accept absent" do
it "should not be included in the generated resources" do
@no_absent_resource = Puppet::Type.type(:service).new(:name => 'foobar')
The code:
func = nil
assert_nothing_raised do
func = Puppet::Parser::AST::Function.new(
:name => "template",
:ftype => :rvalue,
:arguments => AST::ASTArray.new(
:children => [stringobj(template)]
)
becomes:
func = nil
assert_nothing_raised do
func = Puppet::Parser::AST::Function.new(
:name => "template",
:ftype => :rvalue,
:arguments => AST::ASTArray.new(
:children => [stringobj(template)]
)
The code:
assert(
@store.allowed?("hostname.madstop.com", "192.168.1.50"),
"hostname not allowed")
assert(
! @store.allowed?("name.sub.madstop.com", "192.168.0.50"),
"subname name allowed")
becomes:
assert(
@store.allowed?("hostname.madstop.com", "192.168.1.50"),
"hostname not allowed")
assert(
! @store.allowed?("name.sub.madstop.com", "192.168.0.50"),
"subname name allowed")
The code:
assert_nothing_raised {
server = Puppet::Network::Handler.fileserver.new(
:Local => true,
:Config => false
)
}
becomes:
assert_nothing_raised {
server = Puppet::Network::Handler.fileserver.new(
:Local => true,
:Config => false
)
}
The code:
'yay',
{ :failonfail => false,
:uid => @user.uid,
:gid => @user.gid }
).returns('output')
output = Puppet::Util::SUIDManager.run_and_capture 'yay',
@user.uid,
@user.gid
becomes:
'yay',
{ :failonfail => false,
:uid => @user.uid,
:gid => @user.gid }
).returns('output')
output = Puppet::Util::SUIDManager.run_and_capture 'yay',
@user.uid,
@user.gid
The code:
).times(1)
pkg.provider.expects(
:aptget
).with(
'-y',
'-q',
'remove',
'faff'
becomes:
).times(1)
pkg.provider.expects(
:aptget
).with(
'-y',
'-q',
'remove',
'faff'
The code:
johnny one two
billy three four\n"
# Just parse and generate, to make sure it's isomorphic.
assert_nothing_raised do
assert_equal(text, @parser.to_file(@parser.parse(text)),
"parsing was not isomorphic")
end
end
def test_valid_attrs
becomes:
johnny one two
billy three four\n"
# Just parse and generate, to make sure it's isomorphic.
assert_nothing_raised do
assert_equal(text, @parser.to_file(@parser.parse(text)),
"parsing was not isomorphic")
end
end
def test_valid_attrs
The code:
"testing",
:onboolean => [true, "An on bool"],
:string => ["a string", "A string arg"]
)
result = []
should = []
assert_nothing_raised("Add args failed") do
@config.addargs(result)
end
@config.each do |name, element|
becomes:
"testing",
:onboolean => [true, "An on bool"],
:string => ["a string", "A string arg"]
)
result = []
should = []
assert_nothing_raised("Add args failed") do
@config.addargs(result)
end
@config.each do |name, element|
Diffstat (limited to 'lib/puppet/external')
-rwxr-xr-x | lib/puppet/external/base64.rb | 2 | ||||
-rw-r--r-- | lib/puppet/external/event-loop/better-definers.rb | 16 | ||||
-rw-r--r-- | lib/puppet/external/event-loop/event-loop.rb | 4 | ||||
-rw-r--r-- | lib/puppet/external/event-loop/signal-system.rb | 4 | ||||
-rwxr-xr-x | lib/puppet/external/nagios/base.rb | 34 | ||||
-rw-r--r-- | lib/puppet/external/nagios/parser.rb | 1087 | ||||
-rw-r--r-- | lib/puppet/external/pson/common.rb | 675 | ||||
-rw-r--r-- | lib/puppet/external/pson/pure.rb | 124 | ||||
-rw-r--r-- | lib/puppet/external/pson/pure/generator.rb | 840 | ||||
-rw-r--r-- | lib/puppet/external/pson/pure/parser.rb | 501 | ||||
-rw-r--r-- | lib/puppet/external/pson/version.rb | 12 |
11 files changed, 1650 insertions, 1649 deletions
diff --git a/lib/puppet/external/base64.rb b/lib/puppet/external/base64.rb index 4030ad358..1005c8f2f 100755 --- a/lib/puppet/external/base64.rb +++ b/lib/puppet/external/base64.rb @@ -6,7 +6,7 @@ require 'base64' -unless defined? Base64 +unless defined?(Base64) class Base64 def Base64.encode64(*args) Object.method(:encode64).call(*args) diff --git a/lib/puppet/external/event-loop/better-definers.rb b/lib/puppet/external/event-loop/better-definers.rb index 5d6175fe9..c600fc208 100644 --- a/lib/puppet/external/event-loop/better-definers.rb +++ b/lib/puppet/external/event-loop/better-definers.rb @@ -69,7 +69,7 @@ class Module new_aliases.kind_of? Array or new_aliases = [new_aliases] for new_alias in new_aliases do class_eval %{def #{new_alias}(*args, &block) - #{existing_name}(*args, &block) end} + #{existing_name}(*args, &block) end} end end end @@ -94,7 +94,7 @@ class Module end def writer_defined? (name) - method_defined? name.to_sym.writer + method_defined?(name.to_sym.writer) end # If you pass a predicate symbol :foo? to this method, it'll first @@ -110,7 +110,7 @@ class Module end if name.predicate? class_eval %{def #{name.imperative} - self.#{name.writer} true end} + self.#{name.writer} true end} end end end @@ -130,7 +130,7 @@ class Module def define_opposite_readers (name_pairs) name_pairs.collect! { |k, v| [k.to_sym, v.to_sym] } for opposite_name, name in name_pairs do - define_reader(name) unless method_defined? name + define_reader(name) unless method_defined?(name) class_eval %{def #{opposite_name} ; not #{name} end} end end @@ -138,11 +138,11 @@ class Module def define_opposite_writers (name_pairs) name_pairs.collect! { |k, v| [k.to_sym, v.to_sym] } for opposite_name, name in name_pairs do - define_writer(name) unless writer_defined? name + define_writer(name) unless writer_defined?(name) class_eval %{def #{opposite_name.writer} x - self.#{name.writer} !x end} + self.#{name.writer} !x end} class_eval %{def #{opposite_name.imperative} - self.#{name.writer} false end} + self.#{name.writer} false end} end end @@ -167,7 +167,7 @@ class Module define_opposite_writer(opposite_name => name) end - public :define_method + public :define_method def define_methods (*names, &body) names.each { |name| define_method(name, &body) } diff --git a/lib/puppet/external/event-loop/event-loop.rb b/lib/puppet/external/event-loop/event-loop.rb index 75febab80..06fa34607 100644 --- a/lib/puppet/external/event-loop/event-loop.rb +++ b/lib/puppet/external/event-loop/event-loop.rb @@ -118,7 +118,7 @@ class EventLoop end end - private + private def select (timeout) @wakeup_time = timeout ? Time.now + timeout : nil @@ -130,7 +130,7 @@ class EventLoop @timers.each { |x| x.sound_alarm if x.ready? } end - public + public def quit ; stopped! ; wake_up ; self end diff --git a/lib/puppet/external/event-loop/signal-system.rb b/lib/puppet/external/event-loop/signal-system.rb index 07feb9bf0..8d97c4359 100644 --- a/lib/puppet/external/event-loop/signal-system.rb +++ b/lib/puppet/external/event-loop/signal-system.rb @@ -35,7 +35,7 @@ module SignalEmitterModule def define_signal (name, slot=:before, &body) # Can't use `define_method' and take a block pre-1.9. class_eval %{ def on_#{name} &block - add_signal_handler(:#{name}, &block) end } + add_signal_handler(:#{name}, &block) end } define_signal_handler(name, :before, &lambda {|*a|}) define_signal_handler(name, :after, &lambda {|*a|}) define_signal_handler(name, slot, &body) if block_given? @@ -160,7 +160,7 @@ module SignalObserver names.each { |x| __ignore_signal_1(subject, x) } end - private + private def __ignore_signal_1(subject, name) @observed_signals[subject][name].each do |handler| diff --git a/lib/puppet/external/nagios/base.rb b/lib/puppet/external/nagios/base.rb index 69c2c6aab..1b49459a4 100755 --- a/lib/puppet/external/nagios/base.rb +++ b/lib/puppet/external/nagios/base.rb @@ -63,7 +63,7 @@ class Nagios::Base # Return a mapping (or nil) for a param def self.mapping(name) name = name.intern if name.is_a? String - if defined? @map + if defined?(@map) @map[name] else nil @@ -72,7 +72,7 @@ class Nagios::Base # Return the namevar for the canonical name. def self.namevar - if defined? @namevar + if defined?(@namevar) return @namevar else if parameter?(:name) @@ -157,7 +157,7 @@ class Nagios::Base # Whether a given parameter is suppressed. def self.suppress?(name) - defined? @suppress and @suppress.include?(name) + defined?(@suppress) and @suppress.include?(name) end # Return our name as the string. @@ -197,7 +197,7 @@ class Nagios::Base self[param] = value } if @namevar == :_naginator_name - self['_naginator_name'] = self['name'] + self['_naginator_name'] = self['name'] end end @@ -241,7 +241,7 @@ class Nagios::Base end def parammap(param) - unless defined? @map + unless defined?(@map) map = { self.namevar => "cn" } @@ -257,7 +257,7 @@ class Nagios::Base end def parent - unless defined? self.class.attached + unless defined?(self.class.attached) puts "Duh, you called parent on an unattached class" return end @@ -346,9 +346,9 @@ class Nagios::Base end newtype :hostgroup do - setparameters :hostgroup_name, :alias, :members, :hostgroup_members, :notes, - :notes_url, :action_url, - :register, :use + setparameters :hostgroup_name, :alias, :members, :hostgroup_members, :notes, + :notes_url, :action_url, + :register, :use end newtype :service do @@ -434,14 +434,14 @@ class Nagios::Base end newtype :hostdependency do - auxiliary = true - setparameters :dependent_host_name, :dependent_hostgroup_name, :host_name, - :hostgroup_name, :inherits_parent, :execution_failure_criteria, - :notification_failure_criteria, :dependency_period, - :register, :use, - :_naginator_name - - setnamevar :_naginator_name + auxiliary = true + setparameters :dependent_host_name, :dependent_hostgroup_name, :host_name, + :hostgroup_name, :inherits_parent, :execution_failure_criteria, + :notification_failure_criteria, :dependency_period, + :register, :use, + :_naginator_name + + setnamevar :_naginator_name end newtype :hostescalation do diff --git a/lib/puppet/external/nagios/parser.rb b/lib/puppet/external/nagios/parser.rb index 498b0884e..deea9f3bc 100644 --- a/lib/puppet/external/nagios/parser.rb +++ b/lib/puppet/external/nagios/parser.rb @@ -25,433 +25,432 @@ self.class.module_eval <<'..end racc/parser.rb modeval..id5256434e8a', 'racc/par # unless defined?(NotImplementedError) - NotImplementedError = NotImplementError + NotImplementedError = NotImplementError end module Racc - class ParseError < StandardError; end + class ParseError < StandardError; end end unless defined?(::ParseError) - ParseError = Racc::ParseError + ParseError = Racc::ParseError end module Racc - unless defined?(Racc_No_Extentions) - Racc_No_Extentions = false - end - - class Parser - - Racc_Runtime_Version = '1.4.5' - Racc_Runtime_Revision = '$Revision: 1.7 $'.split[1] - - Racc_Runtime_Core_Version_R = '1.4.5' - Racc_Runtime_Core_Revision_R = '$Revision: 1.7 $'.split[1] - begin - require 'racc/cparse' - # Racc_Runtime_Core_Version_C = (defined in extention) - Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2] - unless new.respond_to?(:_racc_do_parse_c, true) - raise LoadError, 'old cparse.so' - end - if Racc_No_Extentions - raise LoadError, 'selecting ruby version of racc runtime core' - end - - Racc_Main_Parsing_Routine = :_racc_do_parse_c - Racc_YY_Parse_Method = :_racc_yyparse_c - Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C - Racc_Runtime_Type = 'c' - rescue LoadError - Racc_Main_Parsing_Routine = :_racc_do_parse_rb - Racc_YY_Parse_Method = :_racc_yyparse_rb - Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R - Racc_Runtime_Type = 'ruby' + unless defined?(Racc_No_Extentions) + Racc_No_Extentions = false end - def Parser.racc_runtime_type - Racc_Runtime_Type - end + class Parser - private - - def _racc_setup - @yydebug = false unless self.class::Racc_debug_parser - @yydebug = false unless defined?(@yydebug) - if @yydebug - @racc_debug_out = $stderr unless defined?(@racc_debug_out) - @racc_debug_out ||= $stderr - end - arg = self.class::Racc_arg - arg[13] = true if arg.size < 14 - arg - end + Racc_Runtime_Version = '1.4.5' + Racc_Runtime_Revision = '$Revision: 1.7 $'.split[1] - def _racc_init_sysvars - @racc_state = [0] - @racc_tstack = [] - @racc_vstack = [] + Racc_Runtime_Core_Version_R = '1.4.5' + Racc_Runtime_Core_Revision_R = '$Revision: 1.7 $'.split[1] + begin + require 'racc/cparse' + # Racc_Runtime_Core_Version_C = (defined in extention) + Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2] + unless new.respond_to?(:_racc_do_parse_c, true) + raise LoadError, 'old cparse.so' + end + if Racc_No_Extentions + raise LoadError, 'selecting ruby version of racc runtime core' + end - @racc_t = nil - @racc_val = nil + Racc_Main_Parsing_Routine = :_racc_do_parse_c + Racc_YY_Parse_Method = :_racc_yyparse_c + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C + Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C + Racc_Runtime_Type = 'c' + rescue LoadError + Racc_Main_Parsing_Routine = :_racc_do_parse_rb + Racc_YY_Parse_Method = :_racc_yyparse_rb + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R + Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R + Racc_Runtime_Type = 'ruby' + end - @racc_read_next = true + def Parser.racc_runtime_type + Racc_Runtime_Type + end - @racc_user_yyerror = false - @racc_error_status = 0 - end + private - ### - ### do_parse - ### + def _racc_setup + @yydebug = false unless self.class::Racc_debug_parser + @yydebug = false unless defined?(@yydebug) + if @yydebug + @racc_debug_out = $stderr unless defined?(@racc_debug_out) + @racc_debug_out ||= $stderr + end + arg = self.class::Racc_arg + arg[13] = true if arg.size < 14 + arg + end - def do_parse - __send__(Racc_Main_Parsing_Routine, _racc_setup(), false) - end + def _racc_init_sysvars + @racc_state = [0] + @racc_tstack = [] + @racc_vstack = [] - def next_token - raise NotImplementedError, "#{self.class}\#next_token is not defined" - end + @racc_t = nil + @racc_val = nil + + @racc_read_next = true + + @racc_user_yyerror = false + @racc_error_status = 0 + end + + ### + ### do_parse + ### + + def do_parse + __send__(Racc_Main_Parsing_Routine, _racc_setup(), false) + end - def _racc_do_parse_rb(arg, in_debug) - action_table, action_check, action_default, action_pointer, - goto_table, goto_check, goto_default, goto_pointer, - nt_base, reduce_table, token_table, shift_n, - reduce_n, use_result, * = arg - - _racc_init_sysvars - tok = act = i = nil - nerr = 0 - - catch(:racc_end_parse) { - while true - if i = action_pointer[@racc_state[-1]] - if @racc_read_next - if @racc_t != 0 # not EOF - tok, @racc_val = next_token() - unless tok # EOF - @racc_t = 0 + def next_token + raise NotImplementedError, "#{self.class}\#next_token is not defined" + end + + def _racc_do_parse_rb(arg, in_debug) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + + _racc_init_sysvars + tok = act = i = nil + nerr = 0 + + catch(:racc_end_parse) { + while true + if i = action_pointer[@racc_state[-1]] + if @racc_read_next + if @racc_t != 0 # not EOF + tok, @racc_val = next_token() + unless tok # EOF + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + racc_read_token(@racc_t, tok, @racc_val) if @yydebug + @racc_read_next = false + end + end + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end else - @racc_t = (token_table[tok] or 1) # error token + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; end - racc_read_token(@racc_t, tok, @racc_val) if @yydebug - @racc_read_next = false - end - end - i += @racc_t - unless i >= 0 and - act = action_table[i] and - action_check[i] == @racc_state[-1] - act = action_default[@racc_state[-1]] end - else - act = action_default[@racc_state[-1]] - end - while act = _racc_evalact(act, arg) - ; - end - end - } - end + } + end - ### - ### yyparse - ### + ### + ### yyparse + ### - def yyparse(recv, mid) - __send__(Racc_YY_Parse_Method, recv, mid, _racc_setup(), true) - end + def yyparse(recv, mid) + __send__(Racc_YY_Parse_Method, recv, mid, _racc_setup(), true) + end - def _racc_yyparse_rb(recv, mid, arg, c_debug) - action_table, action_check, action_default, action_pointer, - goto_table, goto_check, goto_default, goto_pointer, - nt_base, reduce_table, token_table, shift_n, - reduce_n, use_result, * = arg - - _racc_init_sysvars - tok = nil - act = nil - i = nil - nerr = 0 - - catch(:racc_end_parse) { - until i = action_pointer[@racc_state[-1]] - while act = _racc_evalact(action_default[@racc_state[-1]], arg) - ; - end - end - recv.__send__(mid) do |tok, val| - unless tok - @racc_t = 0 - else - @racc_t = (token_table[tok] or 1) # error token - end - @racc_val = val - @racc_read_next = false - - i += @racc_t - unless i >= 0 and - act = action_table[i] and - action_check[i] == @racc_state[-1] - act = action_default[@racc_state[-1]] - end - while act = _racc_evalact(act, arg) - ; - end - - while not (i = action_pointer[@racc_state[-1]]) or - not @racc_read_next or - @racc_t == 0 # $ - unless i and i += @racc_t and - i >= 0 and - act = action_table[i] and - action_check[i] == @racc_state[-1] - act = action_default[@racc_state[-1]] + def _racc_yyparse_rb(recv, mid, arg, c_debug) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + + _racc_init_sysvars + tok = nil + act = nil + i = nil + nerr = 0 + + catch(:racc_end_parse) { + until i = action_pointer[@racc_state[-1]] + while act = _racc_evalact(action_default[@racc_state[-1]], arg) + ; + end end - while act = _racc_evalact(act, arg) - ; + recv.__send__(mid) do |tok, val| + unless tok + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + @racc_val = val + @racc_read_next = false + + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + + while not (i = action_pointer[@racc_state[-1]]) or + not @racc_read_next or + @racc_t == 0 # $ + unless i and i += @racc_t and + i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + end end - end + } end - } - end - - ### - ### common - ### - def _racc_evalact(act, arg) - action_table, action_check, action_default, action_pointer, - goto_table, goto_check, goto_default, goto_pointer, - nt_base, reduce_table, token_table, shift_n, - reduce_n, use_result, * = arg - nerr = 0 # tmp + ### + ### common + ### + + def _racc_evalact(act, arg) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + nerr = 0 # tmp + + if act > 0 and act < shift_n + # + # shift + # + if @racc_error_status > 0 + @racc_error_status -= 1 unless @racc_t == 1 # error token + end + @racc_vstack.push @racc_val + @racc_state.push act + @racc_read_next = true + if @yydebug + @racc_tstack.push @racc_t + racc_shift @racc_t, @racc_tstack, @racc_vstack + end - if act > 0 and act < shift_n - # - # shift - # - if @racc_error_status > 0 - @racc_error_status -= 1 unless @racc_t == 1 # error token - end - @racc_vstack.push @racc_val - @racc_state.push act - @racc_read_next = true - if @yydebug - @racc_tstack.push @racc_t - racc_shift @racc_t, @racc_tstack, @racc_vstack - end + elsif act < 0 and act > -reduce_n + # + # reduce + # + code = catch(:racc_jump) { + @racc_state.push _racc_do_reduce(arg, act) + false + } + if code + case code + when 1 # yyerror + @racc_user_yyerror = true # user_yyerror + return -reduce_n + when 2 # yyaccept + return shift_n + else + raise '[Racc Bug] unknown jump code' + end + end - elsif act < 0 and act > -reduce_n - # - # reduce - # - code = catch(:racc_jump) { - @racc_state.push _racc_do_reduce(arg, act) - false - } - if code - case code - when 1 # yyerror - @racc_user_yyerror = true # user_yyerror - return -reduce_n - when 2 # yyaccept - return shift_n - else - raise '[Racc Bug] unknown jump code' - end - end - - elsif act == shift_n - # - # accept - # - racc_accept if @yydebug - throw :racc_end_parse, @racc_vstack[0] + elsif act == shift_n + # + # accept + # + racc_accept if @yydebug + throw :racc_end_parse, @racc_vstack[0] + + elsif act == -reduce_n + # + # error + # + case @racc_error_status + when 0 + unless arg[21] # user_yyerror + nerr += 1 + on_error @racc_t, @racc_val, @racc_vstack + end + when 3 + if @racc_t == 0 # is $ + throw :racc_end_parse, nil + end + @racc_read_next = true + end + @racc_user_yyerror = false + @racc_error_status = 3 + while true + if i = action_pointer[@racc_state[-1]] + i += 1 # error token + if i >= 0 and + (act = action_table[i]) and + action_check[i] == @racc_state[-1] + break + end + end + throw :racc_end_parse, nil if @racc_state.size <= 1 + @racc_state.pop + @racc_vstack.pop + if @yydebug + @racc_tstack.pop + racc_e_pop @racc_state, @racc_tstack, @racc_vstack + end + end + return act - elsif act == -reduce_n - # - # error - # - case @racc_error_status - when 0 - unless arg[21] # user_yyerror - nerr += 1 - on_error @racc_t, @racc_val, @racc_vstack - end - when 3 - if @racc_t == 0 # is $ - throw :racc_end_parse, nil - end - @racc_read_next = true - end - @racc_user_yyerror = false - @racc_error_status = 3 - while true - if i = action_pointer[@racc_state[-1]] - i += 1 # error token - if i >= 0 and - (act = action_table[i]) and - action_check[i] == @racc_state[-1] - break + else + raise "[Racc Bug] unknown action #{act.inspect}" end - end - throw :racc_end_parse, nil if @racc_state.size <= 1 - @racc_state.pop - @racc_vstack.pop - if @yydebug - @racc_tstack.pop - racc_e_pop @racc_state, @racc_tstack, @racc_vstack - end + + racc_next_state(@racc_state[-1], @racc_state) if @yydebug + + nil end - return act - else - raise "[Racc Bug] unknown action #{act.inspect}" - end + def _racc_do_reduce(arg, act) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + state = @racc_state + vstack = @racc_vstack + tstack = @racc_tstack + + i = act * -3 + len = reduce_table[i] + reduce_to = reduce_table[i+1] + method_id = reduce_table[i+2] + void_array = [] + + tmp_t = tstack[-len, len] if @yydebug + tmp_v = vstack[-len, len] + tstack[-len, len] = void_array if @yydebug + vstack[-len, len] = void_array + state[-len, len] = void_array + + # tstack must be updated AFTER method call + if use_result + vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]) + else + vstack.push __send__(method_id, tmp_v, vstack) + end + tstack.push reduce_to + + racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug - racc_next_state(@racc_state[-1], @racc_state) if @yydebug + k1 = reduce_to - nt_base + if i = goto_pointer[k1] + i += state[-1] + if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 + return curstate + end + end + goto_default[k1] + end - nil - end + def on_error(t, val, vstack) + raise ParseError, sprintf("\nparse error on value %s (%s)", val.inspect, token_to_str(t) || '?') + end - def _racc_do_reduce(arg, act) - action_table, action_check, action_default, action_pointer, - goto_table, goto_check, goto_default, goto_pointer, - nt_base, reduce_table, token_table, shift_n, - reduce_n, use_result, * = arg - state = @racc_state - vstack = @racc_vstack - tstack = @racc_tstack - - i = act * -3 - len = reduce_table[i] - reduce_to = reduce_table[i+1] - method_id = reduce_table[i+2] - void_array = [] - - tmp_t = tstack[-len, len] if @yydebug - tmp_v = vstack[-len, len] - tstack[-len, len] = void_array if @yydebug - vstack[-len, len] = void_array - state[-len, len] = void_array - - # tstack must be updated AFTER method call - if use_result - vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]) - else - vstack.push __send__(method_id, tmp_v, vstack) - end - tstack.push reduce_to - - racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug - - k1 = reduce_to - nt_base - if i = goto_pointer[k1] - i += state[-1] - if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 - return curstate - end - end - goto_default[k1] - end + def yyerror + throw :racc_jump, 1 + end - def on_error(t, val, vstack) - raise ParseError, sprintf("\nparse error on value %s (%s)", - val.inspect, token_to_str(t) || '?') - end + def yyaccept + throw :racc_jump, 2 + end - def yyerror - throw :racc_jump, 1 - end + def yyerrok + @racc_error_status = 0 + end - def yyaccept - throw :racc_jump, 2 - end + # + # for debugging output + # - def yyerrok - @racc_error_status = 0 - end + def racc_read_token(t, tok, val) + @racc_debug_out.print 'read ' + @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' + @racc_debug_out.puts val.inspect + @racc_debug_out.puts + end - # - # for debugging output - # + def racc_shift(tok, tstack, vstack) + @racc_debug_out.puts "shift #{racc_token2str tok}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end - def racc_read_token(t, tok, val) - @racc_debug_out.print 'read ' - @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' - @racc_debug_out.puts val.inspect - @racc_debug_out.puts - end + def racc_reduce(toks, sim, tstack, vstack) + out = @racc_debug_out + out.print 'reduce ' + if toks.empty? + out.print ' <none>' + else + toks.each {|t| out.print ' ', racc_token2str(t) } + end + out.puts " --> #{racc_token2str(sim)}" - def racc_shift(tok, tstack, vstack) - @racc_debug_out.puts "shift #{racc_token2str tok}" - racc_print_stacks tstack, vstack - @racc_debug_out.puts - end + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end - def racc_reduce(toks, sim, tstack, vstack) - out = @racc_debug_out - out.print 'reduce ' - if toks.empty? - out.print ' <none>' - else - toks.each {|t| out.print ' ', racc_token2str(t) } - end - out.puts " --> #{racc_token2str(sim)}" - - racc_print_stacks tstack, vstack - @racc_debug_out.puts - end + def racc_accept + @racc_debug_out.puts 'accept' + @racc_debug_out.puts + end - def racc_accept - @racc_debug_out.puts 'accept' - @racc_debug_out.puts - end + def racc_e_pop(state, tstack, vstack) + @racc_debug_out.puts 'error recovering mode: pop token' + racc_print_states state + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end - def racc_e_pop(state, tstack, vstack) - @racc_debug_out.puts 'error recovering mode: pop token' - racc_print_states state - racc_print_stacks tstack, vstack - @racc_debug_out.puts - end + def racc_next_state(curstate, state) + @racc_debug_out.puts "goto #{curstate}" + racc_print_states state + @racc_debug_out.puts + end - def racc_next_state(curstate, state) - @racc_debug_out.puts "goto #{curstate}" - racc_print_states state - @racc_debug_out.puts - end + def racc_print_stacks(t, v) + out = @racc_debug_out + out.print ' [' + t.each_index do |i| + out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')' + end + out.puts ' ]' + end - def racc_print_stacks(t, v) - out = @racc_debug_out - out.print ' [' - t.each_index do |i| - out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')' - end - out.puts ' ]' - end + def racc_print_states(s) + out = @racc_debug_out + out.print ' [' + s.each {|st| out.print ' ', st } + out.puts ' ]' + end - def racc_print_states(s) - out = @racc_debug_out - out.print ' [' - s.each {|st| out.print ' ', st } - out.puts ' ]' - end + def racc_token2str(tok) + self.class::Racc_token_to_s_table[tok] or + raise "[Racc Bug] can't convert token #{tok} to string" + end - def racc_token2str(tok) - self.class::Racc_token_to_s_table[tok] or - raise "[Racc Bug] can't convert token #{tok} to string" - end + def token_to_str(t) + self.class::Racc_token_to_s_table[t] + end - def token_to_str(t) - self.class::Racc_token_to_s_table[t] end - end - end ..end racc/parser.rb modeval..id5256434e8a end @@ -460,68 +459,68 @@ end module Nagios - class Parser < Racc::Parser + class Parser < Racc::Parser module_eval <<'..end grammar.ry modeval..idcb2ea30b34', 'grammar.ry', 57 class ::Nagios::Parser::SyntaxError < RuntimeError; end def parse(src) - @src = src + @src = src - # state variables - @invar = false - @inobject = false - @done = false + # state variables + @invar = false + @inobject = false + @done = false - @line = 0 - @yydebug = true + @line = 0 + @yydebug = true do_parse end # The lexer. Very simple. def token - @src.sub!(/\A\n/,'') - if $& - @line += 1 - return [ :RETURN, "\n" ] - end - - if @done - return nil - end - yytext = String.new - - - # remove comments from this line - @src.sub!(/\A[ \t]*;.*\n/,"\n") - if $& - return [:INLINECOMMENT, ""] - end - - @src.sub!(/\A#.*\n/,"\n") - if $& - return [:COMMENT, ""] - end - - @src.sub!(/#.*/,'') - - if @src.length == 0 - @done = true - return [false, '$'] - end - - if @invar - @src.sub!(/\A[ \t]+/,'') - @src.sub!(/\A([^;\n]+)(\n|;)/,'\2') - if $1 - yytext += $1 - end - @invar = false - return [:VALUE, yytext] - else - @src.sub!(/\A[\t ]*(\S+)([\t ]*|$)/,'') + @src.sub!(/\A\n/,'') + if $& + @line += 1 + return [ :RETURN, "\n" ] + end + + if @done + return nil + end + yytext = String.new + + + # remove comments from this line + @src.sub!(/\A[ \t]*;.*\n/,"\n") + if $& + return [:INLINECOMMENT, ""] + end + + @src.sub!(/\A#.*\n/,"\n") + if $& + return [:COMMENT, ""] + end + + @src.sub!(/#.*/,'') + + if @src.length == 0 + @done = true + return [false, '$'] + end + + if @invar + @src.sub!(/\A[ \t]+/,'') + @src.sub!(/\A([^;\n]+)(\n|;)/,'\2') + if $1 + yytext += $1 + end + @invar = false + return [:VALUE, yytext] + else + @src.sub!(/\A[\t ]*(\S+)([\t ]*|$)/,'') if $1 yytext = $1 case yytext @@ -561,11 +560,11 @@ def token end end end - end + end end def next_token - token + token end def yydebug @@ -577,109 +576,105 @@ def yywrap end def on_error(token, value, vstack ) - msg = "" - unless value.nil? - msg = "line #{@line}: syntax error at '#{value}'" - else - msg = "line #{@line}: syntax error at '#{token}'" - end - unless @src.size > 0 - msg = "line #{@line}: Unexpected end of file" - end - if token == '$end'.intern - puts "okay, this is silly" - else - raise ::Nagios::Parser::SyntaxError, msg - end + msg = "" + unless value.nil? + msg = "line #{@line}: syntax error at '#{value}'" + else + msg = "line #{@line}: syntax error at '#{token}'" + end + unless @src.size > 0 + msg = "line #{@line}: Unexpected end of file" + end + if token == '$end'.intern + puts "okay, this is silly" + else + raise ::Nagios::Parser::SyntaxError, msg + end end ..end grammar.ry modeval..idcb2ea30b34 ##### racc 1.4.5 generates ### racc_reduce_table = [ - 0, 0, :racc_error, - 1, 13, :_reduce_1, - 2, 13, :_reduce_2, - 1, 14, :_reduce_3, - 1, 14, :_reduce_4, - 1, 14, :_reduce_none, - 2, 16, :_reduce_6, - 6, 15, :_reduce_7, - 1, 17, :_reduce_none, - 2, 17, :_reduce_9, - 4, 18, :_reduce_10, - 1, 20, :_reduce_none, - 2, 20, :_reduce_none, - 0, 19, :_reduce_none, - 1, 19, :_reduce_none ] + 0, 0, :racc_error, + 1, 13, :_reduce_1, + 2, 13, :_reduce_2, + 1, 14, :_reduce_3, + 1, 14, :_reduce_4, + 1, 14, :_reduce_none, + 2, 16, :_reduce_6, + 6, 15, :_reduce_7, + 1, 17, :_reduce_none, + 2, 17, :_reduce_9, + 4, 18, :_reduce_10, + 1, 20, :_reduce_none, + 2, 20, :_reduce_none, + 0, 19, :_reduce_none, + 1, 19, :_reduce_none ] racc_reduce_n = 15 racc_shift_n = 26 racc_action_table = [ - 9, 15, 1, 20, 1, 14, 12, 13, 11, 6, - 7, 6, 7, 15, 18, 8, 21, 23, 25 ] + 9, 15, 1, 20, 1, 14, 12, 13, 11, 6, + 7, 6, 7, 15, 18, 8, 21, 23, 25 ] racc_action_check = [ - 2, 16, 2, 16, 0, 12, 8, 9, 7, 2, - 2, 0, 0, 14, 15, 1, 18, 22, 24 ] + 2, 16, 2, 16, 0, 12, 8, 9, 7, 2, + 2, 0, 0, 14, 15, 1, 18, 22, 24 ] racc_action_pointer = [ - 2, 12, 0, nil, nil, nil, nil, -1, 0, 7, - nil, nil, -4, nil, 8, 6, -4, nil, 5, nil, - nil, nil, 8, nil, 9, nil ] + 2, 12, 0, nil, nil, nil, nil, -1, 0, 7, + nil, nil, -4, nil, 8, 6, -4, nil, 5, nil, + nil, nil, 8, nil, 9, nil ] racc_action_default = [ - -15, -15, -15, -1, -3, -5, -4, -15, -15, -15, + -15, -15, -15, -1, -3, -5, -4, -15, -15, -15, -2, -6, -15, 26, -15, -15, -15, -8, -13, -9, -7, -14, -15, -11, -10, -12 ] -racc_goto_table = [ - 17, 3, 19, 10, 2, 16, 22, 24 ] +racc_goto_table = [ 17, 3, 19, 10, 2, 16, 22, 24 ] -racc_goto_check = [ - 6, 2, 6, 2, 1, 5, 7, 8 ] +racc_goto_check = [ 6, 2, 6, 2, 1, 5, 7, 8 ] -racc_goto_pointer = [ - nil, 4, 1, nil, nil, -9, -14, -12, -15 ] +racc_goto_pointer = [ nil, 4, 1, nil, nil, -9, -14, -12, -15 ] -racc_goto_default = [ - nil, nil, nil, 4, 5, nil, nil, nil, nil ] +racc_goto_default = [ nil, nil, nil, 4, 5, nil, nil, nil, nil ] racc_token_table = { - false => 0, - Object.new => 1, - :DEFINE => 2, - :NAME => 3, - :STRING => 4, - :PARAM => 5, - :LCURLY => 6, - :RCURLY => 7, - :VALUE => 8, - :RETURN => 9, - :COMMENT => 10, - :INLINECOMMENT => 11 } + false => 0, + Object.new => 1, + :DEFINE => 2, + :NAME => 3, + :STRING => 4, + :PARAM => 5, + :LCURLY => 6, + :RCURLY => 7, + :VALUE => 8, + :RETURN => 9, + :COMMENT => 10, + :INLINECOMMENT => 11 } racc_use_result_var = true racc_nt_base = 12 Racc_arg = [ - racc_action_table, - racc_action_check, - racc_action_default, - racc_action_pointer, - racc_goto_table, - racc_goto_check, - racc_goto_default, - racc_goto_pointer, - racc_nt_base, - racc_reduce_table, - racc_token_table, - racc_shift_n, - racc_reduce_n, - racc_use_result_var ] + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] Racc_token_to_s_table = [ '$end', @@ -708,91 +703,91 @@ Racc_debug_parser = false ##### racc system variables end ##### - # reduce 0 omitted +# reduce 0 omitted module_eval <<'.,.,', 'grammar.ry', 6 - def _reduce_1( val, _values, result ) - return val[0] if val[0] - result - end + def _reduce_1( val, _values, result ) +return val[0] if val[0] + result +end .,., module_eval <<'.,.,', 'grammar.ry', 18 - def _reduce_2( val, _values, result ) - if val[1].nil? - result = val[0] - else - if val[0].nil? - result = val[1] - else - result = [ val[0], val[1] ].flatten - end - end - result - end + def _reduce_2( val, _values, result ) + if val[1].nil? + result = val[0] + else + if val[0].nil? + result = val[1] + else + result = [ val[0], val[1] ].flatten + end + end + result + end .,., module_eval <<'.,.,', 'grammar.ry', 20 - def _reduce_3( val, _values, result ) - result = [val[0]] - result - end + def _reduce_3( val, _values, result ) +result = [val[0]] + result +end .,., module_eval <<'.,.,', 'grammar.ry', 21 - def _reduce_4( val, _values, result ) - result = nil - result - end + def _reduce_4( val, _values, result ) +result = nil + result +end .,., - # reduce 5 omitted +# reduce 5 omitted module_eval <<'.,.,', 'grammar.ry', 25 - def _reduce_6( val, _values, result ) - result = nil - result - end + def _reduce_6( val, _values, result ) +result = nil + result +end .,., module_eval <<'.,.,', 'grammar.ry', 31 - def _reduce_7( val, _values, result ) - result = Nagios::Base.create(val[1],val[4]) - result - end + def _reduce_7( val, _values, result ) + result = Nagios::Base.create(val[1],val[4]) + result + end .,., - # reduce 8 omitted +# reduce 8 omitted module_eval <<'.,.,', 'grammar.ry', 40 - def _reduce_9( val, _values, result ) - val[1].each {|p,v| - val[0][p] = v - } - result = val[0] - result - end + def _reduce_9( val, _values, result ) + val[1].each {|p,v| + val[0][p] = v + } + result = val[0] + result + end .,., module_eval <<'.,.,', 'grammar.ry', 42 - def _reduce_10( val, _values, result ) - result = {val[0],val[1]} - result - end + def _reduce_10( val, _values, result ) +result = {val[0],val[1]} + result +end .,., - # reduce 11 omitted +# reduce 11 omitted - # reduce 12 omitted +# reduce 12 omitted - # reduce 13 omitted +# reduce 13 omitted - # reduce 14 omitted +# reduce 14 omitted - def _reduce_none( val, _values, result ) - result - end +def _reduce_none( val, _values, result ) + result +end - end # class Parser + end # class Parser end # module Nagios diff --git a/lib/puppet/external/pson/common.rb b/lib/puppet/external/pson/common.rb index 87bce988b..17da5ad11 100644 --- a/lib/puppet/external/pson/common.rb +++ b/lib/puppet/external/pson/common.rb @@ -1,367 +1,370 @@ require 'puppet/external/pson/version' module PSON - class << self - # If _object_ is string-like parse the string and return the parsed result - # as a Ruby data structure. Otherwise generate a PSON text from the Ruby - # data structure object and return it. - # - # The _opts_ argument is passed through to generate/parse respectively, see - # generate and parse for their documentation. - def [](object, opts = {}) - if object.respond_to? :to_str - PSON.parse(object.to_str, opts => {}) - else - PSON.generate(object, opts => {}) - end - end + class << self + # If _object_ is string-like parse the string and return the parsed result + # as a Ruby data structure. Otherwise generate a PSON text from the Ruby + # data structure object and return it. + # + # The _opts_ argument is passed through to generate/parse respectively, see + # generate and parse for their documentation. + def [](object, opts = {}) + if object.respond_to? :to_str + PSON.parse(object.to_str, opts => {}) + else + PSON.generate(object, opts => {}) + end + end - # Returns the PSON parser class, that is used by PSON. This might be either - # PSON::Ext::Parser or PSON::Pure::Parser. - attr_reader :parser + # Returns the PSON parser class, that is used by PSON. This might be either + # PSON::Ext::Parser or PSON::Pure::Parser. + attr_reader :parser - # Set the PSON parser class _parser_ to be used by PSON. - def parser=(parser) # :nodoc: - @parser = parser - remove_const :Parser if const_defined? :Parser - const_set :Parser, parser - end + # Set the PSON parser class _parser_ to be used by PSON. + def parser=(parser) # :nodoc: + @parser = parser + remove_const :Parser if const_defined? :Parser + const_set :Parser, parser + end + + def registered_document_types + @registered_document_types ||= {} + end + + # Register a class-constant for deserializaion. + def register_document_type(name,klass) + registered_document_types[name.to_s] = klass + end + + # Return the constant located at _path_. + # Anything may be registered as a path by calling register_path, above. + # Otherwise, the format of _path_ has to be either ::A::B::C or A::B::C. + # In either of these cases A has to be defined in Object (e.g. the path + # must be an absolute namespace path. If the constant doesn't exist at + # the given path, an ArgumentError is raised. + def deep_const_get(path) # :nodoc: + path = path.to_s + registered_document_types[path] || path.split(/::/).inject(Object) do |p, c| + case + when c.empty? then p + when p.const_defined?(c) then p.const_get(c) + else raise ArgumentError, "can't find const for unregistered document type #{path}" + end + end + end + + # Set the module _generator_ to be used by PSON. + def generator=(generator) # :nodoc: + @generator = generator + generator_methods = generator::GeneratorMethods + for const in generator_methods.constants + klass = deep_const_get(const) + modul = generator_methods.const_get(const) + klass.class_eval do + instance_methods(false).each do |m| + m.to_s == 'to_pson' and remove_method m + end + include modul + end + end + self.state = generator::State + const_set :State, self.state + end + + # Returns the PSON generator modul, that is used by PSON. This might be + # either PSON::Ext::Generator or PSON::Pure::Generator. + attr_reader :generator - def registered_document_types - @registered_document_types ||= {} + # Returns the PSON generator state class, that is used by PSON. This might + # be either PSON::Ext::Generator::State or PSON::Pure::Generator::State. + attr_accessor :state + + # This is create identifier, that is used to decide, if the _pson_create_ + # hook of a class should be called. It defaults to 'document_type'. + attr_accessor :create_id end + self.create_id = 'document_type' + + NaN = (-1.0) ** 0.5 + + Infinity = 1.0/0 + + MinusInfinity = -Infinity + + # The base exception for PSON errors. + class PSONError < StandardError; end + + # This exception is raised, if a parser error occurs. + class ParserError < PSONError; end + + # This exception is raised, if the nesting of parsed datastructures is too + # deep. + class NestingError < ParserError; end + + # This exception is raised, if a generator or unparser error occurs. + class GeneratorError < PSONError; end + # For backwards compatibility + UnparserError = GeneratorError - # Register a class-constant for deserializaion. - def register_document_type(name,klass) - registered_document_types[name.to_s] = klass + # If a circular data structure is encountered while unparsing + # this exception is raised. + class CircularDatastructure < GeneratorError; end + + # This exception is raised, if the required unicode support is missing on the + # system. Usually this means, that the iconv library is not installed. + class MissingUnicodeSupport < PSONError; end + + module_function + + # Parse the PSON string _source_ into a Ruby data structure and return it. + # + # _opts_ can have the following + # keys: + # * *max_nesting*: The maximum depth of nesting allowed in the parsed data + # structures. Disable depth checking with :max_nesting => false, it defaults + # to 19. + # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in + # defiance of RFC 4627 to be parsed by the Parser. This option defaults + # to false. + # * *create_additions*: If set to false, the Parser doesn't create + # additions even if a matchin class and create_id was found. This option + # defaults to true. + def parse(source, opts = {}) + PSON.parser.new(source, opts).parse end - # Return the constant located at _path_. - # Anything may be registered as a path by calling register_path, above. - # Otherwise, the format of _path_ has to be either ::A::B::C or A::B::C. - # In either of these cases A has to be defined in Object (e.g. the path - # must be an absolute namespace path. If the constant doesn't exist at - # the given path, an ArgumentError is raised. - def deep_const_get(path) # :nodoc: - path = path.to_s - registered_document_types[path] || path.split(/::/).inject(Object) do |p, c| - case - when c.empty? then p - when p.const_defined?(c) then p.const_get(c) - else raise ArgumentError, "can't find const for unregistered document type #{path}" - end - end + # Parse the PSON string _source_ into a Ruby data structure and return it. + # The bang version of the parse method, defaults to the more dangerous values + # for the _opts_ hash, so be sure only to parse trusted _source_ strings. + # + # _opts_ can have the following keys: + # * *max_nesting*: The maximum depth of nesting allowed in the parsed data + # structures. Enable depth checking with :max_nesting => anInteger. The parse! + # methods defaults to not doing max depth checking: This can be dangerous, + # if someone wants to fill up your stack. + # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in + # defiance of RFC 4627 to be parsed by the Parser. This option defaults + # to true. + # * *create_additions*: If set to false, the Parser doesn't create + # additions even if a matchin class and create_id was found. This option + # defaults to true. + def parse!(source, opts = {}) + opts = { + :max_nesting => false, + :allow_nan => true + }.update(opts) + PSON.parser.new(source, opts).parse end - # Set the module _generator_ to be used by PSON. - def generator=(generator) # :nodoc: - @generator = generator - generator_methods = generator::GeneratorMethods - for const in generator_methods.constants - klass = deep_const_get(const) - modul = generator_methods.const_get(const) - klass.class_eval do - instance_methods(false).each do |m| - m.to_s == 'to_pson' and remove_method m - end - include modul + # Unparse the Ruby data structure _obj_ into a single line PSON string and + # return it. _state_ is + # * a PSON::State object, + # * or a Hash like object (responding to to_hash), + # * an object convertible into a hash by a to_h method, + # that is used as or to configure a State object. + # + # It defaults to a state object, that creates the shortest possible PSON text + # in one line, checks for circular data structures and doesn't allow NaN, + # Infinity, and -Infinity. + # + # A _state_ hash can have the following keys: + # * *indent*: a string used to indent levels (default: ''), + # * *space*: a string that is put after, a : or , delimiter (default: ''), + # * *space_before*: a string that is put before a : pair delimiter (default: ''), + # * *object_nl*: a string that is put at the end of a PSON object (default: ''), + # * *array_nl*: a string that is put at the end of a PSON array (default: ''), + # * *check_circular*: true if checking for circular data structures + # should be done (the default), false otherwise. + # * *allow_nan*: true if NaN, Infinity, and -Infinity should be + # generated, otherwise an exception is thrown, if these values are + # encountered. This options defaults to false. + # * *max_nesting*: The maximum depth of nesting allowed in the data + # structures from which PSON is to be generated. Disable depth checking + # with :max_nesting => false, it defaults to 19. + # + # See also the fast_generate for the fastest creation method with the least + # amount of sanity checks, and the pretty_generate method for some + # defaults for a pretty output. + def generate(obj, state = nil) + if state + state = State.from_state(state) + else + state = State.new end - end - self.state = generator::State - const_set :State, self.state + obj.to_pson(state) end - # Returns the PSON generator modul, that is used by PSON. This might be - # either PSON::Ext::Generator or PSON::Pure::Generator. - attr_reader :generator - - # Returns the PSON generator state class, that is used by PSON. This might - # be either PSON::Ext::Generator::State or PSON::Pure::Generator::State. - attr_accessor :state - - # This is create identifier, that is used to decide, if the _pson_create_ - # hook of a class should be called. It defaults to 'document_type'. - attr_accessor :create_id - end - self.create_id = 'document_type' - - NaN = (-1.0) ** 0.5 - - Infinity = 1.0/0 - - MinusInfinity = -Infinity - - # The base exception for PSON errors. - class PSONError < StandardError; end - - # This exception is raised, if a parser error occurs. - class ParserError < PSONError; end - - # This exception is raised, if the nesting of parsed datastructures is too - # deep. - class NestingError < ParserError; end - - # This exception is raised, if a generator or unparser error occurs. - class GeneratorError < PSONError; end - # For backwards compatibility - UnparserError = GeneratorError - - # If a circular data structure is encountered while unparsing - # this exception is raised. - class CircularDatastructure < GeneratorError; end - - # This exception is raised, if the required unicode support is missing on the - # system. Usually this means, that the iconv library is not installed. - class MissingUnicodeSupport < PSONError; end - - module_function - - # Parse the PSON string _source_ into a Ruby data structure and return it. - # - # _opts_ can have the following - # keys: - # * *max_nesting*: The maximum depth of nesting allowed in the parsed data - # structures. Disable depth checking with :max_nesting => false, it defaults - # to 19. - # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in - # defiance of RFC 4627 to be parsed by the Parser. This option defaults - # to false. - # * *create_additions*: If set to false, the Parser doesn't create - # additions even if a matchin class and create_id was found. This option - # defaults to true. - def parse(source, opts = {}) - PSON.parser.new(source, opts).parse - end - - # Parse the PSON string _source_ into a Ruby data structure and return it. - # The bang version of the parse method, defaults to the more dangerous values - # for the _opts_ hash, so be sure only to parse trusted _source_ strings. - # - # _opts_ can have the following keys: - # * *max_nesting*: The maximum depth of nesting allowed in the parsed data - # structures. Enable depth checking with :max_nesting => anInteger. The parse! - # methods defaults to not doing max depth checking: This can be dangerous, - # if someone wants to fill up your stack. - # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in - # defiance of RFC 4627 to be parsed by the Parser. This option defaults - # to true. - # * *create_additions*: If set to false, the Parser doesn't create - # additions even if a matchin class and create_id was found. This option - # defaults to true. - def parse!(source, opts = {}) - opts = { - :max_nesting => false, - :allow_nan => true - }.update(opts) - PSON.parser.new(source, opts).parse - end - - # Unparse the Ruby data structure _obj_ into a single line PSON string and - # return it. _state_ is - # * a PSON::State object, - # * or a Hash like object (responding to to_hash), - # * an object convertible into a hash by a to_h method, - # that is used as or to configure a State object. - # - # It defaults to a state object, that creates the shortest possible PSON text - # in one line, checks for circular data structures and doesn't allow NaN, - # Infinity, and -Infinity. - # - # A _state_ hash can have the following keys: - # * *indent*: a string used to indent levels (default: ''), - # * *space*: a string that is put after, a : or , delimiter (default: ''), - # * *space_before*: a string that is put before a : pair delimiter (default: ''), - # * *object_nl*: a string that is put at the end of a PSON object (default: ''), - # * *array_nl*: a string that is put at the end of a PSON array (default: ''), - # * *check_circular*: true if checking for circular data structures - # should be done (the default), false otherwise. - # * *allow_nan*: true if NaN, Infinity, and -Infinity should be - # generated, otherwise an exception is thrown, if these values are - # encountered. This options defaults to false. - # * *max_nesting*: The maximum depth of nesting allowed in the data - # structures from which PSON is to be generated. Disable depth checking - # with :max_nesting => false, it defaults to 19. - # - # See also the fast_generate for the fastest creation method with the least - # amount of sanity checks, and the pretty_generate method for some - # defaults for a pretty output. - def generate(obj, state = nil) - if state - state = State.from_state(state) - else - state = State.new - end - obj.to_pson(state) - end - - # :stopdoc: - # I want to deprecate these later, so I'll first be silent about them, and - # later delete them. - alias unparse generate - module_function :unparse - # :startdoc: - - # Unparse the Ruby data structure _obj_ into a single line PSON string and - # return it. This method disables the checks for circles in Ruby objects, and - # also generates NaN, Infinity, and, -Infinity float values. - # - # *WARNING*: Be careful not to pass any Ruby data structures with circles as - # _obj_ argument, because this will cause PSON to go into an infinite loop. - def fast_generate(obj) - obj.to_pson(nil) - end - - # :stopdoc: - # I want to deprecate these later, so I'll first be silent about them, and later delete them. - alias fast_unparse fast_generate - module_function :fast_unparse - # :startdoc: - - # Unparse the Ruby data structure _obj_ into a PSON string and return it. The - # returned string is a prettier form of the string returned by #unparse. - # - # The _opts_ argument can be used to configure the generator, see the - # generate method for a more detailed explanation. - def pretty_generate(obj, opts = nil) - state = PSON.state.new( - :indent => ' ', - :space => ' ', - :object_nl => "\n", - :array_nl => "\n", - :check_circular => true - ) - if opts - if opts.respond_to? :to_hash - opts = opts.to_hash - elsif opts.respond_to? :to_h - opts = opts.to_h - else - raise TypeError, "can't convert #{opts.class} into Hash" - end - state.configure(opts) + # :stopdoc: + # I want to deprecate these later, so I'll first be silent about them, and + # later delete them. + alias unparse generate + module_function :unparse + # :startdoc: + + # Unparse the Ruby data structure _obj_ into a single line PSON string and + # return it. This method disables the checks for circles in Ruby objects, and + # also generates NaN, Infinity, and, -Infinity float values. + # + # *WARNING*: Be careful not to pass any Ruby data structures with circles as + # _obj_ argument, because this will cause PSON to go into an infinite loop. + def fast_generate(obj) + obj.to_pson(nil) end - obj.to_pson(state) - end - - # :stopdoc: - # I want to deprecate these later, so I'll first be silent about them, and later delete them. - alias pretty_unparse pretty_generate - module_function :pretty_unparse - # :startdoc: - - # Load a ruby data structure from a PSON _source_ and return it. A source can - # either be a string-like object, an IO like object, or an object responding - # to the read method. If _proc_ was given, it will be called with any nested - # Ruby object as an argument recursively in depth first order. - # - # This method is part of the implementation of the load/dump interface of - # Marshal and YAML. - def load(source, proc = nil) - if source.respond_to? :to_str - source = source.to_str - elsif source.respond_to? :to_io - source = source.to_io.read - else - source = source.read + + # :stopdoc: + # I want to deprecate these later, so I'll first be silent about them, and later delete them. + alias fast_unparse fast_generate + module_function :fast_unparse + # :startdoc: + + # Unparse the Ruby data structure _obj_ into a PSON string and return it. The + # returned string is a prettier form of the string returned by #unparse. + # + # The _opts_ argument can be used to configure the generator, see the + # generate method for a more detailed explanation. + def pretty_generate(obj, opts = nil) + + state = PSON.state.new( + + :indent => ' ', + :space => ' ', + :object_nl => "\n", + :array_nl => "\n", + + :check_circular => true + ) + if opts + if opts.respond_to? :to_hash + opts = opts.to_hash + elsif opts.respond_to? :to_h + opts = opts.to_h + else + raise TypeError, "can't convert #{opts.class} into Hash" + end + state.configure(opts) + end + obj.to_pson(state) end - result = parse(source, :max_nesting => false, :allow_nan => true) - recurse_proc(result, &proc) if proc - result - end - - def recurse_proc(result, &proc) - case result - when Array - result.each { |x| recurse_proc x, &proc } - proc.call result - when Hash - result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc } - proc.call result - else - proc.call result + + # :stopdoc: + # I want to deprecate these later, so I'll first be silent about them, and later delete them. + alias pretty_unparse pretty_generate + module_function :pretty_unparse + # :startdoc: + + # Load a ruby data structure from a PSON _source_ and return it. A source can + # either be a string-like object, an IO like object, or an object responding + # to the read method. If _proc_ was given, it will be called with any nested + # Ruby object as an argument recursively in depth first order. + # + # This method is part of the implementation of the load/dump interface of + # Marshal and YAML. + def load(source, proc = nil) + if source.respond_to? :to_str + source = source.to_str + elsif source.respond_to? :to_io + source = source.to_io.read + else + source = source.read + end + result = parse(source, :max_nesting => false, :allow_nan => true) + recurse_proc(result, &proc) if proc + result end - end - private :recurse_proc - module_function :recurse_proc - - alias restore load - module_function :restore - - # Dumps _obj_ as a PSON string, i.e. calls generate on the object and returns - # the result. - # - # If anIO (an IO like object or an object that responds to the write method) - # was given, the resulting PSON is written to it. - # - # If the number of nested arrays or objects exceeds _limit_ an ArgumentError - # exception is raised. This argument is similar (but not exactly the - # same!) to the _limit_ argument in Marshal.dump. - # - # This method is part of the implementation of the load/dump interface of - # Marshal and YAML. - def dump(obj, anIO = nil, limit = nil) - if anIO and limit.nil? - anIO = anIO.to_io if anIO.respond_to?(:to_io) - unless anIO.respond_to?(:write) - limit = anIO - anIO = nil - end + + def recurse_proc(result, &proc) + case result + when Array + result.each { |x| recurse_proc x, &proc } + proc.call result + when Hash + result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc } + proc.call result + else + proc.call result + end end - limit ||= 0 - result = generate(obj, :allow_nan => true, :max_nesting => limit) - if anIO - anIO.write result - anIO - else - result + private :recurse_proc + module_function :recurse_proc + + alias restore load + module_function :restore + + # Dumps _obj_ as a PSON string, i.e. calls generate on the object and returns + # the result. + # + # If anIO (an IO like object or an object that responds to the write method) + # was given, the resulting PSON is written to it. + # + # If the number of nested arrays or objects exceeds _limit_ an ArgumentError + # exception is raised. This argument is similar (but not exactly the + # same!) to the _limit_ argument in Marshal.dump. + # + # This method is part of the implementation of the load/dump interface of + # Marshal and YAML. + def dump(obj, anIO = nil, limit = nil) + if anIO and limit.nil? + anIO = anIO.to_io if anIO.respond_to?(:to_io) + unless anIO.respond_to?(:write) + limit = anIO + anIO = nil + end + end + limit ||= 0 + result = generate(obj, :allow_nan => true, :max_nesting => limit) + if anIO + anIO.write result + anIO + else + result + end + rescue PSON::NestingError + raise ArgumentError, "exceed depth limit" end - rescue PSON::NestingError - raise ArgumentError, "exceed depth limit" - end end module ::Kernel - private + private - # Outputs _objs_ to STDOUT as PSON strings in the shortest form, that is in - # one line. - def j(*objs) - objs.each do |obj| - puts PSON::generate(obj, :allow_nan => true, :max_nesting => false) + # Outputs _objs_ to STDOUT as PSON strings in the shortest form, that is in + # one line. + def j(*objs) + objs.each do |obj| + puts PSON::generate(obj, :allow_nan => true, :max_nesting => false) + end + nil end - nil - end - - # Ouputs _objs_ to STDOUT as PSON strings in a pretty format, with - # indentation and over many lines. - def jj(*objs) - objs.each do |obj| - puts PSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false) + + # Ouputs _objs_ to STDOUT as PSON strings in a pretty format, with + # indentation and over many lines. + def jj(*objs) + objs.each do |obj| + puts PSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false) + end + nil end - nil - end - - # If _object_ is string-like parse the string and return the parsed result as - # a Ruby data structure. Otherwise generate a PSON text from the Ruby data - # structure object and return it. - # - # The _opts_ argument is passed through to generate/parse respectively, see - # generate and parse for their documentation. - def PSON(object, opts = {}) - if object.respond_to? :to_str - PSON.parse(object.to_str, opts) - else - PSON.generate(object, opts) + + # If _object_ is string-like parse the string and return the parsed result as + # a Ruby data structure. Otherwise generate a PSON text from the Ruby data + # structure object and return it. + # + # The _opts_ argument is passed through to generate/parse respectively, see + # generate and parse for their documentation. + def PSON(object, opts = {}) + if object.respond_to? :to_str + PSON.parse(object.to_str, opts) + else + PSON.generate(object, opts) + end end - end end class ::Class - # Returns true, if this class can be used to create an instance - # from a serialised PSON string. The class has to implement a class - # method _pson_create_ that expects a hash as first parameter, which includes - # the required data. - def pson_creatable? - respond_to?(:pson_create) - end + # Returns true, if this class can be used to create an instance + # from a serialised PSON string. The class has to implement a class + # method _pson_create_ that expects a hash as first parameter, which includes + # the required data. + def pson_creatable? + respond_to?(:pson_create) + end end diff --git a/lib/puppet/external/pson/pure.rb b/lib/puppet/external/pson/pure.rb index 53d1ea2a7..dffd06d92 100644 --- a/lib/puppet/external/pson/pure.rb +++ b/lib/puppet/external/pson/pure.rb @@ -3,75 +3,75 @@ require 'puppet/external/pson/pure/parser' require 'puppet/external/pson/pure/generator' module PSON - begin - require 'iconv' - # An iconv instance to convert from UTF8 to UTF16 Big Endian. - UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be') # :nodoc: - # An iconv instance to convert from UTF16 Big Endian to UTF8. - UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc: - UTF8toUTF16.iconv('no bom') - rescue LoadError - # We actually don't care - Puppet.warning "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions" - rescue Errno::EINVAL, Iconv::InvalidEncoding - # Iconv doesn't support big endian utf-16. Let's try to hack this manually - # into the converters. begin - old_verbose, $VERBSOSE = $VERBOSE, nil - # An iconv instance to convert from UTF8 to UTF16 Big Endian. - UTF16toUTF8 = Iconv.new('utf-8', 'utf-16') # :nodoc: - # An iconv instance to convert from UTF16 Big Endian to UTF8. - UTF8toUTF16 = Iconv.new('utf-16', 'utf-8') # :nodoc: - UTF8toUTF16.iconv('no bom') - if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20" - swapper = Class.new do - def initialize(iconv) # :nodoc: - @iconv = iconv - end + require 'iconv' + # An iconv instance to convert from UTF8 to UTF16 Big Endian. + UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be') # :nodoc: + # An iconv instance to convert from UTF16 Big Endian to UTF8. + UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc: + UTF8toUTF16.iconv('no bom') + rescue LoadError + # We actually don't care + Puppet.warning "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions" + rescue Errno::EINVAL, Iconv::InvalidEncoding + # Iconv doesn't support big endian utf-16. Let's try to hack this manually + # into the converters. + begin + old_verbose, $VERBSOSE = $VERBOSE, nil + # An iconv instance to convert from UTF8 to UTF16 Big Endian. + UTF16toUTF8 = Iconv.new('utf-8', 'utf-16') # :nodoc: + # An iconv instance to convert from UTF16 Big Endian to UTF8. + UTF8toUTF16 = Iconv.new('utf-16', 'utf-8') # :nodoc: + UTF8toUTF16.iconv('no bom') + if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20" + swapper = Class.new do + def initialize(iconv) # :nodoc: + @iconv = iconv + end - def iconv(string) # :nodoc: - result = @iconv.iconv(string) - PSON.swap!(result) - end - end - UTF8toUTF16 = swapper.new(UTF8toUTF16) # :nodoc: - end - if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac" - swapper = Class.new do - def initialize(iconv) # :nodoc: - @iconv = iconv - end + def iconv(string) # :nodoc: + result = @iconv.iconv(string) + PSON.swap!(result) + end + end + UTF8toUTF16 = swapper.new(UTF8toUTF16) # :nodoc: + end + if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac" + swapper = Class.new do + def initialize(iconv) # :nodoc: + @iconv = iconv + end - def iconv(string) # :nodoc: - string = PSON.swap!(string.dup) - @iconv.iconv(string) - end + def iconv(string) # :nodoc: + string = PSON.swap!(string.dup) + @iconv.iconv(string) + end + end + UTF16toUTF8 = swapper.new(UTF16toUTF8) # :nodoc: + end + rescue Errno::EINVAL, Iconv::InvalidEncoding + Puppet.warning "iconv doesn't seem to support UTF-8/UTF-16 conversions" + ensure + $VERBOSE = old_verbose end - UTF16toUTF8 = swapper.new(UTF16toUTF8) # :nodoc: - end - rescue Errno::EINVAL, Iconv::InvalidEncoding - Puppet.warning "iconv doesn't seem to support UTF-8/UTF-16 conversions" - ensure - $VERBOSE = old_verbose end - end - # Swap consecutive bytes of _string_ in place. - def self.swap!(string) # :nodoc: - 0.upto(string.size / 2) do |i| - break unless string[2 * i + 1] - string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i] + # Swap consecutive bytes of _string_ in place. + def self.swap!(string) # :nodoc: + 0.upto(string.size / 2) do |i| + break unless string[2 * i + 1] + string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i] + end + string end - string - end - # This module holds all the modules/classes that implement PSON's - # functionality in pure ruby. - module Pure - $DEBUG and warn "Using pure library for PSON." - PSON.parser = Parser - PSON.generator = Generator - end + # This module holds all the modules/classes that implement PSON's + # functionality in pure ruby. + module Pure + $DEBUG and warn "Using pure library for PSON." + PSON.parser = Parser + PSON.generator = Generator + end - PSON_LOADED = true + PSON_LOADED = true end diff --git a/lib/puppet/external/pson/pure/generator.rb b/lib/puppet/external/pson/pure/generator.rb index b2a7ddeb5..44aa526c7 100644 --- a/lib/puppet/external/pson/pure/generator.rb +++ b/lib/puppet/external/pson/pure/generator.rb @@ -1,429 +1,429 @@ module PSON - MAP = { - "\x0" => '\u0000', - "\x1" => '\u0001', - "\x2" => '\u0002', - "\x3" => '\u0003', - "\x4" => '\u0004', - "\x5" => '\u0005', - "\x6" => '\u0006', - "\x7" => '\u0007', - "\b" => '\b', - "\t" => '\t', - "\n" => '\n', - "\xb" => '\u000b', - "\f" => '\f', - "\r" => '\r', - "\xe" => '\u000e', - "\xf" => '\u000f', - "\x10" => '\u0010', - "\x11" => '\u0011', - "\x12" => '\u0012', - "\x13" => '\u0013', - "\x14" => '\u0014', - "\x15" => '\u0015', - "\x16" => '\u0016', - "\x17" => '\u0017', - "\x18" => '\u0018', - "\x19" => '\u0019', - "\x1a" => '\u001a', - "\x1b" => '\u001b', - "\x1c" => '\u001c', - "\x1d" => '\u001d', - "\x1e" => '\u001e', - "\x1f" => '\u001f', - '"' => '\"', - '\\' => '\\\\', - } # :nodoc: - - # Convert a UTF8 encoded Ruby string _string_ to a PSON string, encoded with - # UTF16 big endian characters as \u????, and return it. - if String.method_defined?(:force_encoding) - def utf8_to_pson(string) # :nodoc: - string = string.dup - string << '' # XXX workaround: avoid buffer sharing - string.force_encoding(Encoding::ASCII_8BIT) - string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] } - string.gsub!(/( - (?: - [\xc2-\xdf][\x80-\xbf] | - [\xe0-\xef][\x80-\xbf]{2} | - [\xf0-\xf4][\x80-\xbf]{3} - )+ | - [\x80-\xc1\xf5-\xff] # invalid - )/nx) { |c| - c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" - s = PSON::UTF8toUTF16.iconv(c).unpack('H*')[0] - s.gsub!(/.{4}/n, '\\\\u\&') - } - string.force_encoding(Encoding::UTF_8) - string - rescue Iconv::Failure => e - raise GeneratorError, "Caught #{e.class}: #{e}" - end - else - def utf8_to_pson(string) # :nodoc: - string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] } - string.gsub!(/( - (?: - [\xc2-\xdf][\x80-\xbf] | - [\xe0-\xef][\x80-\xbf]{2} | - [\xf0-\xf4][\x80-\xbf]{3} - )+ | - [\x80-\xc1\xf5-\xff] # invalid - )/nx) { |c| - c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" - s = PSON::UTF8toUTF16.iconv(c).unpack('H*')[0] - s.gsub!(/.{4}/n, '\\\\u\&') - } - string - rescue Iconv::Failure => e - raise GeneratorError, "Caught #{e.class}: #{e}" - end - end - module_function :utf8_to_pson - - module Pure - module Generator - # This class is used to create State instances, that are use to hold data - # while generating a PSON text from a a Ruby data structure. - class State - # Creates a State object from _opts_, which ought to be Hash to create - # a new State instance configured by _opts_, something else to create - # an unconfigured instance. If _opts_ is a State object, it is just - # returned. - def self.from_state(opts) - case opts - when self - opts - when Hash - new(opts) - else - new - end - end - - # Instantiates a new State object, configured by _opts_. - # - # _opts_ can have the following keys: - # - # * *indent*: a string used to indent levels (default: ''), - # * *space*: a string that is put after, a : or , delimiter (default: ''), - # * *space_before*: a string that is put before a : pair delimiter (default: ''), - # * *object_nl*: a string that is put at the end of a PSON object (default: ''), - # * *array_nl*: a string that is put at the end of a PSON array (default: ''), - # * *check_circular*: true if checking for circular data structures - # should be done (the default), false otherwise. - # * *check_circular*: true if checking for circular data structures - # should be done, false (the default) otherwise. - # * *allow_nan*: true if NaN, Infinity, and -Infinity should be - # generated, otherwise an exception is thrown, if these values are - # encountered. This options defaults to false. - def initialize(opts = {}) - @seen = {} - @indent = '' - @space = '' - @space_before = '' - @object_nl = '' - @array_nl = '' - @check_circular = true - @allow_nan = false - configure opts - end - - # This string is used to indent levels in the PSON text. - attr_accessor :indent - - # This string is used to insert a space between the tokens in a PSON - # string. - attr_accessor :space - - # This string is used to insert a space before the ':' in PSON objects. - attr_accessor :space_before - - # This string is put at the end of a line that holds a PSON object (or - # Hash). - attr_accessor :object_nl - - # This string is put at the end of a line that holds a PSON array. - attr_accessor :array_nl - - # This integer returns the maximum level of data structure nesting in - # the generated PSON, max_nesting = 0 if no maximum is checked. - attr_accessor :max_nesting - - def check_max_nesting(depth) # :nodoc: - return if @max_nesting.zero? - current_nesting = depth + 1 - current_nesting > @max_nesting and - raise NestingError, "nesting of #{current_nesting} is too deep" - end - - # Returns true, if circular data structures should be checked, - # otherwise returns false. - def check_circular? - @check_circular - end - - # Returns true if NaN, Infinity, and -Infinity should be considered as - # valid PSON and output. - def allow_nan? - @allow_nan - end - - # Returns _true_, if _object_ was already seen during this generating - # run. - def seen?(object) - @seen.key?(object.__id__) - end - - # Remember _object_, to find out if it was already encountered (if a - # cyclic data structure is if a cyclic data structure is rendered). - def remember(object) - @seen[object.__id__] = true - end - - # Forget _object_ for this generating run. - def forget(object) - @seen.delete object.__id__ - end - - # Configure this State instance with the Hash _opts_, and return - # itself. - def configure(opts) - @indent = opts[:indent] if opts.key?(:indent) - @space = opts[:space] if opts.key?(:space) - @space_before = opts[:space_before] if opts.key?(:space_before) - @object_nl = opts[:object_nl] if opts.key?(:object_nl) - @array_nl = opts[:array_nl] if opts.key?(:array_nl) - @check_circular = !!opts[:check_circular] if opts.key?(:check_circular) - @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan) - if !opts.key?(:max_nesting) # defaults to 19 - @max_nesting = 19 - elsif opts[:max_nesting] - @max_nesting = opts[:max_nesting] - else - @max_nesting = 0 - end - self - end - - # Returns the configuration instance variables as a hash, that can be - # passed to the configure method. - def to_h - result = {} - for iv in %w[indent space space_before object_nl array_nl check_circular allow_nan max_nesting] - result[iv.intern] = instance_variable_get("@#{iv}") - end - result - end - end - - module GeneratorMethods - module Object - # Converts this object to a string (calling #to_s), converts - # it to a PSON string, and returns the result. This is a fallback, if no - # special method #to_pson was defined for some object. - def to_pson(*) to_s.to_pson end + MAP = { + "\x0" => '\u0000', + "\x1" => '\u0001', + "\x2" => '\u0002', + "\x3" => '\u0003', + "\x4" => '\u0004', + "\x5" => '\u0005', + "\x6" => '\u0006', + "\x7" => '\u0007', + "\b" => '\b', + "\t" => '\t', + "\n" => '\n', + "\xb" => '\u000b', + "\f" => '\f', + "\r" => '\r', + "\xe" => '\u000e', + "\xf" => '\u000f', + "\x10" => '\u0010', + "\x11" => '\u0011', + "\x12" => '\u0012', + "\x13" => '\u0013', + "\x14" => '\u0014', + "\x15" => '\u0015', + "\x16" => '\u0016', + "\x17" => '\u0017', + "\x18" => '\u0018', + "\x19" => '\u0019', + "\x1a" => '\u001a', + "\x1b" => '\u001b', + "\x1c" => '\u001c', + "\x1d" => '\u001d', + "\x1e" => '\u001e', + "\x1f" => '\u001f', + '"' => '\"', + '\\' => '\\\\', + } # :nodoc: + + # Convert a UTF8 encoded Ruby string _string_ to a PSON string, encoded with + # UTF16 big endian characters as \u????, and return it. + if String.method_defined?(:force_encoding) + def utf8_to_pson(string) # :nodoc: + string = string.dup + string << '' # XXX workaround: avoid buffer sharing + string.force_encoding(Encoding::ASCII_8BIT) + string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] } + string.gsub!(/( + (?: + [\xc2-\xdf][\x80-\xbf] | + [\xe0-\xef][\x80-\xbf]{2} | + [\xf0-\xf4][\x80-\xbf]{3} + )+ | + [\x80-\xc1\xf5-\xff] # invalid + )/nx) { |c| + c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" + s = PSON::UTF8toUTF16.iconv(c).unpack('H*')[0] + s.gsub!(/.{4}/n, '\\\\u\&') + } + string.force_encoding(Encoding::UTF_8) + string + rescue Iconv::Failure => e + raise GeneratorError, "Caught #{e.class}: #{e}" end - - module Hash - # Returns a PSON string containing a PSON object, that is unparsed from - # this Hash instance. - # _state_ is a PSON::State object, that can also be used to configure the - # produced PSON string output further. - # _depth_ is used to find out nesting depth, to indent accordingly. - def to_pson(state = nil, depth = 0, *) - if state - state = PSON.state.from_state(state) - state.check_max_nesting(depth) - pson_check_circular(state) { pson_transform(state, depth) } - else - pson_transform(state, depth) - end - end - - private - - def pson_check_circular(state) - if state and state.check_circular? - state.seen?(self) and raise PSON::CircularDatastructure, - "circular data structures not supported!" - state.remember self - end - yield - ensure - state and state.forget self - end - - def pson_shift(state, depth) - state and not state.object_nl.empty? or return '' - state.indent * depth - end - - def pson_transform(state, depth) - delim = ',' - if state - delim << state.object_nl - result = '{' - result << state.object_nl - result << map { |key,value| - s = pson_shift(state, depth + 1) - s << key.to_s.to_pson(state, depth + 1) - s << state.space_before - s << ':' - s << state.space - s << value.to_pson(state, depth + 1) - }.join(delim) - result << state.object_nl - result << pson_shift(state, depth) - result << '}' - else - result = '{' - result << map { |key,value| - key.to_s.to_pson << ':' << value.to_pson - }.join(delim) - result << '}' - end - result - end - end - - module Array - # Returns a PSON string containing a PSON array, that is unparsed from - # this Array instance. - # _state_ is a PSON::State object, that can also be used to configure the - # produced PSON string output further. - # _depth_ is used to find out nesting depth, to indent accordingly. - def to_pson(state = nil, depth = 0, *) - if state - state = PSON.state.from_state(state) - state.check_max_nesting(depth) - pson_check_circular(state) { pson_transform(state, depth) } - else - pson_transform(state, depth) - end - end - - private - - def pson_check_circular(state) - if state and state.check_circular? - state.seen?(self) and raise PSON::CircularDatastructure, - "circular data structures not supported!" - state.remember self - end - yield - ensure - state and state.forget self - end - - def pson_shift(state, depth) - state and not state.array_nl.empty? or return '' - state.indent * depth - end - - def pson_transform(state, depth) - delim = ',' - if state - delim << state.array_nl - result = '[' - result << state.array_nl - result << map { |value| - pson_shift(state, depth + 1) << value.to_pson(state, depth + 1) - }.join(delim) - result << state.array_nl - result << pson_shift(state, depth) - result << ']' - else - '[' << map { |value| value.to_pson }.join(delim) << ']' - end - end - end - - module Integer - # Returns a PSON string representation for this Integer number. - def to_pson(*) to_s end + else + def utf8_to_pson(string) # :nodoc: + string = string.gsub(/["\\\x0-\x1f]/) { MAP[$&] } + string.gsub!(/( + (?: + [\xc2-\xdf][\x80-\xbf] | + [\xe0-\xef][\x80-\xbf]{2} | + [\xf0-\xf4][\x80-\xbf]{3} + )+ | + [\x80-\xc1\xf5-\xff] # invalid + )/nx) { |c| + c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'" + s = PSON::UTF8toUTF16.iconv(c).unpack('H*')[0] + s.gsub!(/.{4}/n, '\\\\u\&') + } + string + rescue Iconv::Failure => e + raise GeneratorError, "Caught #{e.class}: #{e}" end - - module Float - # Returns a PSON string representation for this Float number. - def to_pson(state = nil, *) - case - when infinite? - if !state || state.allow_nan? - to_s - else - raise GeneratorError, "#{self} not allowed in PSON" - end - when nan? - if !state || state.allow_nan? - to_s - else - raise GeneratorError, "#{self} not allowed in PSON" - end - else - to_s + end + module_function :utf8_to_pson + + module Pure + module Generator + # This class is used to create State instances, that are use to hold data + # while generating a PSON text from a a Ruby data structure. + class State + # Creates a State object from _opts_, which ought to be Hash to create + # a new State instance configured by _opts_, something else to create + # an unconfigured instance. If _opts_ is a State object, it is just + # returned. + def self.from_state(opts) + case opts + when self + opts + when Hash + new(opts) + else + new + end + end + + # Instantiates a new State object, configured by _opts_. + # + # _opts_ can have the following keys: + # + # * *indent*: a string used to indent levels (default: ''), + # * *space*: a string that is put after, a : or , delimiter (default: ''), + # * *space_before*: a string that is put before a : pair delimiter (default: ''), + # * *object_nl*: a string that is put at the end of a PSON object (default: ''), + # * *array_nl*: a string that is put at the end of a PSON array (default: ''), + # * *check_circular*: true if checking for circular data structures + # should be done (the default), false otherwise. + # * *check_circular*: true if checking for circular data structures + # should be done, false (the default) otherwise. + # * *allow_nan*: true if NaN, Infinity, and -Infinity should be + # generated, otherwise an exception is thrown, if these values are + # encountered. This options defaults to false. + def initialize(opts = {}) + @seen = {} + @indent = '' + @space = '' + @space_before = '' + @object_nl = '' + @array_nl = '' + @check_circular = true + @allow_nan = false + configure opts + end + + # This string is used to indent levels in the PSON text. + attr_accessor :indent + + # This string is used to insert a space between the tokens in a PSON + # string. + attr_accessor :space + + # This string is used to insert a space before the ':' in PSON objects. + attr_accessor :space_before + + # This string is put at the end of a line that holds a PSON object (or + # Hash). + attr_accessor :object_nl + + # This string is put at the end of a line that holds a PSON array. + attr_accessor :array_nl + + # This integer returns the maximum level of data structure nesting in + # the generated PSON, max_nesting = 0 if no maximum is checked. + attr_accessor :max_nesting + + def check_max_nesting(depth) # :nodoc: + return if @max_nesting.zero? + current_nesting = depth + 1 + current_nesting > @max_nesting and + raise NestingError, "nesting of #{current_nesting} is too deep" + end + + # Returns true, if circular data structures should be checked, + # otherwise returns false. + def check_circular? + @check_circular + end + + # Returns true if NaN, Infinity, and -Infinity should be considered as + # valid PSON and output. + def allow_nan? + @allow_nan + end + + # Returns _true_, if _object_ was already seen during this generating + # run. + def seen?(object) + @seen.key?(object.__id__) + end + + # Remember _object_, to find out if it was already encountered (if a + # cyclic data structure is if a cyclic data structure is rendered). + def remember(object) + @seen[object.__id__] = true + end + + # Forget _object_ for this generating run. + def forget(object) + @seen.delete object.__id__ + end + + # Configure this State instance with the Hash _opts_, and return + # itself. + def configure(opts) + @indent = opts[:indent] if opts.key?(:indent) + @space = opts[:space] if opts.key?(:space) + @space_before = opts[:space_before] if opts.key?(:space_before) + @object_nl = opts[:object_nl] if opts.key?(:object_nl) + @array_nl = opts[:array_nl] if opts.key?(:array_nl) + @check_circular = !!opts[:check_circular] if opts.key?(:check_circular) + @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan) + if !opts.key?(:max_nesting) # defaults to 19 + @max_nesting = 19 + elsif opts[:max_nesting] + @max_nesting = opts[:max_nesting] + else + @max_nesting = 0 + end + self + end + + # Returns the configuration instance variables as a hash, that can be + # passed to the configure method. + def to_h + result = {} + for iv in %w[indent space space_before object_nl array_nl check_circular allow_nan max_nesting] + result[iv.intern] = instance_variable_get("@#{iv}") + end + result + end end - end - end - module String - # This string should be encoded with UTF-8 A call to this method - # returns a PSON string encoded with UTF16 big endian characters as - # \u????. - def to_pson(*) - '"' << PSON.utf8_to_pson(self) << '"' - end - - # Module that holds the extinding methods if, the String module is - # included. - module Extend - # Raw Strings are PSON Objects (the raw bytes are stored in an array for the - # key "raw"). The Ruby String can be created by this module method. - def pson_create(o) - o['raw'].pack('C*') + module GeneratorMethods + module Object + # Converts this object to a string (calling #to_s), converts + # it to a PSON string, and returns the result. This is a fallback, if no + # special method #to_pson was defined for some object. + def to_pson(*) to_s.to_pson end + end + + module Hash + # Returns a PSON string containing a PSON object, that is unparsed from + # this Hash instance. + # _state_ is a PSON::State object, that can also be used to configure the + # produced PSON string output further. + # _depth_ is used to find out nesting depth, to indent accordingly. + def to_pson(state = nil, depth = 0, *) + if state + state = PSON.state.from_state(state) + state.check_max_nesting(depth) + pson_check_circular(state) { pson_transform(state, depth) } + else + pson_transform(state, depth) + end + end + + private + + def pson_check_circular(state) + if state and state.check_circular? + state.seen?(self) and raise PSON::CircularDatastructure, + "circular data structures not supported!" + state.remember self + end + yield + ensure + state and state.forget self + end + + def pson_shift(state, depth) + state and not state.object_nl.empty? or return '' + state.indent * depth + end + + def pson_transform(state, depth) + delim = ',' + if state + delim << state.object_nl + result = '{' + result << state.object_nl + result << map { |key,value| + s = pson_shift(state, depth + 1) + s << key.to_s.to_pson(state, depth + 1) + s << state.space_before + s << ':' + s << state.space + s << value.to_pson(state, depth + 1) + }.join(delim) + result << state.object_nl + result << pson_shift(state, depth) + result << '}' + else + result = '{' + result << map { |key,value| + key.to_s.to_pson << ':' << value.to_pson + }.join(delim) + result << '}' + end + result + end + end + + module Array + # Returns a PSON string containing a PSON array, that is unparsed from + # this Array instance. + # _state_ is a PSON::State object, that can also be used to configure the + # produced PSON string output further. + # _depth_ is used to find out nesting depth, to indent accordingly. + def to_pson(state = nil, depth = 0, *) + if state + state = PSON.state.from_state(state) + state.check_max_nesting(depth) + pson_check_circular(state) { pson_transform(state, depth) } + else + pson_transform(state, depth) + end + end + + private + + def pson_check_circular(state) + if state and state.check_circular? + state.seen?(self) and raise PSON::CircularDatastructure, + "circular data structures not supported!" + state.remember self + end + yield + ensure + state and state.forget self + end + + def pson_shift(state, depth) + state and not state.array_nl.empty? or return '' + state.indent * depth + end + + def pson_transform(state, depth) + delim = ',' + if state + delim << state.array_nl + result = '[' + result << state.array_nl + result << map { |value| + pson_shift(state, depth + 1) << value.to_pson(state, depth + 1) + }.join(delim) + result << state.array_nl + result << pson_shift(state, depth) + result << ']' + else + '[' << map { |value| value.to_pson }.join(delim) << ']' + end + end + end + + module Integer + # Returns a PSON string representation for this Integer number. + def to_pson(*) to_s end + end + + module Float + # Returns a PSON string representation for this Float number. + def to_pson(state = nil, *) + case + when infinite? + if !state || state.allow_nan? + to_s + else + raise GeneratorError, "#{self} not allowed in PSON" + end + when nan? + if !state || state.allow_nan? + to_s + else + raise GeneratorError, "#{self} not allowed in PSON" + end + else + to_s + end + end + end + + module String + # This string should be encoded with UTF-8 A call to this method + # returns a PSON string encoded with UTF16 big endian characters as + # \u????. + def to_pson(*) + '"' << PSON.utf8_to_pson(self) << '"' + end + + # Module that holds the extinding methods if, the String module is + # included. + module Extend + # Raw Strings are PSON Objects (the raw bytes are stored in an array for the + # key "raw"). The Ruby String can be created by this module method. + def pson_create(o) + o['raw'].pack('C*') + end + end + + # Extends _modul_ with the String::Extend module. + def self.included(modul) + modul.extend Extend + end + + # This method creates a raw object hash, that can be nested into + # other data structures and will be unparsed as a raw string. This + # method should be used, if you want to convert raw strings to PSON + # instead of UTF-8 strings, e. g. binary data. + def to_pson_raw_object + { + PSON.create_id => self.class.name, + 'raw' => self.unpack('C*'), + } + end + + # This method creates a PSON text from the result of + # a call to to_pson_raw_object of this String. + def to_pson_raw(*args) + to_pson_raw_object.to_pson(*args) + end + end + + module TrueClass + # Returns a PSON string for true: 'true'. + def to_pson(*) 'true' end + end + + module FalseClass + # Returns a PSON string for false: 'false'. + def to_pson(*) 'false' end + end + + module NilClass + # Returns a PSON string for nil: 'null'. + def to_pson(*) 'null' end + end end - end - - # Extends _modul_ with the String::Extend module. - def self.included(modul) - modul.extend Extend - end - - # This method creates a raw object hash, that can be nested into - # other data structures and will be unparsed as a raw string. This - # method should be used, if you want to convert raw strings to PSON - # instead of UTF-8 strings, e. g. binary data. - def to_pson_raw_object - { - PSON.create_id => self.class.name, - 'raw' => self.unpack('C*'), - } - end - - # This method creates a PSON text from the result of - # a call to to_pson_raw_object of this String. - def to_pson_raw(*args) - to_pson_raw_object.to_pson(*args) - end - end - - module TrueClass - # Returns a PSON string for true: 'true'. - def to_pson(*) 'true' end - end - - module FalseClass - # Returns a PSON string for false: 'false'. - def to_pson(*) 'false' end - end - - module NilClass - # Returns a PSON string for nil: 'null'. - def to_pson(*) 'null' end end - end end - end end diff --git a/lib/puppet/external/pson/pure/parser.rb b/lib/puppet/external/pson/pure/parser.rb index 56c27f762..ef14d4009 100644 --- a/lib/puppet/external/pson/pure/parser.rb +++ b/lib/puppet/external/pson/pure/parser.rb @@ -1,269 +1,272 @@ require 'strscan' module PSON - module Pure - # This class implements the PSON parser that is used to parse a PSON string - # into a Ruby data structure. - class Parser < StringScanner - STRING = /" ((?:[^\x0-\x1f"\\] | - # escaped special characters: - \\["\\\/bfnrt] | - \\u[0-9a-fA-F]{4} | - # match all but escaped special characters: - \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*) - "/nx - INTEGER = /(-?0|-?[1-9]\d*)/ - FLOAT = /(-? - (?:0|[1-9]\d*) - (?: - \.\d+(?i:e[+-]?\d+) | - \.\d+ | - (?i:e[+-]?\d+) - ) - )/x - NAN = /NaN/ - INFINITY = /Infinity/ - MINUS_INFINITY = /-Infinity/ - OBJECT_OPEN = /\{/ - OBJECT_CLOSE = /\}/ - ARRAY_OPEN = /\[/ - ARRAY_CLOSE = /\]/ - PAIR_DELIMITER = /:/ - COLLECTION_DELIMITER = /,/ - TRUE = /true/ - FALSE = /false/ - NULL = /null/ - IGNORE = %r( - (?: - //[^\n\r]*[\n\r]| # line comments - /\* # c-style comments - (?: - [^*/]| # normal chars - /[^*]| # slashes that do not start a nested comment - \*[^/]| # asterisks that do not end this comment - /(?=\*/) # single slash before this comment's end - )* - \*/ # the End of this comment - |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr - )+ - )mx + module Pure + # This class implements the PSON parser that is used to parse a PSON string + # into a Ruby data structure. + class Parser < StringScanner + STRING = /" ((?:[^\x0-\x1f"\\] | + # escaped special characters: + \\["\\\/bfnrt] | + \\u[0-9a-fA-F]{4} | + # match all but escaped special characters: + \\[\x20-\x21\x23-\x2e\x30-\x5b\x5d-\x61\x63-\x65\x67-\x6d\x6f-\x71\x73\x75-\xff])*) + "/nx + INTEGER = /(-?0|-?[1-9]\d*)/ + FLOAT = /(-? + (?:0|[1-9]\d*) + (?: + \.\d+(?i:e[+-]?\d+) | + \.\d+ | + (?i:e[+-]?\d+) + ) + )/x + NAN = /NaN/ + INFINITY = /Infinity/ + MINUS_INFINITY = /-Infinity/ + OBJECT_OPEN = /\{/ + OBJECT_CLOSE = /\}/ + ARRAY_OPEN = /\[/ + ARRAY_CLOSE = /\]/ + PAIR_DELIMITER = /:/ + COLLECTION_DELIMITER = /,/ + TRUE = /true/ + FALSE = /false/ + NULL = /null/ + IGNORE = %r( + (?: + //[^\n\r]*[\n\r]| # line comments + /\* # c-style comments + (?: + [^*/]| # normal chars + /[^*]| # slashes that do not start a nested comment + \*[^/]| # asterisks that do not end this comment + /(?=\*/) # single slash before this comment's end + )* + \*/ # the End of this comment + |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr + )+ + )mx - UNPARSED = Object.new + UNPARSED = Object.new - # Creates a new PSON::Pure::Parser instance for the string _source_. - # - # It will be configured by the _opts_ hash. _opts_ can have the following - # keys: - # * *max_nesting*: The maximum depth of nesting allowed in the parsed data - # structures. Disable depth checking with :max_nesting => false|nil|0, - # it defaults to 19. - # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in - # defiance of RFC 4627 to be parsed by the Parser. This option defaults - # to false. - # * *create_additions*: If set to false, the Parser doesn't create - # additions even if a matchin class and create_id was found. This option - # defaults to true. - # * *object_class*: Defaults to Hash - # * *array_class*: Defaults to Array - def initialize(source, opts = {}) - super - if !opts.key?(:max_nesting) # defaults to 19 - @max_nesting = 19 - elsif opts[:max_nesting] - @max_nesting = opts[:max_nesting] - else - @max_nesting = 0 - end - @allow_nan = !!opts[:allow_nan] - ca = true - ca = opts[:create_additions] if opts.key?(:create_additions) - @create_id = ca ? PSON.create_id : nil - @object_class = opts[:object_class] || Hash - @array_class = opts[:array_class] || Array - end + # Creates a new PSON::Pure::Parser instance for the string _source_. + # + # It will be configured by the _opts_ hash. _opts_ can have the following + # keys: + # * *max_nesting*: The maximum depth of nesting allowed in the parsed data + # structures. Disable depth checking with :max_nesting => false|nil|0, + # it defaults to 19. + # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in + # defiance of RFC 4627 to be parsed by the Parser. This option defaults + # to false. + # * *create_additions*: If set to false, the Parser doesn't create + # additions even if a matchin class and create_id was found. This option + # defaults to true. + # * *object_class*: Defaults to Hash + # * *array_class*: Defaults to Array + def initialize(source, opts = {}) + super + if !opts.key?(:max_nesting) # defaults to 19 + @max_nesting = 19 + elsif opts[:max_nesting] + @max_nesting = opts[:max_nesting] + else + @max_nesting = 0 + end + @allow_nan = !!opts[:allow_nan] + ca = true + ca = opts[:create_additions] if opts.key?(:create_additions) + @create_id = ca ? PSON.create_id : nil + @object_class = opts[:object_class] || Hash + @array_class = opts[:array_class] || Array + end - alias source string + alias source string - # Parses the current PSON string _source_ and returns the complete data - # structure as a result. - def parse - reset - obj = nil - until eos? - case - when scan(OBJECT_OPEN) - obj and raise ParserError, "source '#{peek(20)}' not in PSON!" - @current_nesting = 1 - obj = parse_object - when scan(ARRAY_OPEN) - obj and raise ParserError, "source '#{peek(20)}' not in PSON!" - @current_nesting = 1 - obj = parse_array - when skip(IGNORE) - ; - else - raise ParserError, "source '#{peek(20)}' not in PSON!" - end - end - obj or raise ParserError, "source did not contain any PSON!" - obj - end + # Parses the current PSON string _source_ and returns the complete data + # structure as a result. + def parse + reset + obj = nil + until eos? + case + when scan(OBJECT_OPEN) + obj and raise ParserError, "source '#{peek(20)}' not in PSON!" + @current_nesting = 1 + obj = parse_object + when scan(ARRAY_OPEN) + obj and raise ParserError, "source '#{peek(20)}' not in PSON!" + @current_nesting = 1 + obj = parse_array + when skip(IGNORE) + ; + else + raise ParserError, "source '#{peek(20)}' not in PSON!" + end + end + obj or raise ParserError, "source did not contain any PSON!" + obj + end - private + private - # Unescape characters in strings. - UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr } - UNESCAPE_MAP.update({ - ?" => '"', - ?\\ => '\\', - ?/ => '/', - ?b => "\b", - ?f => "\f", - ?n => "\n", - ?r => "\r", - ?t => "\t", - ?u => nil, - }) + # Unescape characters in strings. + UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr } - def parse_string - if scan(STRING) - return '' if self[1].empty? - string = self[1].gsub(%r{(?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff])}n) do |c| - if u = UNESCAPE_MAP[$&[1]] - u - else # \uXXXX - bytes = '' - i = 0 - while c[6 * i] == ?\\ && c[6 * i + 1] == ?u - bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16) - i += 1 - end - PSON::UTF16toUTF8.iconv(bytes) - end - end - if string.respond_to?(:force_encoding) - string.force_encoding(Encoding::UTF_8) - end - string - else - UNPARSED - end - rescue Iconv::Failure => e - raise GeneratorError, "Caught #{e.class}: #{e}" - end + UNESCAPE_MAP.update( + { + ?" => '"', + ?\\ => '\\', + ?/ => '/', + ?b => "\b", + ?f => "\f", + ?n => "\n", + ?r => "\r", + ?t => "\t", + ?u => nil, - def parse_value - case - when scan(FLOAT) - Float(self[1]) - when scan(INTEGER) - Integer(self[1]) - when scan(TRUE) - true - when scan(FALSE) - false - when scan(NULL) - nil - when (string = parse_string) != UNPARSED - string - when scan(ARRAY_OPEN) - @current_nesting += 1 - ary = parse_array - @current_nesting -= 1 - ary - when scan(OBJECT_OPEN) - @current_nesting += 1 - obj = parse_object - @current_nesting -= 1 - obj - when @allow_nan && scan(NAN) - NaN - when @allow_nan && scan(INFINITY) - Infinity - when @allow_nan && scan(MINUS_INFINITY) - MinusInfinity - else - UNPARSED - end - end + }) - def parse_array - raise NestingError, "nesting of #@current_nesting is too deep" if - @max_nesting.nonzero? && @current_nesting > @max_nesting - result = @array_class.new - delim = false - until eos? - case - when (value = parse_value) != UNPARSED - delim = false - result << value - skip(IGNORE) - if scan(COLLECTION_DELIMITER) - delim = true - elsif match?(ARRAY_CLOSE) - ; - else - raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!" - end - when scan(ARRAY_CLOSE) - if delim - raise ParserError, "expected next element in array at '#{peek(20)}'!" + def parse_string + if scan(STRING) + return '' if self[1].empty? + string = self[1].gsub(%r{(?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff])}n) do |c| + if u = UNESCAPE_MAP[$&[1]] + u + else # \uXXXX + bytes = '' + i = 0 + while c[6 * i] == ?\\ && c[6 * i + 1] == ?u + bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16) + i += 1 + end + PSON::UTF16toUTF8.iconv(bytes) + end + end + if string.respond_to?(:force_encoding) + string.force_encoding(Encoding::UTF_8) + end + string + else + UNPARSED + end + rescue Iconv::Failure => e + raise GeneratorError, "Caught #{e.class}: #{e}" end - break - when skip(IGNORE) - ; - else - raise ParserError, "unexpected token in array at '#{peek(20)}'!" - end - end - result - end - def parse_object - raise NestingError, "nesting of #@current_nesting is too deep" if - @max_nesting.nonzero? && @current_nesting > @max_nesting - result = @object_class.new - delim = false - until eos? - case - when (string = parse_string) != UNPARSED - skip(IGNORE) - unless scan(PAIR_DELIMITER) - raise ParserError, "expected ':' in object at '#{peek(20)}'!" + def parse_value + case + when scan(FLOAT) + Float(self[1]) + when scan(INTEGER) + Integer(self[1]) + when scan(TRUE) + true + when scan(FALSE) + false + when scan(NULL) + nil + when (string = parse_string) != UNPARSED + string + when scan(ARRAY_OPEN) + @current_nesting += 1 + ary = parse_array + @current_nesting -= 1 + ary + when scan(OBJECT_OPEN) + @current_nesting += 1 + obj = parse_object + @current_nesting -= 1 + obj + when @allow_nan && scan(NAN) + NaN + when @allow_nan && scan(INFINITY) + Infinity + when @allow_nan && scan(MINUS_INFINITY) + MinusInfinity + else + UNPARSED + end end - skip(IGNORE) - unless (value = parse_value).equal? UNPARSED - result[string] = value - delim = false - skip(IGNORE) - if scan(COLLECTION_DELIMITER) - delim = true - elsif match?(OBJECT_CLOSE) - ; - else - raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!" - end - else - raise ParserError, "expected value in object at '#{peek(20)}'!" - end - when scan(OBJECT_CLOSE) - if delim - raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!" + + def parse_array + raise NestingError, "nesting of #@current_nesting is too deep" if + @max_nesting.nonzero? && @current_nesting > @max_nesting + result = @array_class.new + delim = false + until eos? + case + when (value = parse_value) != UNPARSED + delim = false + result << value + skip(IGNORE) + if scan(COLLECTION_DELIMITER) + delim = true + elsif match?(ARRAY_CLOSE) + ; + else + raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!" + end + when scan(ARRAY_CLOSE) + if delim + raise ParserError, "expected next element in array at '#{peek(20)}'!" + end + break + when skip(IGNORE) + ; + else + raise ParserError, "unexpected token in array at '#{peek(20)}'!" + end + end + result end - if @create_id and klassname = result[@create_id] - klass = PSON.deep_const_get klassname - break unless klass and klass.pson_creatable? - result = klass.pson_create(result) + + def parse_object + raise NestingError, "nesting of #@current_nesting is too deep" if + @max_nesting.nonzero? && @current_nesting > @max_nesting + result = @object_class.new + delim = false + until eos? + case + when (string = parse_string) != UNPARSED + skip(IGNORE) + unless scan(PAIR_DELIMITER) + raise ParserError, "expected ':' in object at '#{peek(20)}'!" + end + skip(IGNORE) + unless (value = parse_value).equal? UNPARSED + result[string] = value + delim = false + skip(IGNORE) + if scan(COLLECTION_DELIMITER) + delim = true + elsif match?(OBJECT_CLOSE) + ; + else + raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!" + end + else + raise ParserError, "expected value in object at '#{peek(20)}'!" + end + when scan(OBJECT_CLOSE) + if delim + raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!" + end + if @create_id and klassname = result[@create_id] + klass = PSON.deep_const_get klassname + break unless klass and klass.pson_creatable? + result = klass.pson_create(result) + end + break + when skip(IGNORE) + ; + else + raise ParserError, "unexpected token in object at '#{peek(20)}'!" + end + end + result end - break - when skip(IGNORE) - ; - else - raise ParserError, "unexpected token in object at '#{peek(20)}'!" - end end - result - end end - end end diff --git a/lib/puppet/external/pson/version.rb b/lib/puppet/external/pson/version.rb index a5a8e4702..0bcfa4ad8 100644 --- a/lib/puppet/external/pson/version.rb +++ b/lib/puppet/external/pson/version.rb @@ -1,8 +1,8 @@ module PSON - # PSON version - VERSION = '1.1.9' - VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: - VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: - VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: - VERSION_BUILD = VERSION_ARRAY[2] # :nodoc: + # PSON version + VERSION = '1.1.9' + VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: + VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: + VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: + VERSION_BUILD = VERSION_ARRAY[2] # :nodoc: end |