irb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +5 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +55 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +6 -0
  9. data/bin/setup +6 -0
  10. data/exe/irb +11 -0
  11. data/irb.gemspec +26 -0
  12. data/lib/irb.rb +798 -0
  13. data/lib/irb/cmd/chws.rb +34 -0
  14. data/lib/irb/cmd/fork.rb +39 -0
  15. data/lib/irb/cmd/help.rb +42 -0
  16. data/lib/irb/cmd/load.rb +67 -0
  17. data/lib/irb/cmd/nop.rb +39 -0
  18. data/lib/irb/cmd/pushws.rb +41 -0
  19. data/lib/irb/cmd/subirb.rb +43 -0
  20. data/lib/irb/completion.rb +244 -0
  21. data/lib/irb/context.rb +425 -0
  22. data/lib/irb/ext/change-ws.rb +46 -0
  23. data/lib/irb/ext/history.rb +119 -0
  24. data/lib/irb/ext/loader.rb +129 -0
  25. data/lib/irb/ext/multi-irb.rb +265 -0
  26. data/lib/irb/ext/save-history.rb +105 -0
  27. data/lib/irb/ext/tracer.rb +72 -0
  28. data/lib/irb/ext/use-loader.rb +74 -0
  29. data/lib/irb/ext/workspaces.rb +67 -0
  30. data/lib/irb/extend-command.rb +306 -0
  31. data/lib/irb/frame.rb +81 -0
  32. data/lib/irb/help.rb +37 -0
  33. data/lib/irb/init.rb +302 -0
  34. data/lib/irb/input-method.rb +192 -0
  35. data/lib/irb/inspector.rb +132 -0
  36. data/lib/irb/lc/.document +4 -0
  37. data/lib/irb/lc/error.rb +32 -0
  38. data/lib/irb/lc/help-message +49 -0
  39. data/lib/irb/lc/ja/encoding_aliases.rb +11 -0
  40. data/lib/irb/lc/ja/error.rb +31 -0
  41. data/lib/irb/lc/ja/help-message +52 -0
  42. data/lib/irb/locale.rb +182 -0
  43. data/lib/irb/magic-file.rb +38 -0
  44. data/lib/irb/notifier.rb +232 -0
  45. data/lib/irb/output-method.rb +92 -0
  46. data/lib/irb/ruby-lex.rb +1180 -0
  47. data/lib/irb/ruby-token.rb +267 -0
  48. data/lib/irb/slex.rb +282 -0
  49. data/lib/irb/src_encoding.rb +7 -0
  50. data/lib/irb/version.rb +17 -0
  51. data/lib/irb/workspace.rb +143 -0
  52. data/lib/irb/ws-for-case-2.rb +15 -0
  53. data/lib/irb/xmp.rb +170 -0
  54. metadata +125 -0
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # frame.rb -
4
+ # $Release Version: 0.9$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require "e2mmap"
14
+
15
+ module IRB
16
+ class Frame
17
+ extend Exception2MessageMapper
18
+ def_exception :FrameOverflow, "frame overflow"
19
+ def_exception :FrameUnderflow, "frame underflow"
20
+
21
+ # Default number of stack frames
22
+ INIT_STACK_TIMES = 3
23
+ # Default number of frames offset
24
+ CALL_STACK_OFFSET = 3
25
+
26
+ # Creates a new stack frame
27
+ def initialize
28
+ @frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES
29
+ end
30
+
31
+ # Used by Kernel#set_trace_func to register each event in the call stack
32
+ def trace_func(event, file, line, id, binding)
33
+ case event
34
+ when 'call', 'class'
35
+ @frames.push binding
36
+ when 'return', 'end'
37
+ @frames.pop
38
+ end
39
+ end
40
+
41
+ # Returns the +n+ number of frames on the call stack from the last frame
42
+ # initialized.
43
+ #
44
+ # Raises FrameUnderflow if there are no frames in the given stack range.
45
+ def top(n = 0)
46
+ bind = @frames[-(n + CALL_STACK_OFFSET)]
47
+ Fail FrameUnderflow unless bind
48
+ bind
49
+ end
50
+
51
+ # Returns the +n+ number of frames on the call stack from the first frame
52
+ # initialized.
53
+ #
54
+ # Raises FrameOverflow if there are no frames in the given stack range.
55
+ def bottom(n = 0)
56
+ bind = @frames[n]
57
+ Fail FrameOverflow unless bind
58
+ bind
59
+ end
60
+
61
+ # Convenience method for Frame#bottom
62
+ def Frame.bottom(n = 0)
63
+ @backtrace.bottom(n)
64
+ end
65
+
66
+ # Convenience method for Frame#top
67
+ def Frame.top(n = 0)
68
+ @backtrace.top(n)
69
+ end
70
+
71
+ # Returns the binding context of the caller from the last frame initialized
72
+ def Frame.sender
73
+ eval "self", @backtrace.top
74
+ end
75
+
76
+ @backtrace = Frame.new
77
+ set_trace_func proc{|event, file, line, id, binding, klass|
78
+ @backtrace.trace_func(event, file, line, id, binding)
79
+ }
80
+ end
81
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # irb/help.rb - print usage module
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ishitsuka.com)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require_relative 'magic-file'
14
+
15
+ module IRB
16
+ # Outputs the irb help message, see IRB@Command+line+options.
17
+ def IRB.print_usage
18
+ lc = IRB.conf[:LC_MESSAGES]
19
+ path = lc.find("irb/help-message")
20
+ space_line = false
21
+ IRB::MagicFile.open(path){|f|
22
+ f.each_line do |l|
23
+ if /^\s*$/ =~ l
24
+ lc.puts l unless space_line
25
+ space_line = true
26
+ next
27
+ end
28
+ space_line = false
29
+
30
+ l.sub!(/#.*$/, "")
31
+ next if /^\s*$/ =~ l
32
+ lc.puts l
33
+ end
34
+ }
35
+ end
36
+ end
37
+
@@ -0,0 +1,302 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # irb/init.rb - irb initialize module
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ module IRB # :nodoc:
14
+
15
+ # initialize config
16
+ def IRB.setup(ap_path, argv: ::ARGV)
17
+ IRB.init_config(ap_path)
18
+ IRB.init_error
19
+ IRB.parse_opts(argv: argv)
20
+ IRB.run_config
21
+ IRB.load_modules
22
+
23
+ unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]]
24
+ IRB.fail(UndefinedPromptMode, @CONF[:PROMPT_MODE])
25
+ end
26
+ end
27
+
28
+ # @CONF default setting
29
+ def IRB.init_config(ap_path)
30
+ # class instance variables
31
+ @TRACER_INITIALIZED = false
32
+
33
+ # default configurations
34
+ unless ap_path and @CONF[:AP_NAME]
35
+ ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb")
36
+ end
37
+ @CONF[:AP_NAME] = File::basename(ap_path, ".rb")
38
+
39
+ @CONF[:IRB_NAME] = "irb"
40
+ @CONF[:IRB_LIB_PATH] = File.dirname(__FILE__)
41
+
42
+ @CONF[:RC] = true
43
+ @CONF[:LOAD_MODULES] = []
44
+ @CONF[:IRB_RC] = nil
45
+
46
+ @CONF[:USE_READLINE] = false unless defined?(ReadlineInputMethod)
47
+ @CONF[:INSPECT_MODE] = true
48
+ @CONF[:USE_TRACER] = false
49
+ @CONF[:USE_LOADER] = false
50
+ @CONF[:IGNORE_SIGINT] = true
51
+ @CONF[:IGNORE_EOF] = false
52
+ @CONF[:ECHO] = nil
53
+ @CONF[:VERBOSE] = nil
54
+
55
+ @CONF[:EVAL_HISTORY] = nil
56
+ @CONF[:SAVE_HISTORY] = nil
57
+
58
+ @CONF[:BACK_TRACE_LIMIT] = 16
59
+
60
+ @CONF[:PROMPT] = {
61
+ :NULL => {
62
+ :PROMPT_I => nil,
63
+ :PROMPT_N => nil,
64
+ :PROMPT_S => nil,
65
+ :PROMPT_C => nil,
66
+ :RETURN => "%s\n"
67
+ },
68
+ :DEFAULT => {
69
+ :PROMPT_I => "%N(%m):%03n:%i> ",
70
+ :PROMPT_N => "%N(%m):%03n:%i> ",
71
+ :PROMPT_S => "%N(%m):%03n:%i%l ",
72
+ :PROMPT_C => "%N(%m):%03n:%i* ",
73
+ :RETURN => "=> %s\n"
74
+ },
75
+ :CLASSIC => {
76
+ :PROMPT_I => "%N(%m):%03n:%i> ",
77
+ :PROMPT_N => "%N(%m):%03n:%i> ",
78
+ :PROMPT_S => "%N(%m):%03n:%i%l ",
79
+ :PROMPT_C => "%N(%m):%03n:%i* ",
80
+ :RETURN => "%s\n"
81
+ },
82
+ :SIMPLE => {
83
+ :PROMPT_I => ">> ",
84
+ :PROMPT_N => ">> ",
85
+ :PROMPT_S => nil,
86
+ :PROMPT_C => "?> ",
87
+ :RETURN => "=> %s\n"
88
+ },
89
+ :INF_RUBY => {
90
+ :PROMPT_I => "%N(%m):%03n:%i> ",
91
+ :PROMPT_N => nil,
92
+ :PROMPT_S => nil,
93
+ :PROMPT_C => nil,
94
+ :RETURN => "%s\n",
95
+ :AUTO_INDENT => true
96
+ },
97
+ :XMP => {
98
+ :PROMPT_I => nil,
99
+ :PROMPT_N => nil,
100
+ :PROMPT_S => nil,
101
+ :PROMPT_C => nil,
102
+ :RETURN => " ==>%s\n"
103
+ }
104
+ }
105
+
106
+ @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
107
+ @CONF[:AUTO_INDENT] = false
108
+
109
+ @CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING
110
+ @CONF[:SINGLE_IRB] = false
111
+
112
+ @CONF[:LC_MESSAGES] = Locale.new
113
+
114
+ @CONF[:AT_EXIT] = []
115
+
116
+ @CONF[:DEBUG_LEVEL] = 0
117
+ end
118
+
119
+ def IRB.init_error
120
+ @CONF[:LC_MESSAGES].load("irb/error.rb")
121
+ end
122
+
123
+ # option analyzing
124
+ def IRB.parse_opts(argv: ::ARGV)
125
+ load_path = []
126
+ while opt = argv.shift
127
+ case opt
128
+ when "-f"
129
+ @CONF[:RC] = false
130
+ when "-d"
131
+ $DEBUG = true
132
+ $VERBOSE = true
133
+ when "-w"
134
+ $VERBOSE = true
135
+ when /^-W(.+)?/
136
+ opt = $1 || argv.shift
137
+ case opt
138
+ when "0"
139
+ $VERBOSE = nil
140
+ when "1"
141
+ $VERBOSE = false
142
+ else
143
+ $VERBOSE = true
144
+ end
145
+ when /^-r(.+)?/
146
+ opt = $1 || argv.shift
147
+ @CONF[:LOAD_MODULES].push opt if opt
148
+ when /^-I(.+)?/
149
+ opt = $1 || argv.shift
150
+ load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt
151
+ when '-U'
152
+ set_encoding("UTF-8", "UTF-8")
153
+ when /^-E(.+)?/, /^--encoding(?:=(.+))?/
154
+ opt = $1 || argv.shift
155
+ set_encoding(*opt.split(':', 2))
156
+ when "--inspect"
157
+ if /^-/ !~ argv.first
158
+ @CONF[:INSPECT_MODE] = argv.shift
159
+ else
160
+ @CONF[:INSPECT_MODE] = true
161
+ end
162
+ when "--noinspect"
163
+ @CONF[:INSPECT_MODE] = false
164
+ when "--readline"
165
+ @CONF[:USE_READLINE] = true
166
+ when "--noreadline"
167
+ @CONF[:USE_READLINE] = false
168
+ when "--echo"
169
+ @CONF[:ECHO] = true
170
+ when "--noecho"
171
+ @CONF[:ECHO] = false
172
+ when "--verbose"
173
+ @CONF[:VERBOSE] = true
174
+ when "--noverbose"
175
+ @CONF[:VERBOSE] = false
176
+ when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/
177
+ opt = $1 || argv.shift
178
+ prompt_mode = opt.upcase.tr("-", "_").intern
179
+ @CONF[:PROMPT_MODE] = prompt_mode
180
+ when "--noprompt"
181
+ @CONF[:PROMPT_MODE] = :NULL
182
+ when "--inf-ruby-mode"
183
+ @CONF[:PROMPT_MODE] = :INF_RUBY
184
+ when "--sample-book-mode", "--simple-prompt"
185
+ @CONF[:PROMPT_MODE] = :SIMPLE
186
+ when "--tracer"
187
+ @CONF[:USE_TRACER] = true
188
+ when /^--back-trace-limit(?:=(.+))?/
189
+ @CONF[:BACK_TRACE_LIMIT] = ($1 || argv.shift).to_i
190
+ when /^--context-mode(?:=(.+))?/
191
+ @CONF[:CONTEXT_MODE] = ($1 || argv.shift).to_i
192
+ when "--single-irb"
193
+ @CONF[:SINGLE_IRB] = true
194
+ when /^--irb_debug(?:=(.+))?/
195
+ @CONF[:DEBUG_LEVEL] = ($1 || argv.shift).to_i
196
+ when "-v", "--version"
197
+ print IRB.version, "\n"
198
+ exit 0
199
+ when "-h", "--help"
200
+ require_relative "help"
201
+ IRB.print_usage
202
+ exit 0
203
+ when "--"
204
+ if opt = argv.shift
205
+ @CONF[:SCRIPT] = opt
206
+ $0 = opt
207
+ end
208
+ break
209
+ when /^-/
210
+ IRB.fail UnrecognizedSwitch, opt
211
+ else
212
+ @CONF[:SCRIPT] = opt
213
+ $0 = opt
214
+ break
215
+ end
216
+ end
217
+ load_path.collect! do |path|
218
+ /\A\.\// =~ path ? path : File.expand_path(path)
219
+ end
220
+ $LOAD_PATH.unshift(*load_path)
221
+
222
+ end
223
+
224
+ # running config
225
+ def IRB.run_config
226
+ if @CONF[:RC]
227
+ begin
228
+ load rc_file
229
+ rescue LoadError, Errno::ENOENT
230
+ rescue # StandardError, ScriptError
231
+ print "load error: #{rc_file}\n"
232
+ print $!.class, ": ", $!, "\n"
233
+ for err in $@[0, $@.size - 2]
234
+ print "\t", err, "\n"
235
+ end
236
+ end
237
+ end
238
+ end
239
+
240
+ IRBRC_EXT = "rc"
241
+ def IRB.rc_file(ext = IRBRC_EXT)
242
+ if !@CONF[:RC_NAME_GENERATOR]
243
+ rc_file_generators do |rcgen|
244
+ @CONF[:RC_NAME_GENERATOR] ||= rcgen
245
+ if File.exist?(rcgen.call(IRBRC_EXT))
246
+ @CONF[:RC_NAME_GENERATOR] = rcgen
247
+ break
248
+ end
249
+ end
250
+ end
251
+ case rc_file = @CONF[:RC_NAME_GENERATOR].call(ext)
252
+ when String
253
+ return rc_file
254
+ else
255
+ IRB.fail IllegalRCNameGenerator
256
+ end
257
+ end
258
+
259
+ # enumerate possible rc-file base name generators
260
+ def IRB.rc_file_generators
261
+ if irbrc = ENV["IRBRC"]
262
+ yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
263
+ end
264
+ if home = ENV["HOME"]
265
+ yield proc{|rc| home+"/.irb#{rc}"}
266
+ end
267
+ home = Dir.pwd
268
+ yield proc{|rc| home+"/.irb#{rc}"}
269
+ yield proc{|rc| home+"/irb#{rc.sub(/\A_?/, '.')}"}
270
+ yield proc{|rc| home+"/_irb#{rc}"}
271
+ yield proc{|rc| home+"/$irb#{rc}"}
272
+ end
273
+
274
+ # loading modules
275
+ def IRB.load_modules
276
+ for m in @CONF[:LOAD_MODULES]
277
+ begin
278
+ require m
279
+ rescue LoadError => err
280
+ warn "#{err.class}: #{err}", uplevel: 0
281
+ end
282
+ end
283
+ end
284
+
285
+
286
+ DefaultEncodings = Struct.new(:external, :internal)
287
+ class << IRB
288
+ private
289
+ def set_encoding(extern, intern = nil)
290
+ verbose, $VERBOSE = $VERBOSE, nil
291
+ Encoding.default_external = extern unless extern.nil? || extern.empty?
292
+ Encoding.default_internal = intern unless intern.nil? || intern.empty?
293
+ @CONF[:ENCODINGS] = IRB::DefaultEncodings.new(extern, intern)
294
+ [$stdin, $stdout, $stderr].each do |io|
295
+ io.set_encoding(extern, intern)
296
+ end
297
+ @CONF[:LC_MESSAGES].instance_variable_set(:@encoding, extern)
298
+ ensure
299
+ $VERBOSE = verbose
300
+ end
301
+ end
302
+ end
@@ -0,0 +1,192 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # irb/input-method.rb - input methods used irb
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+ require_relative 'src_encoding'
13
+ require_relative 'magic-file'
14
+
15
+ module IRB
16
+ STDIN_FILE_NAME = "(line)" # :nodoc:
17
+ class InputMethod
18
+
19
+ # Creates a new input method object
20
+ def initialize(file = STDIN_FILE_NAME)
21
+ @file_name = file
22
+ end
23
+ # The file name of this input method, usually given during initialization.
24
+ attr_reader :file_name
25
+
26
+ # The irb prompt associated with this input method
27
+ attr_accessor :prompt
28
+
29
+ # Reads the next line from this input method.
30
+ #
31
+ # See IO#gets for more information.
32
+ def gets
33
+ IRB.fail NotImplementedError, "gets"
34
+ end
35
+ public :gets
36
+
37
+ # Whether this input method is still readable when there is no more data to
38
+ # read.
39
+ #
40
+ # See IO#eof for more information.
41
+ def readable_after_eof?
42
+ false
43
+ end
44
+ end
45
+
46
+ class StdioInputMethod < InputMethod
47
+ # Creates a new input method object
48
+ def initialize
49
+ super
50
+ @line_no = 0
51
+ @line = []
52
+ @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
53
+ @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
54
+ end
55
+
56
+ # Reads the next line from this input method.
57
+ #
58
+ # See IO#gets for more information.
59
+ def gets
60
+ print @prompt
61
+ line = @stdin.gets
62
+ @line[@line_no += 1] = line
63
+ end
64
+
65
+ # Whether the end of this input method has been reached, returns +true+ if
66
+ # there is no more data to read.
67
+ #
68
+ # See IO#eof? for more information.
69
+ def eof?
70
+ @stdin.eof?
71
+ end
72
+
73
+ # Whether this input method is still readable when there is no more data to
74
+ # read.
75
+ #
76
+ # See IO#eof for more information.
77
+ def readable_after_eof?
78
+ true
79
+ end
80
+
81
+ # Returns the current line number for #io.
82
+ #
83
+ # #line counts the number of times #gets is called.
84
+ #
85
+ # See IO#lineno for more information.
86
+ def line(line_no)
87
+ @line[line_no]
88
+ end
89
+
90
+ # The external encoding for standard input.
91
+ def encoding
92
+ @stdin.external_encoding
93
+ end
94
+ end
95
+
96
+ # Use a File for IO with irb, see InputMethod
97
+ class FileInputMethod < InputMethod
98
+ # Creates a new input method object
99
+ def initialize(file)
100
+ super
101
+ @io = IRB::MagicFile.open(file)
102
+ end
103
+ # The file name of this input method, usually given during initialization.
104
+ attr_reader :file_name
105
+
106
+ # Whether the end of this input method has been reached, returns +true+ if
107
+ # there is no more data to read.
108
+ #
109
+ # See IO#eof? for more information.
110
+ def eof?
111
+ @io.eof?
112
+ end
113
+
114
+ # Reads the next line from this input method.
115
+ #
116
+ # See IO#gets for more information.
117
+ def gets
118
+ print @prompt
119
+ l = @io.gets
120
+ l
121
+ end
122
+
123
+ # The external encoding for standard input.
124
+ def encoding
125
+ @io.external_encoding
126
+ end
127
+ end
128
+
129
+ begin
130
+ require "readline"
131
+ class ReadlineInputMethod < InputMethod
132
+ include Readline
133
+ # Creates a new input method object using Readline
134
+ def initialize
135
+ super
136
+
137
+ @line_no = 0
138
+ @line = []
139
+ @eof = false
140
+
141
+ @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
142
+ @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
143
+ end
144
+
145
+ # Reads the next line from this input method.
146
+ #
147
+ # See IO#gets for more information.
148
+ def gets
149
+ Readline.input = @stdin
150
+ Readline.output = @stdout
151
+ if l = readline(@prompt, false)
152
+ HISTORY.push(l) if !l.empty?
153
+ @line[@line_no += 1] = l + "\n"
154
+ else
155
+ @eof = true
156
+ l
157
+ end
158
+ end
159
+
160
+ # Whether the end of this input method has been reached, returns +true+
161
+ # if there is no more data to read.
162
+ #
163
+ # See IO#eof? for more information.
164
+ def eof?
165
+ @eof
166
+ end
167
+
168
+ # Whether this input method is still readable when there is no more data to
169
+ # read.
170
+ #
171
+ # See IO#eof for more information.
172
+ def readable_after_eof?
173
+ true
174
+ end
175
+
176
+ # Returns the current line number for #io.
177
+ #
178
+ # #line counts the number of times #gets is called.
179
+ #
180
+ # See IO#lineno for more information.
181
+ def line(line_no)
182
+ @line[line_no]
183
+ end
184
+
185
+ # The external encoding for standard input.
186
+ def encoding
187
+ @stdin.external_encoding
188
+ end
189
+ end
190
+ rescue LoadError
191
+ end
192
+ end