source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/tecsgen/tecsmerge.rb@ 352

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

arm向けASP3版ECNLを追加

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