dbc 1.2.1 → 1.2.2

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.
@@ -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