source: EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecsmerge.rb@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 22.5 KB
Line 
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-2015 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: tecsmerge.rb 1011 2016-07-11 02:20:01Z coas-nagasima $
55#++
56
57#= tecsgen : TECS のマージャ
58#
59#Authors:: 大山 博司
60#Version::
61#Copyright:: Copyright (C) TOPPERS Project, 2008-2015. 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
310 # p "R: #{stat_info[0]}"
311 if stat_info[2] =~ line || ( line == nil && next_stat == :EOF ) then
312 # p "D: #{line}: #{stat}"
313 b_delim = true
314
315 found = false
316 stat_info[1].each{ |prev_stat|
317 if stat == prev_stat then
318 found = true
319 end
320 }
321 if ! found then
322 STDERR.puts "error #{line_no}: unsuitable previous keyword"
323 STDERR.puts "error #{line_no}: previous: \"#{@@DELIMITERS[stat][0]}\""
324 STDERR.puts "error #{line_no}: current: \"#{@@DELIMITERS[next_stat][0]}\""
325 expect = ""; delim = ""
326 stat_info[1].each{ |prev_stat| expect = "#{expect+delim}\"#{@@DELIMITERS[prev_stat][0]}\""; delim = ", " }
327 STDERR.puts "error #{line_no}: suitable previous: #{expect}"
328 $n_err += 1
329 end
330
331 case stat
332 when :PREAMBLE_COMMENT, :ENTRY_COMMENT, :ENTRY_FUNC_COMMENT, :POSTAMBLE_COMMENT
333 part << line
334 end
335
336 case stat # 前の状æ…
337‹
338 when :HEAD
339 @head = part
340 when :PREAMBLE_COMMENT
341 @preamble_comment = part
342 when :PREAMBLE_BODY
343 @preamble_body = part
344 when :ENTRY_COMMENT
345 port_name = arg.to_sym
346 @entry_port[ port_name ] = CDLEntryPort.new
347 @entry_port_array << port_name
348 @entry_port[ port_name ].entry_comment = part
349 when :ENTRY_BODY
350 @entry_port[ port_name ].entry_body = part
351 when :ENTRY_FUNC_COMMENT
352 func_name = arg.to_sym
353 if @entry_port[ port_name ] then # nil なら既にエラー
354 @entry_port[ port_name ].entry_func_comment[ func_name ] = part
355 @entry_port[ port_name ].entry_func_array << func_name
356 end
357 when :ENTRY_FUNC_BODY, :ENTRY_FUNC_BODY2
358 if @entry_port[ port_name ] then # nil なら既にエラー
359 @entry_port[ port_name ].entry_func_body[ func_name ] = part
360 end
361 when :POSTAMBLE_COMMENT
362 @postamble_comment = part
363 when :POSTAMBLE_BODY
364 @postamble_body = part
365 else
366 raise "Unknown state #{stat}"
367 end
368
369 case next_stat
370 when :PREAMBLE_COMMENT, :ENTRY_COMMENT, :ENTRY_FUNC_COMMENT, :POSTAMBLE_COMMENT
371 part = [ line ]
372 else
373 part = []
374 end
375
376 stat = next_stat
377 arg = $1 # arg に取っておく
378 # p stat, arg
379 break
380 end
381 }
382
383 if ! b_delim then
384 part << line
385 end
386 }
387
388 end
389
390 def check template
391 # template にないものをチェック
392 @entry_port.each{ |port_name, entry_port|
393 temp_entry_port = template.entry_port[port_name]
394 if temp_entry_port == nil then
395 STDERR.puts "info: #{port_name} is deleted port"
396 next
397 end
398 # temp_entry_port.entry_func_body.each{ |f,b| p f }
399 entry_port.entry_func_body.each{ |func_name, func_body|
400 if temp_entry_port.entry_func_body[func_name] == nil then
401 STDERR.puts "info: #{func_name} is deleted function"
402 end
403 }
404 }
405 end
406
407 def rename
408
409 renamed_entry_port = {}
410 PortRenamer.get_list.each{ |pon,pr|
411
412 # 対象受け口を捜す
413 ep = @entry_port[pon]
414 if ep == nil then
415 STDERR.puts "warning: #{pon}: renaming port not found"
416 next
417 end
418
419 # ポートの rename
420 pnn = pr.new_port_name # 置換後の名前
421 if pnn then
422 # 置換する名前があれば、登録しなおす
423 renamed_entry_port[pnn] = @entry_port[pon]
424 @entry_port.delete pon
425 end
426
427 # 指定された関数の置換
428 renamed_func_comment = {}
429 renamed_func_body = {}
430 pr.func_renamer_list.each{ |old,new|
431 ofn = "#{pon}_#{old}".to_sym
432 nfn = "#{pon}_#{new}".to_sym
433 # p "fnn: #{ofn} #{nfn} #{pon}"
434 if ep.entry_func_comment[ofn] == nil then
435 STDERR.puts "warning: #{old}: renaming function not found"
436 next
437 end
438 ep.entry_func_array.map! { |fn|
439 # p fn, nfn, ofn, fn==ofn ? nfn : fn
440 fn==ofn ? nfn : fn
441 }
442 renamed_func_comment[nfn] = ep.entry_func_comment[ofn]
443 renamed_func_body[nfn] = ep.entry_func_body[ofn]
444 ep.entry_func_comment.delete ofn
445 ep.entry_func_body.delete ofn
446 }
447 ep.entry_func_comment.merge! renamed_func_comment
448 ep.entry_func_body.merge! renamed_func_body
449
450 # ポート名の変更による関数名の置換
451 renamed_func_comment = {}
452 renamed_func_body = {}
453 if pnn then
454 ep.entry_func_array.map! { |ofn|
455 nfn = ofn.to_s.sub( /#{pon.to_s}/, pnn.to_s ).to_sym
456 # p "pnn: #{ofn} #{nfn} #{pon} #{pnn}"
457 if nfn != ofn then
458 renamed_func_comment[nfn] = ep.entry_func_comment[ofn]
459 renamed_func_body[nfn] = ep.entry_func_body[ofn]
460 ep.entry_func_comment.delete ofn
461 ep.entry_func_body.delete ofn
462 nfn
463 else
464 ofn
465 end
466 }
467 ep.entry_func_comment.merge! renamed_func_comment
468 ep.entry_func_body.merge! renamed_func_body
469
470 # ep.entry_func_comment.each { |f,e| p "FF: #{f}" }
471 # ep.entry_func_array.each { |f,e| p "FA: #{f}" }
472 end
473 }
474 # p renamed_entry_port
475 @entry_port.merge! renamed_entry_port
476 end
477
478 def merge src
479 @head = src.head
480 @preamble_body = src.preamble_body
481 @postamble_body = src.postamble_body
482
483 @entry_port_array.each{ |port_name|
484 # p "merging #{port_name}"
485 entry_port = @entry_port[ port_name ]
486 src_entry_port = src.entry_port[port_name]
487 if src_entry_port == nil then
488 print "port merged: #{port_name}\n"
489 next
490 end
491 entry_port.entry_body = src_entry_port.entry_body
492 entry_port.entry_func_array.each{ |func_name|
493 # p "merging #{func_name}"
494 func_body = entry_port.entry_func_body[ func_name ]
495 if src_entry_port.entry_func_body[func_name] == nil then
496 print "func merged: #{func_name}\n"
497 next
498 end
499 print "func remained: #{func_name}\n"
500 # entry_port.entry_func_comment[func_name] = src_entry_port.entry_func_comment[func_name]
501 entry_port.entry_func_body[func_name] = src_entry_port.entry_func_body[func_name]
502 }
503 }
504 end
505
506 def write file
507#2.0 file.write @head
508 write_array( file, @head )
509#2.0 file.write @preamble_comment
510 write_array( file, @preamble_comment )
511#2.0 file.write @preamble_body
512 write_array( file, @preamble_body )
513 @entry_port_array.each{ |port_name| @entry_port[port_name].write file }
514#2.0 file.write @postamble_comment
515 write_array( file, @postamble_comment )
516#2.0 file.write @postamble_body
517 write_array( file, @postamble_body )
518 end
519
520 attr_accessor :head, :preamble_comment, :preamble_body, :entry_port, :postamble_body
521end
522
523class CDLEntryPort
524 #@entry_comment:: [string]
525 #@entry_body:: [string]
526 #@entry_func_comment:: {ep_func_name=>string}
527 #@entry_func_body:: {ep_func_name=>string}
528 #@entry_func_array:: [string]
529
530 def initialize
531 @entry_comment = []
532 @entry_body = []
533 @entry_func_comment = {}
534 @entry_func_body = {}
535 @entry_func_array = []
536 end
537
538 def write file
539#2.0 file.write @entry_comment
540 write_array( file, @entry_comment )
541#2.0 file.write @entry_body
542 write_array( file, @entry_body )
543 @entry_func_array.each{ |fnm|
544 # p @entry_func_comment[fnm][0]
545
546#2.0 file.write @entry_func_comment[fnm]
547 write_array( file, @entry_func_comment[fnm] )
548#2.0 file.write @entry_func_body[fnm]
549 write_array( file, @entry_func_body[fnm] )
550 }
551 end
552
553 attr_accessor :entry_comment, :entry_body, :entry_func_comment, :entry_func_body, :entry_func_array
554end
555
556def merge( src_file, dst_dir )
557 unless src_file =~ /(.*)_templ(.[ch])$/ then
558 STDERR.puts( "error: #{src_file}: not end with _templ.c/h" )
559 exit 1
560 end
561
562 fname = "#{$1}#{$2}"
563 dst_file = "#{dst_dir}/#{File.basename fname}"
564 if FileTest.file?( dst_file ) then
565 print( "merging #{src_file} to #{dst_file}\n" )
566 # dst_file の読込み
567 begin
568 dst = open( dst_file )
569#2.0
570 set_encoding dst
571 old_contents = dst.readlines
572 rescue
573 STDERR.puts "error: cannot open #{dst_file}"
574 $n_err += 1
575 exit 1
576 ensure
577 dst.close
578 end
579 old = CDLContents.new( old_contents )
580
581 # template の読込み
582 begin
583 src = open( src_file )
584#2.0
585 set_encoding src
586 new_contents = src.readlines
587 rescue
588 STDERR.puts "error: cannot open #{src_file}"
589 $n_err += 1
590 exit 1
591 ensure
592 src.close
593 end
594 templ = CDLContents.new( new_contents )
595
596 old.rename
597 error_check dst_file, 1
598
599 old.check templ
600 error_check dst_file, 2
601
602 templ.merge old
603 error_check dst_file, 3
604
605 bkup_file = rename_dst( dst_file )
606
607 begin
608 dst = open( dst_file, "w" )
609#2.0
610 set_encoding dst
611 templ.write dst
612 ensure
613 dst.close
614 end
615
616 elsif $b_exist == false then
617 # src_file を dst_file へコピー
618 begin
619 src = File.open( src_file )
620#2.0
621 set_encoding src
622 contents = src.readlines
623 rescue
624 print "#{src_file}: fail to read\n"
625 ensure
626 src.close
627 end
628
629 begin
630 dst = File.open( dst_file, "w" )
631 set_encoding dst
632#2.0 dst.write( contents )
633 contents.each{ |line|
634 dst.print line
635 }
636 rescue
637 print "#{dst_file}: fail to write\n"
638 ensure
639 dst.close
640 end
641 else
642 print "info: #{dst_file} skipped\n"
643 end
644end
645
646def error_check dst_file, level
647 if $n_err > 0 then
648 STDERR.puts "=== #{dst_file} not generated because of error ==="
649 exit level
650 end
651end
652
653
654#=== ファイルのエンコーディングを ASCII-8BIT に変更
655# Ruby 1.9 以上の場合に変更
656def set_encoding file
657 if RUBY_VERSION >= "1.9.0" then
658 file.set_encoding "ASCII-8BIT"
659 end
660end
661
662#=== rename_dst
663# dst_file のバックアップファイル名を決定し、リネームする
664# 成功すれば、リネーム後のファイル名を返す
665# dst_file が存在しなければ(リネームは行われず)nil を返す。
666def rename_dst( dst_file )
667 begin
668 File.stat dst_file
669 rescue
670 STDERR.puts( "info: backup not generated for #{dst_file}" )
671 # なければ終わり
672 return nil
673 end
674
675 i = 0
676 found = true
677 while found == true
678 begin
679 i = i + 1
680 bkup_file = "#{dst_file}_#{i}"
681 File.stat bkup_file
682 rescue
683 found = false
684 end
685 end
686
687 begin
688 File.rename( dst_file, bkup_file )
689 STDERR.puts( "info: backup generated for #{dst_file} to #{bkup_file}" )
690 return bkup_file
691 rescue
692 STDERR.puts( "error: fail to rename backup file: #{bkup_file}" )
693 exit 1
694 end
695
696 return nil
697end
698
699ARGV.options {|parser|
700 parser.banner =<<EOT
701Usage: tecsmerge [options] files_templ.c src_dir
702 tecsmerge [options] gen_dir src_dir
703EOT
704 parser.on('-e', '--exist-only', "merge if exist in destination directory") { |fs|
705 $b_exist = true
706 }
707 parser.on('-p', '--port=old_name:new_name', "specify entry port name change") { |ps|
708 p = ps.split( ':' )
709 PortRenamer.new( p[0], p[1] )
710 }
711 parser.on('-f', '--func=old_name:new_name', "specify entry function name change") { |fs|
712 f = fs.split( ':' )
713 PortRenamer.add_func( f[0], f[1] )
714 }
715 parser.on('-s', '--show_change_set', "show change set. all substitute") {
716 $b_show = true
717 }
718 parser.on('-o', '--old-mode', "old mode (function head not substituted)") { |fs|
719 $old_mode = true
720 }
721 parser.version = #{$version}
722 parser.release = nil
723 parser.parse!
724# if ARGV.empty?
725 if ARGV.length < 2 then
726 puts parser.help
727 exit 1
728 end
729}
730
731if $b_show then
732 PortRenamer.show
733end
734
735if $old_mode then
736 CDLContents.merge_DELIMITERS :OLD_FUNC_BODY
737else
738 CDLContents.merge_DELIMITERS :NEW_FUNC_BODY
739end
740
741if $n_err > 0 then
742 STDERR.puts( "#{$n_err} errors" )
743 exit 1
744end
745
746src = ARGV[0,ARGV.length-1]
747dst = ARGV[-1]
748
749begin
750 stat = File.stat dst
751rescue
752 STDERR.puts( "error: #{dst}: not found" )
753 exit 1
754ensure
755 if stat && ! stat.directory? then
756 STDERR.puts( "error: #{dst}: not directory" )
757 exit 1
758 end
759end
760
761src.each { |s|
762 begin
763 stat = File.stat s
764 rescue
765 STDERR.puts( "error: #{s}: not found or cannot access" )
766 exit 1
767 end
768
769 if stat.directory? then
770 Dir.foreach(s) {|file|
771 if file =~ /_templ.[ch]$/ then
772 merge( "#{s}/#{file}", dst )
773 end
774 }
775 elsif stat.file? then
776 merge( s, dst )
777 end
778}
Note: See TracBrowser for help on using the repository browser.