dbc 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -42,7 +42,7 @@ opts = GetoptLong.new(
42
42
  [ "--output", "-o", GetoptLong::REQUIRED_ARGUMENT ],
43
43
  # cc compatibility options
44
44
  [ "--define", "-D", GetoptLong::REQUIRED_ARGUMENT ],
45
- [ "--include", "-I", GetoptLong::REQUIRED_ARGUMENT ]
45
+ [ "--include", "-I", GetoptLong::OPTIONAL_ARGUMENT ]
46
46
  )
47
47
 
48
48
  # initialize with defaults
@@ -50,6 +50,7 @@ dest_file = nil
50
50
  src_file = nil
51
51
  search_path = SearchPath.new
52
52
  defines = []
53
+ search_usr_include = true
53
54
 
54
55
  always_output = false
55
56
  check_level = nil
@@ -70,10 +71,15 @@ begin
70
71
  end
71
72
  when "--include"
72
73
  # should support including file in the future
73
- begin
74
- search_path << arg
75
- rescue
76
- opts.error($!)
74
+ if arg
75
+ begin
76
+ search_path.unshift(arg)
77
+ rescue
78
+ opts.error($!)
79
+ end
80
+ else
81
+ # -I with no argument means don't search /usr/include
82
+ search_usr_include = false
77
83
  end
78
84
  when "--define"
79
85
  unless arg =~ /\A([A-Za-z_]\w*)(?:\(([\w,\s]*)\))?(?:=(.*))?\Z/
@@ -168,12 +174,32 @@ else
168
174
  end
169
175
 
170
176
  ### Compatibility with various compilers ###
171
- search_path.unshift('/usr/include') if File.exists?('/usr/include')
172
- search_path.unshift(File.dirname(src_file)) if src_file
173
- # search for /usr/lib/gcc*/<system>/<version>/include
174
- Dir['/usr/lib/gcc*/*/*/include'].each do |gcc_inc|
175
- search_path << gcc_inc if File.directory?(gcc_inc)
177
+
178
+ # the following are added to the end of the search path
179
+ if search_usr_include
180
+ if File.exists?('/usr/include')
181
+ search_path << '/usr/include'
182
+ # search for /usr/lib/gcc*/<system>/<version>/include
183
+ Dir['/usr/lib/gcc*/*/*/include'].each do |gcc_inc|
184
+ search_path << gcc_inc if File.directory?(gcc_inc)
185
+ end
186
+ else
187
+ if env_include = ENV['INCLUDE']
188
+ env_include.split(';').each do |p|
189
+ # any anci c installation should have stdlib.h or stdio.h
190
+ if File.exists?(File.join(p, 'stdlib.h'))
191
+ search_path << p
192
+ end
193
+ end # each
194
+ end
195
+ end # if File.exists?('/usr/include')
176
196
  end
197
+
198
+ search_path_limited = search_path.dup
199
+ # Add directory of file to the begining of the search_path
200
+ # search_path_limited does not include the directory of the file being parsed
201
+ search_path.unshift( src_file ? File.dirname(src_file) : '.' )
202
+
177
203
  case RUBY_PLATFORM
178
204
  when /i[0-9]86|cygwin|mingw/
179
205
  defines << ['__i386__', nil, nil]
@@ -181,8 +207,11 @@ case RUBY_PLATFORM
181
207
  # experiance may vary :)
182
208
  defines << ['__GLIBC_HAVE_LONG_LONG', nil, '1']
183
209
  defines << ['__extension__', nil, ' ']
210
+ defines << ['__inline__', nil, ' ']
184
211
  when /powerpc|darwin/
185
212
  defines << ['__ppc__', nil, nil]
213
+ else
214
+ warn "unrecognized platform: #{RUBY_PLATFORM}"
186
215
  end
187
216
  # for gcc 3.4+ compatibility
188
217
  defines << ['__builtin_va_list', nil, 'int *']
@@ -191,9 +220,6 @@ defines << ['SHLIB_COMPAT', ['arg'], '(0)']
191
220
  defines << ['__STDC__', nil, '1']
