origen 0.1.3 → 0.2.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.
- checksums.yaml +4 -4
- data/config/version.rb +2 -2
- data/lib/origen/application/deployer.rb +16 -17
- data/lib/origen/application/plugins_manager.rb +1 -1
- data/lib/origen/commands.rb +33 -1
- data/lib/origen/commands/interactive.rb +11 -3
- data/lib/origen/commands/rc.rb +5 -1
- data/lib/origen/commands/web.rb +2 -0
- data/lib/origen/generator/pattern.rb +25 -2
- data/lib/origen/regression_manager.rb +6 -5
- data/lib/origen/revision_control/git.rb +95 -15
- data/lib/origen/specs.rb +19 -13
- data/lib/origen/specs/checkers.rb +99 -93
- data/lib/origen/specs/creation_info.rb +23 -3
- data/lib/origen/specs/spec.rb +8 -1
- data/lib/origen/users/user.rb +13 -4
- data/lib/origen/utility.rb +1 -0
- data/lib/origen/utility/diff.rb +7 -3
- data/lib/origen/utility/file_diff.rb +213 -0
- data/templates/nanoc/Rules +13 -15
- data/templates/nanoc/layouts/bootstrap.html.erb +31 -4
- data/templates/shared/web/_logo.html +3 -3
- data/templates/web/css/landing.css +3 -0
- data/templates/web/design-engineering.html.erb +0 -0
- data/templates/web/index.html.erb +23 -0
- data/templates/web/js/jquery-singlePageNav.js +8 -0
- data/templates/web/js/landing.js +9 -0
- data/templates/web/layouts/_basic.html.erb +1 -0
- data/templates/web/layouts/_cyborg.html.erb +111 -0
- data/templates/web/layouts/_doc.html.erb +1 -0
- data/templates/web/test-engineering.html.erb +79 -0
- metadata +11 -5
- data/templates/nanoc/content/favicon.ico +0 -0
- data/templates/web/index.md.erb +0 -12
@@ -1,103 +1,109 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# a baseline value for a spec use target as it will not be
|
22
|
-
# checked against pass/fail
|
23
|
-
def limits_ok?
|
24
|
-
status = true
|
25
|
-
if (@min.exp.to_s.include? '/') || (@max.exp.to_s.include? '/')
|
26
|
-
return status
|
27
|
-
end
|
28
|
-
if @min.exp.nil? ^ @max.exp.nil?
|
29
|
-
@limit_type = :single_sided
|
30
|
-
if @typ.exp
|
31
|
-
# status = false
|
32
|
-
Origen.log.debug "Spec #{@name} has a typical limit defined with either min or max. They are mutually exclusive, use 'target' when using min or max"
|
33
|
-
end
|
34
|
-
elsif @min.exp && @max.exp
|
35
|
-
@limit_type = :double_sided
|
36
|
-
# Both min and max must be numerical to compare them
|
37
|
-
if @min.value.is_a?(Numeric) && @max.value.is_a?(Numeric)
|
38
|
-
# Check that min and max make sense
|
39
|
-
if @max.value <= @min.value || @min.value >= @max.value
|
40
|
-
status = false
|
41
|
-
Origen.log.debug "Spec #{@name} has min (#{@min.value}) and max (#{@max.value}) reversed"
|
1
|
+
module Origen
|
2
|
+
module Specs
|
3
|
+
module Checkers
|
4
|
+
# rubocop:disable Style/RescueModifier:
|
5
|
+
def name_audit(name)
|
6
|
+
return name if name.nil?
|
7
|
+
return nil unless name.is_a?(Symbol) || name.is_a?(String)
|
8
|
+
if name == :inspect
|
9
|
+
Origen.log.debug ':inspect is a reserved spec name'
|
10
|
+
return nil
|
11
|
+
end
|
12
|
+
if name.match(/^\d/)
|
13
|
+
Origen.log.debug "Spec #{name} starts with a number"
|
14
|
+
return nil
|
15
|
+
end
|
16
|
+
if name.match(/\s+/)
|
17
|
+
Origen.log.debug "Spec #{name} contains white space, removing it"
|
18
|
+
name.delete!(/\s+/)
|
19
|
+
end
|
20
|
+
name.is_a?(String) ? name.downcase.to_sym : name
|
42
21
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
22
|
+
|
23
|
+
# Check that min, max are not mixed with typ. If a user wants
|
24
|
+
# a baseline value for a spec use target as it will not be
|
25
|
+
# checked against pass/fail
|
26
|
+
def limits_ok?
|
27
|
+
status = true
|
28
|
+
if (@min.exp.to_s.include? '/') || (@max.exp.to_s.include? '/')
|
29
|
+
return status
|
30
|
+
end
|
31
|
+
if @min.exp.nil? ^ @max.exp.nil?
|
32
|
+
@limit_type = :single_sided
|
33
|
+
if @typ.exp
|
34
|
+
# status = false
|
35
|
+
Origen.log.debug "Spec #{@name} has a typical limit defined with either min or max. They are mutually exclusive, use 'target' when using min or max"
|
36
|
+
end
|
37
|
+
elsif @min.exp && @max.exp
|
38
|
+
@limit_type = :double_sided
|
39
|
+
# Both min and max must be numerical to compare them
|
40
|
+
if @min.value.is_a?(Numeric) && @max.value.is_a?(Numeric)
|
41
|
+
# Check that min and max make sense
|
42
|
+
if @max.value <= @min.value || @min.value >= @max.value
|
43
|
+
status = false
|
44
|
+
Origen.log.debug "Spec #{@name} has min (#{@min.value}) and max (#{@max.value}) reversed"
|
45
|
+
end
|
46
|
+
# Check that target is OK
|
47
|
+
unless @target.nil?
|
48
|
+
if @target.value <= @min.value || @target.value >= @max.value
|
49
|
+
status = false
|
50
|
+
Origen.log.debug "Spec #{@name} has a target (#{@target.value}) that is not within the min (#{@min.value}) and max #{@max.value}) values"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
48
54
|
end
|
55
|
+
status
|
49
56
|
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
status
|
53
|
-
end
|
54
57
|
|
55
|
-
def get_mode
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
58
|
+
def get_mode
|
59
|
+
spec_mode = nil
|
60
|
+
if current_mode.nil?
|
61
|
+
if self == Origen.top_level
|
62
|
+
spec_mode = :global
|
63
|
+
else
|
64
|
+
spec_mode = :local
|
65
|
+
end
|
66
|
+
else
|
67
|
+
spec_mode = current_mode.name
|
68
|
+
end
|
69
|
+
spec_mode
|
70
|
+
end
|
68
71
|
|
69
|
-
def evaluate_limit(limit)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
else
|
84
|
-
result = Integer(limit) rescue false
|
85
|
-
end
|
86
|
-
if result == false
|
87
|
-
# Attempt to eval the limit because users could write a limit like "3.3 + 50.mV"
|
88
|
-
# which would not work with the code above but should eval to a number 3.35
|
89
|
-
begin
|
90
|
-
result = eval(limit)
|
91
|
-
return result.round(4) if result.is_a? Numeric
|
92
|
-
rescue SyntaxError, NameError, TypeError
|
93
|
-
Origen.log.debug "Limit '#{limit}' had to be rescued, storing it as a #{limit.class}"
|
94
|
-
if limit.is_a? Symbol
|
95
|
-
return limit
|
72
|
+
def evaluate_limit(limit)
|
73
|
+
return limit if limit.is_a?(Numeric) || limit.is_a?(Symbol)
|
74
|
+
return nil if limit.nil?
|
75
|
+
limit.gsub!("\n", ' ')
|
76
|
+
limit.scrub!
|
77
|
+
result = false
|
78
|
+
if !!(limit.match(/^\d+\.\d+$/)) || !!(limit.match(/^-\d+\.\d+$/))
|
79
|
+
result = Float(limit).round(4) rescue false # Use the same four digits of accuracy as the Spec model
|
80
|
+
elsif !!(limit.match(/\d+\.\d+\s+\d+\.\d+/)) # workaround for multiple specs authoring bug
|
81
|
+
Origen.log.debug "Found two numbers without an operator in the limit string '#{limit}', choosing the first..."
|
82
|
+
first_number = limit.match(/(\d+\.\d+)\s+\d+\.\d+/).captures.first
|
83
|
+
result = Float(first_number).round(4) rescue false # Use the same four digits of accuracy as the Spec model
|
84
|
+
# elsif !!(limit.match(/^tbd$/i)) # unique case of TBD or To Be Determined, will convert to symbol
|
85
|
+
# limit = limit.downcase.to_sym
|
96
86
|
else
|
97
|
-
|
87
|
+
result = Integer(limit) rescue false
|
98
88
|
end
|
89
|
+
if result == false
|
90
|
+
# Attempt to eval the limit because users could write a limit like "3.3 + 50.mV"
|
91
|
+
# which would not work with the code above but should eval to a number 3.35
|
92
|
+
begin
|
93
|
+
result = eval(limit)
|
94
|
+
return result.round(4) if result.is_a? Numeric
|
95
|
+
rescue SyntaxError, NameError, TypeError
|
96
|
+
Origen.log.debug "Limit '#{limit}' had to be rescued, storing it as a #{limit.class}"
|
97
|
+
if limit.is_a? Symbol
|
98
|
+
return limit
|
99
|
+
else
|
100
|
+
return "#{limit}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
else
|
104
|
+
return result
|
105
|
+
end
|
106
|
+
end
|
99
107
|
end
|
100
|
-
else
|
101
|
-
return result
|
102
108
|
end
|
103
109
|
end
|
@@ -1,12 +1,32 @@
|
|
1
1
|
module Origen
|
2
2
|
module Specs
|
3
|
-
#
|
3
|
+
# Ruby Data Class that contains Creation Information for the IP Block
|
4
4
|
class Creation_Info
|
5
|
-
attr_accessor :author, :date, :revision, :source, :tool, :tool_version
|
5
|
+
attr_accessor :author, :date, :revision, :source, :tool, :tool_version, :ip_version
|
6
6
|
|
7
|
-
|
7
|
+
# Initialize the Creation Info block to store data for latest version of the file.
|
8
|
+
#
|
9
|
+
# ==== Parameters
|
10
|
+
#
|
11
|
+
# * author # Author/Subject Matter Expert for the IP Block
|
12
|
+
# * date # Date that the File was released to Downstream Audiences
|
13
|
+
# ==== Source Information
|
14
|
+
#
|
15
|
+
# * :revision # Revision Information
|
16
|
+
# * :source # Where the Information came from
|
17
|
+
#
|
18
|
+
# ==== Tool Info
|
19
|
+
#
|
20
|
+
# * :tool # Tool that created the initial XML file
|
21
|
+
# * :version # Version of the Tool that created the XML file
|
22
|
+
#
|
23
|
+
# ==== Example
|
24
|
+
#
|
25
|
+
# Creation_Info.new("author", "07/10/2015", :revision => "5.4", :source => "CSV", :tool => "oRiGeN", :tool_version => "0.0.6")
|
26
|
+
def initialize(author, date, ip_version, src_info = {}, tool_info = {})
|
8
27
|
@author = author
|
9
28
|
@date = date
|
29
|
+
@ip_version = ip_version
|
10
30
|
@revision = src_info[:revision]
|
11
31
|
@source = src_info[:source]
|
12
32
|
@tool = tool_info[:tool]
|
data/lib/origen/specs/spec.rb
CHANGED
@@ -3,7 +3,8 @@ module Origen
|
|
3
3
|
class Spec
|
4
4
|
autoload :Note, 'origen/specs/note'
|
5
5
|
autoload :Exhibit, 'origen/specs/exhibit'
|
6
|
-
|
6
|
+
include Checkers
|
7
|
+
extend Checkers
|
7
8
|
|
8
9
|
SpecAttribute = Struct.new(:name, :type, :required, :author, :description)
|
9
10
|
|
@@ -106,6 +107,12 @@ module Origen
|
|
106
107
|
fail "Spec #{name} failed the limits audit!" unless limits_ok?
|
107
108
|
end
|
108
109
|
|
110
|
+
def inspect
|
111
|
+
$dut.send(:specs_to_table_string, [self])
|
112
|
+
rescue
|
113
|
+
super
|
114
|
+
end
|
115
|
+
|
109
116
|
def method_missing(method, *args, &block)
|
110
117
|
ivar = "@#{method.to_s.gsub('=', '')}"
|
111
118
|
ivar_sym = ":#{ivar}"
|
data/lib/origen/users/user.rb
CHANGED
@@ -66,16 +66,25 @@ module Origen
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def name
|
69
|
-
@name || @id
|
69
|
+
@name || name_from_rc || @id
|
70
|
+
end
|
71
|
+
|
72
|
+
def name_from_rc
|
73
|
+
RevisionControl::Git.user_name
|
70
74
|
end
|
71
75
|
|
72
76
|
def email
|
73
|
-
|
74
|
-
|
75
|
-
|
77
|
+
@email || email_from_rc || begin
|
78
|
+
if Origen.site_config.email_domain
|
79
|
+
"#{id}@#{Origen.site_config.email_domain}"
|
80
|
+
end
|
76
81
|
end
|
77
82
|
end
|
78
83
|
|
84
|
+
def email_from_rc
|
85
|
+
RevisionControl::Git.user_email
|
86
|
+
end
|
87
|
+
|
79
88
|
# Fetch user data from the FSL application directory
|
80
89
|
#
|
81
90
|
# @example
|
data/lib/origen/utility.rb
CHANGED
data/lib/origen/utility/diff.rb
CHANGED
@@ -101,9 +101,13 @@ module Origen
|
|
101
101
|
if @comment_char
|
102
102
|
# Screen off any inline comments at the end of line
|
103
103
|
begin
|
104
|
-
[@comment_char].flatten.each do |
|
105
|
-
|
106
|
-
|
104
|
+
[@comment_char].flatten.each do |comchar|
|
105
|
+
unless line =~ /^\s*#{comchar}/
|
106
|
+
if line =~ /(.*)\s*#{comchar}.*/
|
107
|
+
return Regexp.last_match[1].strip
|
108
|
+
else
|
109
|
+
return line.strip
|
110
|
+
end
|
107
111
|
end
|
108
112
|
end
|
109
113
|
# This rescue is a crude way to guard against non-ASCII files that find
|
@@ -0,0 +1,213 @@
|
|
1
|
+
module Origen
|
2
|
+
module Utility
|
3
|
+
module FileDiff
|
4
|
+
class InputFile < Array
|
5
|
+
attr_accessor :pointer
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.pointer = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def current_line
|
12
|
+
self[pointer]
|
13
|
+
end
|
14
|
+
|
15
|
+
def advance_pointer!
|
16
|
+
self.pointer += 1
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_current_line_in(other)
|
20
|
+
index = (other[other.pointer..-1] || []).index(current_line)
|
21
|
+
index.nil? ? nil : other.pointer + index
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class OutputFile < Array
|
26
|
+
class Line < String
|
27
|
+
attr_accessor :type, :original_number
|
28
|
+
def initialize(type, input_file)
|
29
|
+
self.type = type
|
30
|
+
return unless input_file
|
31
|
+
replace(input_file.current_line)
|
32
|
+
self.original_number = input_file.pointer + 1
|
33
|
+
input_file.advance_pointer!
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_line(type, input_file = nil)
|
38
|
+
push(Line.new(type, input_file))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Diff Processor (Origen::Utility::Processor) provides an easy way to diff the contents of two files
|
43
|
+
# and display the differences as an HTML file or a TXT file.
|
44
|
+
# Very basic functionality, but can be expanded to add more features in the future.
|
45
|
+
# Comments are not ignored for now (maybe a future enhancement)
|
46
|
+
# Each difference is displayed in a different color in the HTML page
|
47
|
+
# Legend:
|
48
|
+
# - New: Light Green
|
49
|
+
# - Modified: Light Gray
|
50
|
+
# - Deleted: Pink
|
51
|
+
# Usage:
|
52
|
+
# processor = Origen::Utility::FileDiff::Processor.new("#{Origen.root}/left.txt", "#{Origen.root}/right.txt")
|
53
|
+
#
|
54
|
+
# To Generate a HTML file (diff.html) showing the differences
|
55
|
+
# Origen::Utility::FileDiff::Formatter::Html.new(processor.process!, "#{Origen.root}/diff.html").format
|
56
|
+
#
|
57
|
+
# To Generate a TXT file (diff.txt) showing the differences
|
58
|
+
# Origen::Utility::FileDiff::Formatter::Text.new(processor.process!, "#{Origen.root}/diff.txt").format
|
59
|
+
class Processor
|
60
|
+
attr_accessor :source, :target
|
61
|
+
attr_accessor :source_output, :target_output
|
62
|
+
def initialize(source_file_name, target_file_name)
|
63
|
+
self.source = InputFile.new
|
64
|
+
self.target = InputFile.new
|
65
|
+
self.source_output = OutputFile.new
|
66
|
+
self.target_output = OutputFile.new
|
67
|
+
IO.readlines(source_file_name).each do |line|
|
68
|
+
source << line
|
69
|
+
end
|
70
|
+
IO.readlines(target_file_name).each do |line|
|
71
|
+
target << line
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def handle_exactly_matched
|
76
|
+
source_output.add_line(:unchanged, source)
|
77
|
+
target_output.add_line(:unchanged, target)
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle_line_changed
|
81
|
+
source_output.add_line(:changed, source)
|
82
|
+
target_output.add_line(:changed, target)
|
83
|
+
end
|
84
|
+
|
85
|
+
def handle_block_added(size)
|
86
|
+
size.times do
|
87
|
+
source_output.add_line(:added) # Empty line in the left side of the diff
|
88
|
+
target_output.add_line(:added, target)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def handle_block_deleted(size)
|
93
|
+
size.times do
|
94
|
+
source_output.add_line(:deleted, source)
|
95
|
+
target_output.add_line(:deleted) # Empty line in the right side of the diff
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def process!
|
100
|
+
while source.pointer < source.size && target.pointer < target.size
|
101
|
+
matched = source.find_current_line_in(target)
|
102
|
+
if matched
|
103
|
+
if matched > target.pointer
|
104
|
+
deleted = target.find_current_line_in(source)
|
105
|
+
handle_block_deleted(deleted - source.pointer) if deleted
|
106
|
+
end
|
107
|
+
handle_block_added(matched - target.pointer)
|
108
|
+
handle_exactly_matched
|
109
|
+
else
|
110
|
+
found = target.find_current_line_in(source)
|
111
|
+
if found
|
112
|
+
handle_block_deleted(found - source.pointer)
|
113
|
+
else
|
114
|
+
handle_line_changed
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
handle_block_deleted(source.size - source.pointer)
|
119
|
+
handle_block_added(target.size - target.pointer)
|
120
|
+
|
121
|
+
self
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
module Formatter
|
126
|
+
class Base
|
127
|
+
attr_accessor :source_output, :target_output, :file
|
128
|
+
def initialize(processed_diff, output_file_name)
|
129
|
+
self.source_output = processed_diff.source_output
|
130
|
+
self.target_output = processed_diff.target_output
|
131
|
+
self.file = File.open(output_file_name, 'w')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Html < Base
|
136
|
+
def format
|
137
|
+
tag(:style) { content('td{vertical-align: middle} pre{margin: 0px} .added{background-color: lightgreen;}.deleted{background-color: pink;}.changed{background-color: lightgray;}.line{background-color: lightblue}') }
|
138
|
+
tag :table, cellpaddig: 0, cellspacing: 0 do
|
139
|
+
source_output.each_with_index do |src, i|
|
140
|
+
tgt = target_output[i]
|
141
|
+
tag :tr do
|
142
|
+
tag(:td, class: :line) { tag(:pre) { content(src.original_number) } }
|
143
|
+
tag(:td, class: src.type) { tag(:pre) { content(src) } }
|
144
|
+
tag(:td, class: :line) { tag(:pre) { content(tgt.original_number) } }
|
145
|
+
tag(:td, class: tgt.type) { tag(:pre) { content(tgt) } }
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
def tag(name, options = {}, &block)
|
154
|
+
file.puts %(<#{name})
|
155
|
+
file.puts options.collect { |attribute, value| %(#{attribute}="#{value}") }
|
156
|
+
file.puts '>'
|
157
|
+
yield
|
158
|
+
file.puts "</#{name}>"
|
159
|
+
end
|
160
|
+
|
161
|
+
def content(inner_text)
|
162
|
+
file.puts(inner_text.to_s == '' ? ' ' : inner_text)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class Text < Base
|
167
|
+
def format
|
168
|
+
pointer = 0
|
169
|
+
while pointer < target_output.size
|
170
|
+
size = 1
|
171
|
+
type = source_output[pointer].type
|
172
|
+
case type
|
173
|
+
when :added
|
174
|
+
added(pointer, size = get_block_size(pointer, :added))
|
175
|
+
when :deleted
|
176
|
+
deleted(pointer, size = get_block_size(pointer, :deleted))
|
177
|
+
when :changed
|
178
|
+
changed(pointer, size = get_block_size(pointer, :changed))
|
179
|
+
end
|
180
|
+
file.puts unless type == :unchanged
|
181
|
+
pointer += size
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def get_block_size(pointer, type)
|
188
|
+
size = 1
|
189
|
+
size += 1 while target_output[pointer + size].type == type
|
190
|
+
size
|
191
|
+
end
|
192
|
+
|
193
|
+
def added(pointer, size)
|
194
|
+
file.puts(target_output[pointer].original_number)
|
195
|
+
0.upto(size - 1) { |i| file.puts("+ #{target_output[pointer + i]}") }
|
196
|
+
end
|
197
|
+
|
198
|
+
def deleted(pointer, size)
|
199
|
+
file.puts(source_output[pointer].original_number)
|
200
|
+
0.upto(size - 1) { |i| file.puts("- #{source_output[pointer + i]}") }
|
201
|
+
end
|
202
|
+
|
203
|
+
def changed(pointer, size)
|
204
|
+
file.puts("#{source_output[pointer].original_number},#{target_output[pointer].original_number}")
|
205
|
+
0.upto(size - 1) { |i| file.puts("source<< #{source_output[pointer + i]}") }
|
206
|
+
file.puts('=======')
|
207
|
+
0.upto(size - 1) { |i| file.puts("target>> #{target_output[pointer + i]}") }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|