sal-tools-analyze 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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