192
221
  #############################################
193
222
 
194
- # included files
195
- includes = {}
196
-
197
223
  # Cache Tokens => Preprocessor => Parse OCL => Parse C Types
198
224
  # Cached tokens are output.
199
225
  if not docs and check_level == DBC::NONE
@@ -204,17 +230,10 @@ else
204
230
  out_str = DBC.parse_docs(CTokenizer::Lexer.new(text, src_file))
205
231
  elsif preprocess_only
206
232
  out_str = ''
207
- preproc = Preprocessor::Parser.new(text, src_file) do |f|
208
- if inc_text = includes[f]
209
- inc_text
210
- else
211
- begin
212
- File.open(search_path.find(f)) { |in_f| includes[f] = in_f.read }
213
- rescue ArgumentError
214
- preproc.error($!)
215
- end
216
- end
217
- end
233
+ preproc = Preprocessor::Parser.new( search_path,
234
+ search_path_limited,
235
+ text, src_file )
236
+
218
237
  defines.each { |d,p,v| preproc.define(d, p, v) }
219
238
  preproc.each do |t|
220
239
  out_str << t[1]
@@ -224,20 +243,10 @@ else
224
243
  # cache statements
225
244
  cache = DBC::Cache.new(text, src_file)
226
245
  # preprocesses all tokens
227
- preproc = Preprocessor::Parser.new(cache) do |f|
228
- # open included files
229
- if inc_text = includes[f]
230
- inc_text
231
- else
232
- begin
233
- File.open(search_path.find(f)) { |in_f| includes[f] = in_f.read }
234
- rescue ArgumentError
235
- preproc.error($!)
236
- end
237
- end
238
- end
246
+ preproc = Preprocessor::Parser.new(search_path, search_path_limited, cache)
247
+
239
248
  # define tokens passed
240
- defines.each { |d,p,v| preproc.define(d, p, v) }
249
+ defines.each { |d| preproc.define(*d) }
241
250
 
242
251
  # extracts DBC condtions
243
252
  source = DBC::OCLParser.new(preproc)
@@ -40,10 +40,10 @@ module CTokenizer
40
40
  #FLOAT = %r(#{FLOAT_1}|#{FLOAT_2}|#{FLOAT_3})
