source: azure_iot_hub/trunk/asp3_dcre/tecsgen/tecsmerge.rb@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 22.7 KB
RevLine 
[388]1#! /usr/bin/env ruby
2# -*- coding: utf-8 -*-
3
4#
5# TECS merger
6# Merger for TECS generated templates
7#
8# Copyright (C) 2008-2017 by TOPPERS Project
9#--
10# 上記著作権者
11は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
12# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13# 変・再é…
14å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
15# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17# スコード中に含まれていること.
18# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19# 用できる形で再é…
20å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
21å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
22# 者
23マニュアルなど)に,上記の著作権表示,この利用条件および下記
24# の無保証規定を掲載すること.
25# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
26# 用できない形で再é…
27å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
28# と.
29# (a) 再é…
30å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
31マニュアルなど)に,上記の著
32# 作権表示,この利用条件および下記の無保証規定を掲載すること.
33# (b) 再é…
34å¸ƒã®å½¢æ…
35‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
36# 報告すること.
37# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
38# 害からも,上記著作権者
39およびTOPPERSプロジェクトをå…
40è²¬ã™ã‚‹ã“と.
41# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
42# 由に基づく請求からも,上記著作権者
43およびTOPPERSプロジェクトを
44# å…
45è²¬ã™ã‚‹ã“と.
46#
47# 本ソフトウェアは,無保証で提供されているものである.上記著作権者
48お
49# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
50# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
51# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
52# の責任を負わない.
53#
54# $Id$
55#++
56
57#= tecsgen : TECS のマージャ
58#
59#Authors:: 大山 博司
60#Version::
61#Copyright:: Copyright (C) TOPPERS Project, 2008-2017. All rights reserved.
62#License:: TOPPERS ライセンスに準拠
63
64=begin
65tecsmerge はテンプレートファイルをå…
66ƒã«ä½œæˆã•ã‚ŒãŸã‚»ãƒ«ã‚¿ã‚¤ãƒ—コード(含インライン関数を記述したセルタイプインラインヘッダ)を保守するものである。
67セルタイプに以下の改変が加えられた場合に対応する。
68・受け口関数が増えた
69・受け口の名前が変更された
70・受け口関数の名前が変更された
71
72% tecsmerge source_dir dest_dir
73% tecsmerge source_files dest_dir
74
75% tecsmerge -p port_name -f old_name:new_name source_file dest_dir
76% tecsmerge -p old_name:new_name source_file dest_dir
77
78source_file の名前は _teml.c, _templ.h で終わっていなくてはならない
79dest_file は source_file の _templ を取り除いた名前でなくてはならない
80dest_file が存在しない場合、_templ を取り除いた名前でコピーするだけである
81
82以下のキーワードを 含む行を探す
83
840) å…
85ˆé ­
861) /* #[<PREAMBLE>]#,
872) * #[</PREAMBLE>]#
883) /* #[<ENTRY_PORT>]#
894) * #[</ENTRY_PORT>]#
905) /* #[<ENTRY_FUNC>]#
916) { # new mode (function header is changed)
92 * #[/<ENTRY_FUNC>]# # when --old-mode
93 * #[/ENTRY_FUNC>]# # for Bug compatibility
947) /* #[<POSTAMBLE>]#
958) * #[</POSTAMBLE>]#
969) 終わり
97
98上記のうち 1), 3), 5), 7) を開始キーワードと呼ぶ。
99なお、特に断りのない場合、9) も開始キーワードに含む。
100
101名前の変更
102
103a) 受け口名の変更
104
105 -p old_port_name:new_port_name
106
107b) 受け口関数名の変更
108
109 -f old_port_name:new_port_name
110
111 old_port_name, new_port_name は、次の形式でなくてはならない。
112
113 受け口名 + '_' + 関数名
114
115
116i) ヘッダ1
117
118 0) と開始キーワードの間
119
120ii) ヘッダ2
121
122 1) と開始キーワードの間
123
124通常、これが複数存在することはないが、複数存在した場合、すべてファイル
125のå…
126ˆé ­ã«å‡ºåŠ›ã•ã‚Œã‚‹ã€‚
127
128iii) 受け口ヘッダ
129
130 3) と開始キーワードの間
131
132受け口ヘッダは、後続の受け口関数の受け口を表すものと仮定される。
133受け口ヘッダは、重要ではない。
134
135iv) 受け口関数
136
137 5) と開始キーワードの間
138
139=end
140
141require 'optparse'
142$n_err = 0
143$b_show = false
144$b_exist = false # コピーå…
145ˆã«ãƒ•ã‚¡ã‚¤ãƒ«ãŒã‚る場合のみマージ
146$old_mode = false # old_mode (関数本体として /<ENTRY_FUNC> の代わりに '{' を使う
147
148#2.0
149def write_array( file, array )
150 array.each{ |line|
151 file.write line
152 }
153end
154
155class PortRenamer
156 @@port_renamer_list = {}
157 @@port_renamer_current = nil
158
159 def initialize( old_port_name, new_port_name )
160 old_port_name = old_port_name.to_sym
161 if new_port_name then
162 new_port_name = new_port_name.to_sym
163 end
164 # p "port_renamer: #{old_port_name}"
165 @@port_renamer_list[old_port_name] = self
166 @@port_renamer_current = self
167 @old_port_name = old_port_name
168 @new_port_name = new_port_name
169 @func_renamer_list = {}
170 end
171
172 def self.add_func( old_name, new_name )
173 # p "add_func: #{old_name}"
174 if @@port_renamer_current == nil then
175 STDERR.puts( "error: #{old_name}: specify -p before -f" )
176 n_err += 1
177 else
178 @@port_renamer_current.add_func( old_name, new_name )
179 end
180 end
181
182 def add_func( old_name, new_name )
183 old_name = old_name.to_sym
184 new_name = new_name.to_sym
185 if @func_renamer_list[old_name] then
186 STDERR.puts( "error: #{old_name}: duplicate in port #{@old_port_name}" )
187 $n_err += 1
188 elsif old_name == new_name then
189 STDERR.puts( "error: #{old_name}: old and new are the same name" )
190 $n_err += 1
191 end
192 @func_renamer_list[old_name] = new_name
193 end
194
195 def self.show
196 if @@port_renamer_list then
197 @@port_renamer_list.each { |pr,pc|
198 pc.show
199 }
200 end
201 end
202
203 def self.get_list
204 @@port_renamer_list
205 end
206
207 attr_accessor :old_port_name, :new_port_name, :func_renamer_list
208
209 def show
210 print "port: #{@old_port_name}"
211 if @new_port_name then
212 print " => #{@new_port_name}"
213 end
214 puts ""
215
216 @func_renamer_list.each { |old,new|
217 print " func: #{old} => #{new}\n"
218 }
219 end
220end
221
222
223class CDLContents
224 #@head:: [string]
225 #@preamble_comment:: [string]
226 #@preamble_body:: [string]
227 #@entry_port:: {ep_name=>CDLEntryPort}
228 #@entry_port_array:: [CDLEntryPort]
229 #@postamble_comment::[string]
230 #@postamble_body:: [string]
231
232 @@DELIMITERS = {
233 # state => [ regexp_original, [previous states] , Regexp ]
234 :HEAD => [ "#[<BeginingOfFile>]#", [] ],
235 :PREAMBLE_COMMENT => [ "/* #[<PREAMBLE>]#", [:HEAD] ],
236 :PREAMBLE_BODY => [ " * #[</PREAMBLE>]#", [:PREAMBLE_COMMENT] ],
237 :ENTRY_COMMENT => [ "/* #[<ENTRY_PORT>]# PORT_NAME", [:PREAMBLE_BODY, :ENTRY_FUNC_BODY, :ENTRY_FUNC_BODY2] ],
238 :ENTRY_BODY => [ " * #[</ENTRY_PORT>]#", [:ENTRY_COMMENT] ],
239 :ENTRY_FUNC_COMMENT => [ "/* #[<ENTRY_FUNC>]# FUNC_NAME", [:ENTRY_BODY, :ENTRY_FUNC_BODY, :ENTRY_FUNC_BODY2] ],
240 :POSTAMBLE_COMMENT => [ "/* #[<POSTAMBLE>]#", [:ENTRY_FUNC_BODY, :ENTRY_FUNC_BODY2, :PREAMBLE_BODY] ],
241 :POSTAMBLE_BODY => [ " * #[</POSTAMBLE>]#", [:POSTAMBLE_COMMENT] ],
242 :EOF => [ "#[</EndOfFile>]#", [:POSTAMBLE_BODY,:ENTRY_FUNC_BODY, :ENTRY_FUNC_BODY2, :PREAMBLE_BODY] ],
243 }
244
245 @@DELIMITERS_FUNC_BY_COMMENT = {
246 :ENTRY_FUNC_BODY => [ " * #[</ENTRY_FUNC>]#", [:ENTRY_FUNC_COMMENT] ],
247 :ENTRY_FUNC_BODY2 => [ " * #[/ENTRY_FUNC>]#", [:ENTRY_FUNC_COMMENT] ], # for Bug compatibility
248 }
249
250 @@DELIMITERS_FUNC_BY_BRACKET = {
251 :ENTRY_FUNC_BODY => [ "\\\{", [:ENTRY_FUNC_COMMENT] ],
252 }
253
254 def self.rewrite_DELIMITERS delimiters
255 delimiters.each{ |stat, stat_info|
256 s = stat_info[0].gsub( /([\*\[\]])/, "\\\\\\1" ) # *, [, ] の前に \\ を挿å…
257¥
258 s.gsub!( /\s*\w*_NAME/, "\\s*(\\w*)" ) # ..._NAME を (w*) に変更
259 s = "^" + s # ^ をå…
260ˆé ­ã«æŒ¿å…
261¥
262 stat_info[2] = Regexp.new( s )
263 # p stat_info[2]
264 }
265 end
266
267 rewrite_DELIMITERS @@DELIMITERS
268 rewrite_DELIMITERS @@DELIMITERS_FUNC_BY_COMMENT
269 rewrite_DELIMITERS @@DELIMITERS_FUNC_BY_BRACKET
270
271 #=== モードに従い DELIMITERS に DELIMITERS_FUNC_BY_* をマージする
272 # mode :OLD_FUNC_BODY, :NEW_FUNC_BODY
273 def self.merge_DELIMITERS mode
274 case mode
275 when :OLD_FUNC_BODY
276 @@DELIMITERS.merge! @@DELIMITERS_FUNC_BY_COMMENT
277 when :NEW_FUNC_BODY
278 @@DELIMITERS.merge! @@DELIMITERS_FUNC_BY_BRACKET
279 else
280 raise "unknown mode"
281 end
282 end
283
284 #all_contents:: [string,...]
285 def initialize all_contents
286 part = []
287 line_no = 0
288 stat = :HEAD
289 arg = nil
290 port_name = nil
291 func_name = nil
292
293 @entry_port = {}
294 @entry_port_array = []
295
296 @head = []
297 @preamble_comment = []
298 @preamble_body = []
299 @postamble_comment = []
300 @postamble_body = []
301
302 (all_contents+[nil]).each{ |line| # nil: EOF
303 line_no += 1
304 # p "L: #{line}"
305 b_delim = false # デリミタキーワードの行
306 @@DELIMITERS.each { |next_stat,stat_info|
307
308 next if next_stat == :HEAD || ( next_stat == :EOF && line != nil )
309 # #1002 tecsmerge の非受け口関数 (POSTAMBLE部) の行頭に '{' があるとエラーになる
310 if (! $old_mode) && ( /^\{/ =~ line ) && ( stat == :PREAMBLE_BODY || stat == :POSTAMBLE_BODY )
311 p line + " next_stat=" + next_stat.to_s + "stat=" + stat.to_s
312 next
313 end
314
315 # p "R: #{stat_info[0]}"
316 if stat_info[2] =~ line || ( line == nil && next_stat == :EOF ) then
317 # p "D: #{line}: #{stat}"
318 b_delim = true
319
320 found = false
321 stat_info[1].each{ |prev_stat|
322 if stat == prev_stat then
323 found = true
324 end
325 }
326 if ! found then
327 STDERR.puts "error #{line_no}: unsuitable previous keyword"
328 STDERR.puts "error #{line_no}: previous: \"#{@@DELIMITERS[stat][0]}\""
329 STDERR.puts "error #{line_no}: current: \"#{@@DELIMITERS[next_stat][0]}\""
330 expect = ""; delim = ""
331 stat_info[1].each{ |prev_stat| expect = "#{expect+delim}\"#{@@DELIMITERS[prev_stat][0]}\""; delim = ", " }
332 STDERR.puts "error #{line_no}: suitable previous: #{expect}"
333 $n_err += 1
334 end
335
336 case stat
337 when :PREAMBLE_COMMENT, :ENTRY_COMMENT, :ENTRY_FUNC_COMMENT, :POSTAMBLE_COMMENT
338 part << line
339 end
340
341 case stat # 前の状æ…
342‹
343 when :HEAD
344 @head = part
345 when :PREAMBLE_COMMENT
346 @preamble_comment = part
347 when :PREAMBLE_BODY
348 @preamble_body = part
349 when :ENTRY_COMMENT
350 port_name = arg.to_sym
351 @entry_port[ port_name ] = CDLEntryPort.new
352 @entry_port_array << port_name
353 @entry_port[ port_name ].entry_comment = part
354 when :ENTRY_BODY
355 @entry_port[ port_name ].entry_body = part
356 when :ENTRY_FUNC_COMMENT
357 func_name = arg.to_sym
358 if @entry_port[ port_name ] then # nil なら既にエラー
359 @entry_port[ port_name ].entry_func_comment[ func_name ] = part
360 @entry_port[ port_name ].entry_func_array << func_name
361 end
362 when :ENTRY_FUNC_BODY, :ENTRY_FUNC_BODY2
363 if @entry_port[ port_name ] then # nil なら既にエラー
364 @entry_port[ port_name ].entry_func_body[ func_name ] = part
365 end
366 when :POSTAMBLE_COMMENT
367 @postamble_comment = part
368 when :POSTAMBLE_BODY
369 @postamble_body = part
370 else
371 raise "Unknown state #{stat}"
372 end
373
374 case next_stat
375 when :PREAMBLE_COMMENT, :ENTRY_COMMENT, :ENTRY_FUNC_COMMENT, :POSTAMBLE_COMMENT
376 part = [ line ]
377 else
378 part = []
379 end
380
381 stat = next_stat
382 arg = $1 # arg に取っておく
383 # p stat, arg
384 break
385 end
386 }
387
388 if ! b_delim then
389 part << line
390 end
391 }
392
393 end
394
395 def check template
396 # template にないものをチェック
397 @entry_port.each{ |port_name, entry_port|
398 temp_entry_port = template.entry_port[port_name]
399 if temp_entry_port == nil then
400 STDERR.puts "info: #{port_name} is deleted port"
401 next
402 end
403 # temp_entry_port.entry_func_body.each{ |f,b| p f }
404 entry_port.entry_func_body.each{ |func_name, func_body|
405 if temp_entry_port.entry_func_body[func_name] == nil then
406 STDERR.puts "info: #{func_name} is deleted function"
407 end
408 }
409 }
410 end
411
412 def rename
413
414 renamed_entry_port = {}
415 PortRenamer.get_list.each{ |pon,pr|
416
417 # 対象受け口を捜す
418 ep = @entry_port[pon]
419 if ep == nil then
420 STDERR.puts "warning: #{pon}: renaming port not found"
421 next
422 end
423
424 # ポートの rename
425 pnn = pr.new_port_name # 置換後の名前
426 if pnn then
427 # 置換する名前があれば、登録しなおす
428 renamed_entry_port[pnn] = @entry_port[pon]
429 @entry_port.delete pon
430 end
431
432 # 指定された関数の置換
433 renamed_func_comment = {}
434 renamed_func_body = {}
435 pr.func_renamer_list.each{ |old,new|
436 ofn = "#{pon}_#{old}".to_sym
437 nfn = "#{pon}_#{new}".to_sym
438 # p "fnn: #{ofn} #{nfn} #{pon}"
439 if ep.entry_func_comment[ofn] == nil then
440 STDERR.puts "warning: #{old}: renaming function not found"
441 next
442 end
443 ep.entry_func_array.map! { |fn|
444 # p fn, nfn, ofn, fn==ofn ? nfn : fn
445 fn==ofn ? nfn : fn
446 }
447 renamed_func_comment[nfn] = ep.entry_func_comment[ofn]
448 renamed_func_body[nfn] = ep.entry_func_body[ofn]
449 ep.entry_func_comment.delete ofn
450 ep.entry_func_body.delete ofn
451 }
452 ep.entry_func_comment.merge! renamed_func_comment
453 ep.entry_func_body.merge! renamed_func_body
454
455 # ポート名の変更による関数名の置換
456 renamed_func_comment = {}
457 renamed_func_body = {}
458 if pnn then
459 ep.entry_func_array.map! { |ofn|
460 nfn = ofn.to_s.sub( /#{pon.to_s}/, pnn.to_s ).to_sym
461 # p "pnn: #{ofn} #{nfn} #{pon} #{pnn}"
462 if nfn != ofn then
463 renamed_func_comment[nfn] = ep.entry_func_comment[ofn]
464 renamed_func_body[nfn] = ep.entry_func_body[ofn]
465 ep.entry_func_comment.delete ofn
466 ep.entry_func_body.delete ofn
467 nfn
468 else
469 ofn
470 end
471 }
472 ep.entry_func_comment.merge! renamed_func_comment
473 ep.entry_func_body.merge! renamed_func_body
474
475 # ep.entry_func_comment.each { |f,e| p "FF: #{f}" }
476 # ep.entry_func_array.each { |f,e| p "FA: #{f}" }
477 end
478 }
479 # p renamed_entry_port
480 @entry_port.merge! renamed_entry_port
481 end
482
483 def merge src
484 @head = src.head
485 @preamble_body = src.preamble_body
486 @postamble_body = src.postamble_body
487
488 @entry_port_array.each{ |port_name|
489 # p "merging #{port_name}"
490 entry_port = @entry_port[ port_name ]
491 src_entry_port = src.entry_port[port_name]
492 if src_entry_port == nil then
493 print "port merged: #{port_name}\n"
494 next
495 end
496 entry_port.entry_body = src_entry_port.entry_body
497 entry_port.entry_func_array.each{ |func_name|
498 # p "merging #{func_name}"
499 func_body = entry_port.entry_func_body[ func_name ]
500 if src_entry_port.entry_func_body[func_name] == nil then
501 print "func merged: #{func_name}\n"
502 next
503 end
504 print "func remained: #{func_name}\n"
505 # entry_port.entry_func_comment[func_name] = src_entry_port.entry_func_comment[func_name]
506 entry_port.entry_func_body[func_name] = src_entry_port.entry_func_body[func_name]
507 }
508 }
509 end
510
511 def write file
512#2.0 file.write @head
513 write_array( file, @head )
514#2.0 file.write @preamble_comment
515 write_array( file, @preamble_comment )
516#2.0 file.write @preamble_body
517 write_array( file, @preamble_body )
518 @entry_port_array.each{ |port_name| @entry_port[port_name].write file }
519#2.0 file.write @postamble_comment
520 write_array( file, @postamble_comment )
521#2.0 file.write @postamble_body
522 write_array( file, @postamble_body )
523 end
524
525 attr_accessor :head, :preamble_comment, :preamble_body, :entry_port, :postamble_body
526end
527
528class CDLEntryPort
529 #@entry_comment:: [string]
530 #@entry_body:: [string]
531 #@entry_func_comment:: {ep_func_name=>string}
532 #@entry_func_body:: {ep_func_name=>string}
533 #@entry_func_array:: [string]
534
535 def initialize
536 @entry_comment = []
537 @entry_body = []
538 @entry_func_comment = {}
539 @entry_func_body = {}
540 @entry_func_array = []
541 end
542
543 def write file
544#2.0 file.write @entry_comment
545 write_array( file, @entry_comment )
546#2.0 file.write @entry_body
547 write_array( file, @entry_body )
548 @entry_func_array.each{ |fnm|
549 # p @entry_func_comment[fnm][0]
550
551#2.0 file.write @entry_func_comment[fnm]
552 write_array( file, @entry_func_comment[fnm] )
553#2.0 file.write @entry_func_body[fnm]
554 write_array( file, @entry_func_body[fnm] )
555 }
556 end
557
558 attr_accessor :entry_comment, :entry_body, :entry_func_comment, :entry_func_body, :entry_func_array
559end
560
561def merge( src_file, dst_dir )
562 unless src_file =~ /(.*)_templ(.[ch])$/ then
563 STDERR.puts( "error: #{src_file}: not end with _templ.c/h" )
564 exit 1
565 end
566
567 fname = "#{$1}#{$2}"
568 dst_file = "#{dst_dir}/#{File.basename fname}"
569 if FileTest.file?( dst_file ) then
570 print( "merging #{src_file} to #{dst_file}\n" )
571 # dst_file の読込み
572 begin
573 dst = open( dst_file )
574#2.0
575 set_encoding dst
576 old_contents = dst.readlines
577 rescue
578 STDERR.puts "error: cannot open #{dst_file}"
579 $n_err += 1
580 exit 1
581 ensure
582 dst.close
583 end
584 old = CDLContents.new( old_contents )
585
586 # template の読込み
587 begin
588 src = open( src_file )
589#2.0
590 set_encoding src
591 new_contents = src.readlines
592 rescue
593 STDERR.puts "error: cannot open #{src_file}"
594 $n_err += 1
595 exit 1
596 ensure
597 src.close
598 end
599 templ = CDLContents.new( new_contents )
600
601 old.rename
602 error_check dst_file, 1
603
604 old.check templ
605 error_check dst_file, 2
606
607 templ.merge old
608 error_check dst_file, 3
609
610 bkup_file = rename_dst( dst_file )
611
612 begin
613 dst = open( dst_file, "w" )
614#2.0
615 set_encoding dst
616 templ.write dst
617 ensure
618 dst.close
619 end
620
621 elsif $b_exist == false then
622 # src_file を dst_file へコピー
623 begin
624 src = File.open( src_file )
625#2.0
626 set_encoding src
627 contents = src.readlines
628 rescue
629 print "#{src_file}: fail to read\n"
630 ensure
631 src.close
632 end
633
634 begin
635 dst = File.open( dst_file, "w" )
636 set_encoding dst
637#2.0 dst.write( contents )
638 contents.each{ |line|
639 dst.print line
640 }
641 rescue
642 print "#{dst_file}: fail to write\n"
643 ensure
644 dst.close
645 end
646 else
647 print "info: #{dst_file} skipped\n"
648 end
649end
650
651def error_check dst_file, level
652 if $n_err > 0 then
653 STDERR.puts "=== #{dst_file} not generated because of error ==="
654 exit level
655 end
656end
657
658
659#=== ファイルのエンコーディングを ASCII-8BIT に変更
660# Ruby 1.9 以上の場合に変更
661def set_encoding file
662 if RUBY_VERSION >= "1.9.0" then
663 file.set_encoding "ASCII-8BIT"
664 end
665end
666
667#=== rename_dst
668# dst_file のバックアップファイル名を決定し、リネームする
669# 成功すれば、リネーム後のファイル名を返す
670# dst_file が存在しなければ(リネームは行われず)nil を返す。
671def rename_dst( dst_file )
672 begin
673 File.stat dst_file
674 rescue
675 STDERR.puts( "info: backup not generated for #{dst_file}" )
676 # なければ終わり
677 return nil
678 end
679
680 i = 0
681 found = true
682 while found == true
683 begin
684 i = i + 1
685 bkup_file = "#{dst_file}_#{i}"
686 File.stat bkup_file
687 rescue
688 found = false
689 end
690 end
691
692 begin
693 File.rename( dst_file, bkup_file )
694 STDERR.puts( "info: backup generated for #{dst_file} to #{bkup_file}" )
695 return bkup_file
696 rescue
697 STDERR.puts( "error: fail to rename backup file: #{bkup_file}" )
698 exit 1
699 end
700
701 return nil
702end
703
704ARGV.options {|parser|
705 parser.banner =<<EOT
706Usage: tecsmerge [options] files_templ.c src_dir
707 tecsmerge [options] gen_dir src_dir
708EOT
709 parser.on('-e', '--exist-only', "merge if exist in destination directory") { |fs|
710 $b_exist = true
711 }
712 parser.on('-p', '--port=old_name:new_name', "specify entry port name change") { |ps|
713 p = ps.split( ':' )
714 PortRenamer.new( p[0], p[1] )
715 }
716 parser.on('-f', '--func=old_name:new_name', "specify entry function name change") { |fs|
717 f = fs.split( ':' )
718 PortRenamer.add_func( f[0], f[1] )
719 }
720 parser.on('-s', '--show_change_set', "show change set. all substitute") {
721 $b_show = true
722 }
723 parser.on('-o', '--old-mode', "old mode (function head not substituted)") { |fs|
724 $old_mode = true
725 }
726 parser.version = #{$version}
727 parser.release = nil
728 parser.parse!
729# if ARGV.empty?
730 if ARGV.length < 2 then
731 puts parser.help
732 exit 1
733 end
734}
735
736if $b_show then
737 PortRenamer.show
738end
739
740if $old_mode then
741 CDLContents.merge_DELIMITERS :OLD_FUNC_BODY
742else
743 CDLContents.merge_DELIMITERS :NEW_FUNC_BODY
744end
745
746if $n_err > 0 then
747 STDERR.puts( "#{$n_err} errors" )
748 exit 1
749end
750
751src = ARGV[0,ARGV.length-1]
752dst = ARGV[-1]
753
754begin
755 stat = File.stat dst
756rescue
757 STDERR.puts( "error: #{dst}: not found" )
758 exit 1
759ensure
760 if stat && ! stat.directory? then
761 STDERR.puts( "error: #{dst}: not directory" )
762 exit 1
763 end
764end
765
766src.each { |s|
767 begin
768 stat = File.stat s
769 rescue
770 STDERR.puts( "error: #{s}: not found or cannot access" )
771 exit 1
772 end
773
774 if stat.directory? then
775 Dir.foreach(s) {|file|
776 if file =~ /_templ.[ch]$/ then
777 merge( "#{s}/#{file}", dst )
778 end
779 }
780 elsif stat.file? then
781 merge( s, dst )
782 end
783}
Note: See TracBrowser for help on using the repository browser.