sal-tools-analyze 0.0.1

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.
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ M. Ehehalt (flynn42ryder@rubyforge.org)
data/README ADDED
@@ -0,0 +1,20 @@
1
+ = sal-tools - A library for the analyze of SAL code
2
+
3
+ == SYNOPSIS
4
+
5
+ This library gives the basic functionality to analyse Gupta source code.
6
+ Copyright (c)2007-2011 by Michael Ehehalt
7
+ Error and feature list at the end of the document
8
+
9
+ == Other stuff
10
+
11
+ Author:: M. Ehehalt <flynn42ryder@rubyforge.org>
12
+ License:: Copyright (C) 2007, 2008, ... M. Ehehalt
13
+ Released under the GNU GPL 2 license
14
+
15
+ == Warranty
16
+
17
+ This program is distributed in the hope that it will be useful,
18
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ GNU General Public License for more details.
data/lib/sal/class.rb ADDED
@@ -0,0 +1,43 @@
1
+ require_relative "item.rb"
2
+
3
+ module Sal
4
+
5
+ # The class repressents a class in the code
6
+ class Class
7
+
8
+ def initialize( item )
9
+ @item = item
10
+ item.code.chomp =~ /^(.*? Class): (.*)$/
11
+ @type = $1
12
+ @name = $2
13
+ @functions = nil
14
+ end
15
+
16
+ attr_accessor :name, :item, :type
17
+
18
+ # Getter for the functions (lazy loading)
19
+ def functions
20
+ if( @functions.nil? )
21
+ _analyze
22
+ end
23
+ return @functions
24
+ end
25
+
26
+ private
27
+
28
+ def _analyze
29
+ @functions = []
30
+
31
+ @item.childs.each do | item |
32
+ if(item.level == 4 and item.code.start_with? "Functions")
33
+ item.childs.each do | item |
34
+ @functions << item if item.code.start_with? "Function"
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
data/lib/sal/code.rb ADDED
@@ -0,0 +1,236 @@
1
+ require "ostruct"
2
+
3
+ require_relative "externalfunction.rb"
4
+ require_relative "external.rb"
5
+ require_relative "format.rb"
6
+ require_relative "item.rb"
7
+ require_relative "library.rb"
8
+ require_relative "version.rb"
9
+
10
+ module Sal
11
+
12
+ # The class code represent the complete code from a sal file.
13
+ # You can analyze the code now through the items, the libraries, ...
14
+ # Only code in text format could be analyzed
15
+ class Code
16
+
17
+ # Initialize Code with filename
18
+ # The sourcecode will read and the format and version are analysed
19
+ def initialize( filename )
20
+ read_code_from_file filename
21
+ get_format_and_version_from_code
22
+ end
23
+
24
+ # Save the items of code back to disk
25
+ # Without parameters, the original file will be overridden
26
+ def save( new_filename = filename )
27
+ save_code_to_file new_filename
28
+ end
29
+
30
+ # Save the items of code back to disk in a new file
31
+ # Alias for save with a new filename
32
+ def save_as( new_filename )
33
+ save_code_to_file new_filename
34
+ end
35
+
36
+ attr_accessor :format, :filename, :version, :code
37
+
38
+ # Getter for the items (lazy loading)
39
+ def items
40
+ get_items_from_code if @items.nil?
41
+ @items
42
+ end
43
+
44
+ # Getter for the libraries (lazy loading)
45
+ def libraries
46
+ if @libraries.nil?
47
+ @libraries = Array.new
48
+ items.each do | item |
49
+ if( item.level == 2 and !item.parent.nil? and item.parent.code =~ /Libraries/)
50
+ @libraries << Library.new(item) unless item.commented?
51
+ end
52
+ end
53
+ end
54
+ return @libraries
55
+ end
56
+
57
+ # Add a new library to the libraries section in the code
58
+ def add_library(filename)
59
+ # .head 1 + Libraries
60
+ # .head 2 - File Include: qckttip.apl
61
+ # .head 2 - File Include: vt.apl
62
+ items.each do | item |
63
+ if( item.level == 1 and item.code =~ /Libraries/ )
64
+ include_item = item.copy
65
+ include_item.parent = item
66
+ include_item.childs = []
67
+ include_item.code = "File Include: #{filename}"
68
+ include_item.level = item.level + 1
69
+ @items.insert(@items.index(item) + 1, include_item)
70
+ item.childs.insert(0, include_item)
71
+ item.refresh_child_indicator
72
+ include_item.refresh_child_indicator
73
+ @libraries = nil
74
+ return include_item
75
+ end
76
+ end
77
+ end
78
+
79
+ # Getter for the externals (lazy loading)
80
+ def externals
81
+ if @externals.nil?
82
+ @externals = Array.new
83
+ items.each do | item |
84
+ if( item.level == 3 and !item.parent.nil? and item.parent.code =~ /External Functions/ )
85
+ @externals << External.new(item) unless item.commented?
86
+ end
87
+ end
88
+ end
89
+ return @externals
90
+ end
91
+
92
+ # Getter for the classes (lazy loading)
93
+ def classes
94
+ if @classes.nil?
95
+ @classes = []
96
+ items.each do | item |
97
+ if( item.level == 3 and !item.parent.nil? and item.parent.code.start_with?("Class Definitions") )
98
+ @classes << Class.new(item) unless item.commented?
99
+ end
100
+ end
101
+ end
102
+ return @classes
103
+ end
104
+
105
+ def to_s
106
+ @file_name
107
+ end
108
+
109
+ # Returns the current code from the items
110
+ def generated_code
111
+ new_code = ""
112
+ items.each do | item |
113
+ new_code += item.line
114
+ end
115
+ new_code
116
+ end
117
+
118
+ # Returns a short overview over the code (version, format, ...)
119
+ def display(smart = true)
120
+ disp = "#{File.basename @filename} "
121
+ disp += (smart ? "- " : ":\n")
122
+ disp += "Version = #{@version.td} "
123
+ disp += (smart ? "- " : "\n")
124
+ disp += "Format = #{@format}"
125
+ end
126
+
127
+ private
128
+
129
+ # Saves the current code
130
+ def save_code_to_file(new_filename)
131
+ fh = File.new(new_filename, "wb")
132
+ fh.write( items.join )
133
+ fh.close
134
+ end
135
+
136
+ # Read the code from the file and sets the filename
137
+ def read_code_from_file(filename)
138
+ @filename = filename
139
+ @code = IO.binread filename
140
+ end
141
+
142
+ # Analyzes the file format (normal, text, indented) and the version
143
+ def get_format_and_version_from_code
144
+ @format = Format::get_from_code @code
145
+ @version = Version::from_code @code
146
+ end
147
+
148
+ # Get the items from the code and generats the @items array
149
+ def get_items_from_code
150
+ @items = []
151
+ case format
152
+ when Format::TEXT
153
+ # _analyze_code_textmode
154
+ analyze_items Format::TEXT
155
+ when Format::INDENTED
156
+ # not realized at the moment
157
+ # _analyze_code_indented
158
+ # analyze_items Format::INDENTED
159
+ else
160
+ # Can't analyze indented and normal mode code
161
+ end
162
+ end
163
+
164
+ # Analyzes the source code
165
+ def analyze_items(format)
166
+ vars = analyze_init(format)
167
+ get_lines(vars)
168
+ vars.lines.each do | line |
169
+ if line.length > 0
170
+ vars.line = line
171
+ @items << get_item(vars)
172
+ end
173
+ end
174
+ end
175
+
176
+ # Initialization of the analyze, clears all infos
177
+ # As parameter communication an open struct is used
178
+ def analyze_init(format)
179
+ @items = Array.new
180
+ vars = OpenStruct.new
181
+ vars.counter = 0
182
+ vars.levels = Hash.new
183
+ vars.format = format
184
+ return vars
185
+ end
186
+
187
+ # The source code is splitted into lines
188
+ def get_lines(vars)
189
+ vars.lines = []
190
+ if(vars.format == Format::TEXT)
191
+ code_split_text vars
192
+ elsif(vars.format == Format::INDENTED)
193
+ # code_split_indented vars # not realized at the moment
194
+ end
195
+ end
196
+
197
+ # Split the source code into lines if source code is in text format
198
+ def code_split_text(vars)
199
+ lines = @code.split(/^\.head/)
200
+ lines.each do | line |
201
+ vars.lines << ".head#{line}" if line.length > 0
202
+ end
203
+ vars.lines
204
+ end
205
+
206
+ # Split the source code into lines if source code is in indented format
207
+ def code_split_indented(vars)
208
+ vars.lines = @code.split(/\n/)
209
+ vars.lines.collect { | line | line = line + "\n" }
210
+ end
211
+
212
+ # create the item
213
+ def get_item(vars)
214
+ # item = Item.new vars.line, vars.format
215
+ if(vars.format == Format::TEXT)
216
+ item = Item.new vars.line, vars.format
217
+ else
218
+ item = Item.new(vars.line, Format::INDENTED)
219
+ end
220
+ item.code_line_nr = vars.counter + 1
221
+ vars.levels[item.level] = item
222
+ if(item.level > 0 and vars.levels.count > 1)
223
+ begin
224
+ item.parent = vars.levels[item.level-1]
225
+ item.parent.childs << item
226
+ rescue
227
+ warn "filename = #{@filename}"
228
+ end
229
+ end
230
+ vars.counter += 1 # Bei Textmode war vorher: item_counter = item_counter + code_line.split('\n').length
231
+ item
232
+ end
233
+
234
+ end
235
+
236
+ end
@@ -0,0 +1,35 @@
1
+ module Sal
2
+
3
+ # Checks if the code line to test is a line of code or other stuff (window parameters, ...)
4
+ module Command
5
+
6
+ @@commands = {
7
+ :break => "Break",
8
+ :call => "Call",
9
+ :case => "Case", # => Select Case
10
+ :default => "Default", # => Select Case
11
+ :else => "Else",
12
+ :else_if => "Else If",
13
+ :if => "If",
14
+ :loop => "Loop",
15
+ :on => "On",
16
+ :return => "Return",
17
+ :select_case => "Select Case",
18
+ :set => "Set",
19
+ :when => "When",
20
+ :while => "While"
21
+ }
22
+
23
+ # Checks if the line of code is code or other stuff
24
+ # with using of the @@commands array, that includes
25
+ # the source code starts
26
+ def Command.is_code_line?(line)
27
+ @@commands.each_value do | command |
28
+ return true if line.start_with? "#{command} "
29
+ end
30
+ return false
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,37 @@
1
+ require_relative "item.rb"
2
+
3
+ module Sal
4
+
5
+ # The class represent an included external library (dll)
6
+ class External
7
+
8
+ def initialize( item )
9
+ @item = item
10
+ @name = item.code.gsub(/Library name: /,"")
11
+ @functions = nil
12
+ end
13
+
14
+ attr_accessor :name, :item
15
+
16
+ # Getter of the dll functions (lazy loading)
17
+ def functions
18
+ if( @functions.nil? )
19
+ _analyze
20
+ end
21
+ return @functions
22
+ end
23
+
24
+ private
25
+
26
+ def _analyze
27
+ @functions = Array.new
28
+ @item.childs.each do | item |
29
+ if item.code =~ /Function: /
30
+ @functions << ExternalFunction.new( self, item )
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,46 @@
1
+ require_relative "item.rb"
2
+ require_relative "external.rb"
3
+
4
+ module Sal
5
+
6
+ # This class represent an external function as chilf from the external
7
+ # library (dll)
8
+ class ExternalFunction
9
+
10
+ def initialize( external, item )
11
+ @external = external
12
+ @item = item
13
+ @name = nil
14
+ @ordinal = -1
15
+ @parameters = Array.new
16
+
17
+ #@appears = 0
18
+ #@defs = Array.new
19
+ #@calls = Hash.new # hash with files whith a child code line array
20
+
21
+ _analyze
22
+ @key = @external.name + "::" + @name
23
+ end
24
+
25
+ attr_accessor :external, :item , :name, :ordinal, :key, :parameters # :appears, :defs, :calls
26
+
27
+ private
28
+
29
+ def _analyze
30
+ @name = $1 if @item.code =~ /Function: (.*)$/
31
+ @item.childs.each do | child |
32
+ # ordinal number
33
+ @ordinal = $1.to_i if child.code =~ /Export Ordinal: (\d+)/
34
+
35
+ # parameter
36
+ if child.level == 5 and child.code =~ /Parameters/
37
+ child.childs.each do | parameter |
38
+ @parameters << parameter unless parameter.commented?
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
data/lib/sal/format.rb ADDED
@@ -0,0 +1,43 @@
1
+ module Sal
2
+
3
+ # Analyzes the file format from the sal sourcecode
4
+ # The result is one of the constantsTEXT, NORMAL or INDENTED.
5
+ module Format
6
+
7
+ TEXT = :t
8
+ NORMAL = :n
9
+ INDENTED = :i
10
+
11
+ # Analyzes the file format for the given chunk of code
12
+ def Format.get_from_code( code )
13
+ if(code =~ /Outline Version - \d\.\d\.(\d\d)/m)
14
+ if(code =~ /^\.head/)
15
+ return Format::TEXT
16
+ else
17
+ return Format::INDENTED
18
+ end
19
+ else
20
+ return Format::NORMAL
21
+ end
22
+ end
23
+
24
+ # Analyzes the file format for the file with the given filename
25
+ # The file is read and the source code sends to the method get_from_code
26
+ def Format.get_from_file( filename )
27
+ code = IO.binread(filename)
28
+ return get_from_code( code )
29
+ end
30
+
31
+ def Format.get_from_line( line )
32
+ if(line.start_with? ".head")
33
+ return Format::TEXT
34
+ elsif(line.start_with? "Application Description" or line.start_with? "\t")
35
+ return Format::INDENTED
36
+ else
37
+ return Format::NORMAL
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end