41
41
  FLOAT = %r(#{FLOAT_1}|#{FLOAT_2})
42
42
 
43
- i_s = /[uU]?[lL]|[lL][uU]?/
44
- INTEGER_1 = /0[xX][0-9a-fA-F]+#{i_s}?/
45
- INTEGER_2 = /0[0-7]+#{i_s}?/
46
- INTEGER_3 = /[0-9]+#{i_s}?/
43
+ i_s = /[uUlL]*/
44
+ INTEGER_1 = /0[xX][0-9a-fA-F]+#{i_s}/
45
+ INTEGER_2 = /0[0-7]+#{i_s}/
46
+ INTEGER_3 = /[0-9]+#{i_s}/
47
47
  INTEGER = %r(#{INTEGER_1}|#{INTEGER_2}|#{INTEGER_3})
48
48
  end # Expression
49
49
 
@@ -146,6 +146,7 @@ module CTokenizer
146
146
  when m = scan(Expression::COMMENT)
147
147
  @line += CTokenizer.line_count(m)
148
148
  [:COMMENT, m]
149
+ # SYMBOL should come before INTEGER and FLOAT
149
150
  when m = scan(Expression::SYMBOL)
150
151
  [:SYMBOL, m]
151
152
  when m = scan(Expression::NEWLINE)
@@ -69,7 +69,7 @@ module CType
69
69
 
70
70
  def CType.[]=(val, new_val)
71
71
  raise "expecting a String got #{val.class}" if val.class != String
72
- raise "type #{val} already defined" if @@typedefs.include?(val)
72
+ raise ParseError, "type #{val} already defined" if @@typedefs.include?(val)
73
73
  @@typedefs[val] = new_val
74
74
  end
75
75
 
@@ -601,7 +601,7 @@ module CType
601
601
 
602
602
  class Parser < Racc::Parser
603
603
 
604
- module_eval <<'..end src/ctype.y modeval..idb337f077e4', 'src/ctype.y', 1137
604
+ module_eval <<'..end src/ctype.y modeval..idcee92c23da', 'src/ctype.y', 1137
605
605
 
606
606
  def parse(str, file=nil, line=1)
607
607
  @tokens = CTokenizer::CLexer.new(str, file, line)
@@ -640,7 +640,7 @@ protected
640
640
  t
641
641
  end
642
642
 
643
- ..end src/ctype.y modeval..idb337f077e4
643
+ ..end src/ctype.y modeval..idcee92c23da
644
644
 
645
645
  ##### racc 1.4.4 generates ###
646
646
 
@@ -16,7 +16,7 @@ module Preprocessor
16
16
 
17
17
  class Define < Racc::Parser
18
18
 
19
- module_eval <<'..end src/define.y modeval..id2247533106', 'src/define.y', 75
19
+ module_eval <<'..end src/define.y modeval..idbc0a52f69c', 'src/define.y', 75
20
20
 
21
21
  def initialize(params, tokens)
22
22
  if params and not params.class == Parameters
@@ -87,7 +87,7 @@ protected
87
87
  @q.shift
88
88
  end
89
89
 
90
- ..end src/define.y modeval..id2247533106
90
+ ..end src/define.y modeval..idbc0a52f69c
91
91
 
92
92
  ##### racc 1.4.4 generates ###
93
93
 
@@ -413,7 +413,7 @@ module OCL
413
413
 
414
414
  class Parser < Racc::Parser
415
415
 
416
- module_eval <<'..end src/ocl.y modeval..id459cfd0b09', 'src/ocl.y', 849
416
+ module_eval <<'..end src/ocl.y modeval..ida1d027bef5', 'src/ocl.y', 849
417
417
 
418
418
  def Parser.reserved_word?(str)
419
419
  str =~ /\A(?:context|forall|exists|in|and|or|implies|not|xor)\Z/
@@ -511,7 +511,7 @@ protected
511
511
  t
512
512
  end
513
513
 
514
- ..end src/ocl.y modeval..id459cfd0b09
514
+ ..end src/ocl.y modeval..ida1d027bef5
515
515
 
516
516
  ##### racc 1.4.4 generates ###
517
517
 
@@ -72,7 +72,7 @@ module Preprocessor
72
72
 
73
73
  class ArgumentParser < Racc::Parser
74
74
 
75
- module_eval <<'..end src/parameters.y modeval..id1ab45e1c83', 'src/parameters.y', 144
75
+ module_eval <<'..end src/parameters.y modeval..id008fb4e411', 'src/parameters.y', 144
76
76
 
77
77
  def ArgumentParser.parse(tokens)
78
78
  self.new.parse(tokens)
@@ -103,7 +103,7 @@ protected
103
103
  end # case
104
104
  end
105
105
 
106
- ..end src/parameters.y modeval..id1ab45e1c83
106
+ ..end src/parameters.y modeval..id008fb4e411
107
107
 
108
108
  ##### racc 1.4.4 generates ###
109
109
 
@@ -118,22 +118,34 @@ module Preprocessor
118
118
  end
119
119
  end # Resolve
120
120
 
121
+ module FileMacro
122
+ def FileMacro.takes_args?; false end
123
+ def FileMacro.value(source); source.file.dup end
124
+ end
125
+
126
+ module LineMacro
127
+ def LineMacro.takes_args?; false end
128
+ def LineMacro.value(source); source.line.to_s end
129
+ end
130
+
121
131
  class Parser < CTokenizer::LexerBase
122
132
 
123
133
  include CTokenizer
124
134
  include Resolve
125
135
 
126
- def initialize(source, file=nil, line=1, &upon_include)
127
- @upon_include = upon_include
136
+ def initialize(search_path, search_path_limited, source, file=nil, line=1)
128
137
  if source.class <= String
129
138
  source = CTokenizer::Lexer.new(source, file, line)
130
139
  end
140
+
141
+ @search_path = search_path
142
+ @search_path_limited = search_path_limited
131
143
 
132
144
  @cond_comp = [true] # conditional compile is true at base
133
145
 
134
146
  @source = Tokens.new(source)
135
147
  @macro_tokens = CTokenizer::Lexer.new('', file, line)
136
- @defines = {}
148
+ @defines = { '__FILE__' => FileMacro, '__LINE__' => LineMacro }
137
149
  @resolving = {}
138
150
 
139
151
  @parser = StatementParser.new(@defines)
@@ -190,7 +202,24 @@ module Preprocessor
190
202
  end
191
203
 
192
204
  protected
193
- EMPTY_TOKEN = [:SPACE, ''].freeze
205
+ EMPTY_TOKEN = [:SPACE, ''.freeze].freeze
206
+
207
+ def include_file(file)
208
+ path = begin
209
+ if file =~ /\A"(.*)"\Z/
210
+ yield($1, @search_path)
211
+ elsif file =~ /\A<(.*)>\Z/
212
+ yield($1, @search_path_limited)
213
+ else
214
+ raise "impossible"
215
+ end
216
+ rescue ArgumentError
217
+ self.error($!)
218
+ end
219
+ str = File.open(path) { |f| f.read }
220
+ # could use *path* instead of *file* to give more info
221
+ @source.add_source( CTokenizer::Lexer.new(str, file) )
222
+ end
194
223
 
195
224
  # @macro_tokens is empty when we parse a statement
196
225
  def parse_statement
@@ -218,12 +247,13 @@ protected
218
247
  self.undef(result[1])
219
248
  when :INCLUDE
220
249
  # note: we don't keep track of recursive includes
221
- f = result[1]
222
- str = @upon_include.call(f)
223
- if str.class == String
224
- str = CTokenizer::Lexer.new(str, f)
250
+ include_file(result[1]) do |f, search_path|
251
+ search_path.find(f)
252
+ end
253
+ when :INCLUDE_NEXT
254
+ include_file(result[1]) do |f, search_path|
255
+ search_path.find_next(f)
225
256
  end
226
- @source.add_source(str) if str
227
257
  when :PRAGMA
228
258
  # ignore
229
259
  when :ERROR
@@ -259,10 +289,6 @@ protected
259
289
  end # if
260
290
  when :CLOSE
261
291
  @cond_comp.pop
262
- # for debugging
263
- #when :IGNORE
264
- #else
265
- # raise "impossible"
266
292
  end # case
267
293
 
268
294
  # eat rest of line unless token is a newline
@@ -283,7 +309,7 @@ module Preprocessor
283
309
 
284
310
  class StatementParser < Racc::Parser
285
311
 
286
- module_eval <<'..end src/preprocessor.y modeval..id895fa9d1fa', 'src/preprocessor.y', 708
312
+ module_eval <<'..end src/preprocessor.y modeval..idb767efdc5e', 'src/preprocessor.y', 734
287
313
 
288
314
  include Resolve
289
315
 
@@ -301,6 +327,14 @@ module_eval <<'..end src/preprocessor.y modeval..id895fa9d1fa', 'src/preprocesso
301
327
  @defines.member?(t)
302
328
  end
303
329
 
330
+ def file
331
+ @source.file
332
+ end
333
+
334
+ def line
335
+ @source.line
336
+ end
337
+
304
338
  def parse_ignore(tokens, ignore_all)
305
339
  @source = CTokenizer::CPLexer.new(tokens)
306
340
 
@@ -349,7 +383,7 @@ protected
349
383
  @macro_tokens
350
384
  end .scan(/.*?>/) # NOT multiline
351
385
  raise ParseError, "expecting '>'" unless f
352
- f.chop
386
+ "<#{f}"
353
387
  end
354
388
 
355
389
  # next_ignore and next_ignore_all are used to output the first token
@@ -414,7 +448,7 @@ protected
414
448
  t
415
449
  end
416
450
 
417
- ..end src/preprocessor.y modeval..id895fa9d1fa
451
+ ..end src/preprocessor.y modeval..idb767efdc5e
418
452
 
419
453
  ##### racc 1.4.4 generates ###
420
454
 
@@ -482,7 +516,7 @@ racc_reduce_table = [
482
516
  2, 67, :_reduce_60,
483
517
  1, 87, :_reduce_61,
484
518
  1, 87, :_reduce_62,
485
- 1, 88, :_reduce_63,
519
+ 1, 88, :_reduce_none,
486
520
  1, 88, :_reduce_64,
487
521
  2, 63, :_reduce_65,
488
522
  3, 63, :_reduce_66,
@@ -1569,7 +1603,7 @@ module_eval <<'.,.,', 'src/preprocessor.y', 150
1569
1603
 
1570
1604
  module_eval <<'.,.,', 'src/preprocessor.y', 155
1571
1605
  def _reduce_60( val, _values, result )
1572
- result = val[0,2]; self.set_nonspace
1606
+ result = val[0,2]
1573
1607
  result
1574
1608
  end
1575
1609
  .,.,
@@ -1588,12 +1622,7 @@ module_eval <<'.,.,', 'src/preprocessor.y', 166
1588
1622
  end
1589
1623
  .,.,
1590
1624
 
1591
- module_eval <<'.,.,', 'src/preprocessor.y', 170
1592
- def _reduce_63( val, _values, result )
1593
- val[0] =~ /\A"(.*)"\Z/; result = $1
1594
- result
1595
- end
1596
- .,.,
1625
+ # reduce 63 omitted
1597
1626
 
1598
1627
  module_eval <<'.,.,', 'src/preprocessor.y', 171
1599
1628
  def _reduce_64( val, _values, result )
@@ -5,36 +5,54 @@
5
5
 
6
6
  class SearchPath
7
7
  def SearchPath.check(p)
8
- if !File.exists?(p) or !File.directory?(p)
9
- raise "invalid search path: #{p}"
10
- end
8
+ raise "invalid search path: #{p}" unless File.directory?(p)
11
9
  end
12
10
  def initialize
13
11
  @paths = []
14
- end
15
- def add(path, check=true)
16
- SearchPath.check(path)
17
- @paths << path
12
+ @next_path = {}
18
13
  end
19
14
  def unshift(path)
20
15
  SearchPath.check(path)
21
16
  @paths.unshift(path)
22
17
  end
23
18
  def <<(path)
24
- self.add(path)
19
+ SearchPath.check(path)
20
+ @paths << path
25
21
  end
26
22
 
27
- def check
23
+ def find(file)
24
+ raise ArgumentError, "'#{file}' not found" \
25
+ unless f = self.find_in(@paths, file)
26
+ f
27
+ end
28
+ def find_next(file)
29
+ if next_paths = @next_path[file]
30
+ f = self.find_in(next_paths, file)
31
+ return f if f
32
+ end
33
+ # start the search over
34
+ self.find(file)
35
+ end
36
+
37
+ def dup
38
+ d = SearchPath.new
28
39
  @paths.each do |p|
29
- SearchPath.check(p)
40
+ d << p
30
41
  end
42
+ d
31
43
  end
32
- def find(file)
33
- dir = @paths.find do |inc_dir|
34
- File.exists?(File.join(inc_dir, file))
44
+
45
+ protected
46
+ def find_in(paths, file)
47
+ paths.each_with_index do |dir, i|
48
+ path = File.join(dir, file)
49
+ if File.exists?(path)
50
+ i += 1
51
+ @next_path[file] = @paths[i, @paths.length - i]
52
+ return path
53
+ end
35
54
  end
36
- raise ArgumentError, "'#{file}' not found" unless dir
37
- File.join(dir, file)
55
+ return nil
38
56
  end
39
57
  end
40
58
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.1
3
3
  specification_version: 1
4
4
  name: dbc
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.2.1
7
- date: 2004-11-05
6
+ version: 1.2.2
7
+ date: 2004-11-10
8
8
  summary: Design by Contract (DBC) for C
9
9
  require_paths:
10
10
  - lib