Loading...
Searching...
No Matches
dc_args.f90
Go to the documentation of this file.
1!= コマンドライン引数の解析
2!= Command line arguments parser
3!
4! Authors:: Yasuhiro MORIKAWA
5! Version:: $Id: dc_args.f90,v 1.2 2009-08-09 06:53:11 morikawa Exp $
6! Tag Name:: $Name: $
7! Copyright:: Copyright (C) GFD Dennou Club, 2005. All rights reserved.
8! License:: See COPYRIGHT[link:../../COPYRIGHT]
9!
10
11module dc_args
12 !
13 != コマンドライン引数の解析
14 != Command line arguments parser
15 !
16 ! コマンドライン引数の解析を行います.
17 !
18 ! 加えて, ヘルプメッセージの表示に関して便利なサブルーチンも
19 ! 用意しています.
20 !
21 !== Tutorial
22 !
23 ! * gtool5 オフィシャルチュートリアル:
24 ! {コマンドライン引数の解析}[link:../tutorial/dc_args.htm]
25 !
26 !== Procedures list
27 !
28 ! DCArgsOpen :: 構造型 ARGS 変数の初期化
29 ! DCArgsClose :: 構造型 ARGS 変数の終了処理
30 ! DCArgsGet :: コマンドライン引数の取得
31 ! DCArgsNumber :: コマンドライン引数の数を返す
32 ! DCArgsOption :: コマンドライン引数オプションを取得するための設定
33 ! DCArgsDebug :: デバッグオプションの自動設定
34 ! DCArgsHelp :: ヘルプオプションの自動設定
35 ! DCArgsHelpMsg :: ヘルプメッセージの設定
36 ! DCArgsStrict :: 無効なオプションが指定された時に警告を表示するよう設定
37 ! DCArgsPutLine :: 構造型 ARGS 変数の内容を印字
38 !
39 !
40 !== Usage
41 !
42 ! 構造型 ARGS の変数を定義し, Open, Get を利用することで
43 ! コマンドライン引数を取得することができます.
44 !
45 ! program dc_args_sample1
46 ! use dc_types
47 ! use dc_string, only: StoA
48 ! use dc_args
49 ! implicit none
50 ! type(ARGS) :: arg
51 ! character(STRING), pointer :: argv(:) => null()
52 ! integer :: i
53 !
54 ! call DCArgsOpen( arg = arg ) ! (out)
55 ! call DCArgsDebug( arg = arg ) ! (inout)
56 ! call DCArgsHelp( arg = arg ) ! (inout)
57 ! call DCArgsStrict( arg = arg ) ! (inout)
58 ! call DCArgsGet( arg = arg, & ! (inout)
59 ! & argv = argv ) ! (out)
60 ! do i = 1, size( argv )
61 ! write(*,*) argv(i)
62 ! end do
63 ! deallocate( argv )
64 ! call DCArgsClose( arg = arg ) ! (inout)
65 ! end program dc_args_sample1
66 !
67 ! 引数にオプションを指定したい場合には, DCArgsOption サブルーチンを
68 ! 利用してください. オプションの書式に関しては DCArgsOption の
69 ! 「オプションの書式」を参照してください.
70 !
71 ! program dc_args_sample2
72 ! use dc_types
73 ! use dc_string, only: StoA
74 ! use dc_args
75 ! implicit none
76 ! type(ARGS) :: arg
77 ! logical :: OPT_size
78 ! logical :: OPT_namelist
79 ! character(STRING) :: VAL_namelist
80 !
81 ! call DCArgsOpen( arg = arg ) ! (out)
82 ! call DCArgsOption( arg = arg, & ! (inout)
83 ! & options = StoA('-s', '--size'), & ! (in)
84 ! & flag = OPT_size, & ! (out)
85 ! & help = "Return number of arguments") ! (in)
86 ! call DCArgsOption( arg = arg, & ! (inout)
87 ! & options = StoA('-N', '--namelist'), & ! (in)
88 ! & flag = OPT_namelist, & ! (out)
89 ! & value = VAL_namelist, & ! (out)
90 ! & help = "Namelist filename") ! (in)
91 !
92 ! call DCArgsDebug( arg = arg ) ! (inout)
93 ! call DCArgsHelp( arg = arg ) ! (inout)
94 ! call DCArgsStrict( arg = arg ) ! (inout)
95 !
96 ! if (OPT_size) then
97 ! write(*,*) 'number of arguments :: ', DCArgsNumber(arg)
98 ! end if
99 ! if (OPT_namelist) then
100 ! write(*,*) '--namelist=', trim(VAL_namelist)
101 ! else
102 ! write(*,*) '--namelist is not found'
103 ! end if
104 ! call DCArgsClose( arg = arg ) ! (inout)
105 ! end program dc_args_sample2
106 !
107 ! コマンドライン引数に '-h', '-H', '--help' のいづれかのオプションを
108 ! 指定することで, オプションの一覧が標準出力に表示されます.
109 !
110 ! ヘルプメッセージの内容を充実させたい場合には DCArgsHelpMsg を
111 ! 参照してください.
112 !
113 !
114 !== Note
115 !
116 !=== 後方互換
117 !
118 ! バージョン 20071009 以前に利用可能だった以下の手続きは,
119 ! 後方互換のため, しばらくは利用可能です.
120 !
121 ! * Open, Close, Option, PutLine, Debug, Help, HelpMsg, Strict, Get
122 ! Number
123 !
124 !=== dc_args モジュールを作成した理由について
125 !
126 ! Fortran コンパイラのほとんどには IARGC, GETARG といった
127 ! コマンドライン引数取得のための副プログラムが用意されている.
128 ! これらの副プログラムの利用によって, コマンドラインの引数を
129 ! 単に取得することは簡単である.
130 !
131 ! しかしこの IARGC, GETARG の使用に際し, 2 つほど面倒な点がある.
132 !
133 ! 1 つはコンパイラ依存による IARGC, GETARG の仕様の違いである.
134 ! これらの副プログラムは Fortran 規格に含まれないサービスルーチン
135 ! であるため, たいていのコンパイラにはこの副プログラムは
136 ! 存在するものの, 仕様が微妙に異なる場合がある. (大抵のコンパイラは
137 ! GETARG の第一引数を 1 にすると一つ目の引数を取得するが,
138 ! 古い HITACHI のコンパイラは第一引数を 2 にしないと一つ目の
139 ! 引数を取得できない, など). そこで gtool5 ライブラリでは
140 ! これらのコンパイラ依存性を吸収する設計を行っている.
141 ! dc_args モジュールを使用する際には, これらのコンパイラ依存は
142 ! 気にしなくてよい. (なお, コンパイラ依存性を実際に
143 ! 吸収しているのは sysdep モジュールである).
144 !
145 ! 2 つ目は, コマンドライン引数におけるオプション引数
146 ! (-h や --version など) の取り扱いの不便さである.
147 ! IARGC や GETARG は単に引数を取得するための副プログラムであり,
148 ! Perl や Ruby などのインタプリタ言語のように,
149 ! コマンドライン引数にオプション引数を処理するための
150 ! ライブラリ (Getopt や OptionParser など) が用意されていない.
151 ! dc_args モジュールは, Fortran プログラムでもオプション引数を
152 ! 手軽に扱えるよう, オプション引数処理の
153 ! ためのコーディングをできるだけ簡素にするべく整備したプログラムである.
154 !
155 ! 設計思想は, {オブジェクト指向スクリプト言語 Ruby}[http://www.ruby-lang.org/]
156 ! の OptionParser[http://www.ruby-lang.org/ja/man/index.cgi?cmd=view;name=OptionParser]
157 ! を真似ており, OptionParser クラスのオブジェクトを
158 ! 構造型 ARGS に, new (initialize) メソッドを DCArgsOpen サブルーチンに,
159 ! on メソッドを DCArgsOption サブルーチンに, parse メソッドを DCArgsGet
160 ! サブルーチンに見立てている. 言語仕様の違いにより実装や仕様は
161 ! それなりに異なるが, 構造型 ARGS の変数をオブジェクトに見立て,
162 ! この変数に対してサブルーチンを作用させることによって
163 ! オブジェクトへの操作やオブジェクトからの引数情報の取得を行うという点では
164 ! OptionParser と同様である.
165 !
166 ! おまけ的機能であるが, dc_trace モジュールとの連携も図られており,
167 ! Debug サブルーチンを使用することにより (使用法は上記参照), 再コン
168 ! パイルすることなく, プログラムの実行の際に "-D" オプションをつける
169 ! ことでデバッグメッセージを表示するモードに変更することもできる.
170 !
171
172 use dc_types, only : string
173 use dc_hash, only: hash
174 implicit none
175 private
176
177 public:: args
181 public:: dcargsnumber
182
183 !-----------------------------------------------
184 ! 後方互換用
185 ! For backward compatibility
186 public:: Open, Close, option, putline, debug, help, helpmsg, strict, get
187 public:: number
188
189 type args
190 !
191 ! コマンドライン引数解析用の構造体です.
192 ! 初期化には DCArgsOpen を, 終了処理には DCArgsClose を用います.
193 ! コマンドライン引数に与えられる引数や, プログラム内で
194 ! DCArgsOption, DCArgsHelpMsg サブルーチンによって与えられた情報を
195 ! 格納します.
196 !
197 ! 詳しい使い方は dc_args の Usage を参照ください.
198 !
199 private
200 type(OPT_ENTRY), pointer :: opt_table(:) => null()
201 ! DCArgsOption サブルーチンで指定される
202 ! オプションのリスト
203 logical :: initialized = .false.
204 type(cmd_opts_internal), pointer :: cmd_opts_list(:) => null()
205 ! コマンドライン引数のうち, オプションと
206 ! して識別されるものののリスト.
207 type(hash) :: helpmsg
208 end type args
209
210 type opt_entry
211 character(STRING), pointer:: options(:) => null()
212 ! オプション名リスト
213 character(STRING) :: help_message
214 ! ヘルプメッセージ
215 logical :: optvalue_flag
216 ! オプションの値の有無
217 end type opt_entry
218
219 type cmd_opts_internal
220 character(STRING) :: name ! オプション名
221 character(STRING) :: value ! 値
222 logical:: flag_called = .false.
223 ! このオプション名が DCArgsOption で呼ばれたもの
224 ! かどうかを判別するフラグ
225 end type cmd_opts_internal
226
227 interface dcargsopen
228 module procedure dcargsopen0
229 end interface
230
231 interface dcargsclose
232 module procedure dcargsclose0
233 end interface
234
235 interface dcargsoption
236 module procedure dcargsoption0
237 end interface
238
240 module procedure dcargsputline0
241 end interface
242
243 interface dcargsdebug
244 module procedure dcargsdebug0
245 end interface
246
247 interface dcargshelp
248 module procedure dcargshelp0
249 end interface
250
252 module procedure dcargshelpmsg0
253 end interface
254
255 interface dcargsstrict
256 module procedure dcargsstrict0
257 end interface
258
259 interface dcargsget
260 module procedure dcargsget0
261 end interface
262
263 interface dcargsnumber
264 module procedure dcargsnumber0
265 end interface
266
267 !-----------------------------------------------
268 ! 後方互換用
269 ! For backward compatibility
270 interface open
271 module procedure dcargsopen0
272 end interface
273
274 interface close
275 module procedure dcargsclose0
276 end interface
277
278 interface option
279 module procedure dcargsoption0
280 end interface
281
282 interface putline
283 module procedure dcargsputline0
284 end interface
285
286 interface debug
287 module procedure dcargsdebug0
288 end interface
289
290 interface help
291 module procedure dcargshelp0
292 end interface
293
294 interface helpmsg
295 module procedure dcargshelpmsg0
296 end interface
297
298 interface strict
299 module procedure dcargsstrict0
300 end interface
301
302 interface get
303 module procedure dcargsget0
304 end interface
305
306 interface number
307 module procedure dcargsnumber0
308 end interface
309
310
311 !-------------------------------------
312 ! BuildArgTable で設定される変数
313 character(STRING), allocatable, save:: argstr_table(:)
314 ! 全引数の内容. (オプションかどうかなど
315 ! の判別は行っていない). BuildArgTable
316 ! で設定される.
317
318 integer, save:: argind_count = -1
319 ! 全引数の数. BuildArgTable で
320 ! 設定される.
321
322 !-------------------------------------
323 ! SortArgTable で設定される変数
324 type(CMD_OPTS_INTERNAL), allocatable, save :: cmd_opts_list(:)
325 ! コマンドライン引数のうち, オプションと
326 ! して識別されるものののリス
327 ! ト. SortArgTable で設定される.
328
329 character(STRING), allocatable, save:: cmd_argv_list(:)
330 ! コマンドライン引数のうち, オプションで
331 ! はない引数のリスト. SortArgTable で設
332 ! 定される.
333
334contains
335
336 subroutine dcargsopen0(arg)
337 !
338 ! ARGS 型の変数を初期設定します.
339 !
340 ! ARGS 型の変数を利用する際にはまずこのサブルーチンによって
341 ! 初期設定を行ってください.
342 !
343 ! このサブルーチンは, より下層のサブルーチン内で IARGC や GETARG
344 ! を用いて得られたコマンドライン引数の情報を引数 *arg*
345 ! へと格納します.
346 !
347 use dc_message, only: messagenotify
348 use dc_types, only: string
349 implicit none
350 type(args), intent(out) :: arg
351 integer:: cmd_opts_max
352 character(len = *), parameter :: subname = 'DCArgsOpen'
353 continue
354 if (arg % initialized) then
355 call messagenotify('W', subname, 'This argument (type ARGS) is already opend.')
356 return
357 end if
358 call buildargtable
359 call sortargtable
360 cmd_opts_max = size(cmd_opts_list)
361 allocate(arg % cmd_opts_list(cmd_opts_max))
362 arg % cmd_opts_list = cmd_opts_list
363 nullify( arg % opt_table )
364 arg % initialized = .true.
365 end subroutine dcargsopen0
366
367 subroutine dcargsclose0(arg)
368 !
369 ! ARGS 型の変数の終了処理を行います.
370 !
371 use dc_hash, only: dchashdelete
372 implicit none
373 type(args), intent(inout) :: arg
374 integer :: i
375 continue
376 if (arg % initialized) then
377 if ( associated( arg % opt_table ) ) then
378 do i = 1, size(arg % opt_table)
379 deallocate(arg % opt_table(i) % options)
380 end do
381
382 deallocate(arg % opt_table)
383 end if
384
385 deallocate(arg % cmd_opts_list)
386 deallocate(argstr_table)
387 deallocate(cmd_argv_list)
388 deallocate(cmd_opts_list)
389
390 call dchashdelete(arg % helpmsg)
391 end if
392 end subroutine dcargsclose0
393
394 subroutine dcargsoption0(arg, options, flag, value, help)
395 !
396 ! オプション情報の登録と取得を行います.
397 !
398 ! コマンドライン引数のうち, *options* に与えるオプションに関する情
399 ! 報を *flag* と *value* に取得します. *options* がコマンドライン
400 ! 引数に与えられていれば *flag* に .true. が, そうでない場合は
401 ! .false. が返ります. オプションに値が指定される場合は *value* に
402 ! その値が返ります. オプション自体が与えられていない場合には
403 ! *value* には空文字が返ります.
404 !
405 ! *help* には *options* に関するヘルプメッセージを *arg* に
406 ! 登録します. サブルーチン DCArgsHelp を
407 ! 用いた際に, このメッセージが出力されます.
408 ! *value* を与えているかどうかでこのメッセージは変化します.
409 !
410 !=== オプションの書式
411 !
412 ! コマンドライン引数のうち, オプションと判定されるのは以下の場合です.
413 !
414 ! * 1 文字目が '-' の場合. この場合は短いオプションとなり, '-'
415 ! の次の一文字のみがオプションとして有効になります.
416 !
417 ! * 1-2文字目が '--' (ハイフン 2 文字) の場合.
418 ! この場合は長いオプションとなり,
419 ! '--' 以降の文字列がオプションとして有効になります.
420 !
421 ! オプションの値は, "=" よりも後ろの文字列になります.
422 !
423 ! 例
424 !
425 ! <b>コマンドライン引数</b> :: <b>オプション名, 値 </b>
426 ! -h :: -h, 無し
427 ! --help :: --help, 無し
428 ! -D=6 :: -D, 6
429 ! -debug= :: -d, 無し
430 ! --include=/usr :: --include, /usr
431 !
432
433 use dc_message, only: messagenotify
434 implicit none
435 type(args), intent(inout) :: arg
436 character(len = *), intent(in) :: options(:)
437 logical, intent(out) :: flag
438 character(len = *), intent(out), optional :: value
439 character(len = *), intent(in), optional :: help
440 integer :: i, j, options_size, table_size
441 type(opt_entry), allocatable :: local_tables(:)
442 character(len = STRING) :: opt_name, opt_value, opt_full
443 character(len = *), parameter :: subname = 'DCArgsOption'
444 continue
445 flag = .false.
446 if (present(value)) value = ''
447 if (.not. arg % initialized) then
448 call messagenotify('W', subname, 'Call Open before Option in dc_args.')
449 call dcargsopen(arg)
450 end if
451 options_size = size(options)
452 if (options_size < 1) then
453 return
454 end if
455
456 !-----------------------------------
457 ! 構造体 ARGS へのヘルプメッセージ用の情報登録
458 ! * まずはテーブル arg % opt_table を一つ広げる.
459 !-----------------------------------
460 if ( .not. associated( arg % opt_table ) ) then
461 ! 1 つめのオプション指定
462 !
463 table_size = 0
464 allocate(arg % opt_table(table_size + 1))
465 else
466 ! 2 つめ以降のオプション指定
467 !
468 table_size = size(arg % opt_table)
469 allocate(local_tables(table_size))
470 local_tables(1:table_size) = arg % opt_table(1:table_size)
471 deallocate(arg % opt_table)
472 allocate(arg % opt_table(table_size + 1))
473 arg % opt_table(1:table_size) = local_tables(1:table_size)
474 deallocate(local_tables)
475 end if
476
477 !----- 値の代入 -----
478 allocate(arg % opt_table(table_size + 1) % options(options_size))
479 arg % opt_table(table_size + 1) % options = options
480 arg % opt_table(table_size + 1) % help_message = ''
481 if (present(help)) then
482 arg % opt_table(table_size + 1) % help_message = help
483 end if
484 arg % opt_table(table_size + 1) % optvalue_flag = present(value)
485
486
487 !----- options の正規化 -----
488 do i = 1, options_size
489 opt_full = arg % opt_table(table_size + 1) % options(i)
490 if (dcoptionformc(opt_full, opt_name, opt_value)) then
491 arg % opt_table(table_size + 1) % options(i) = opt_name
492 else
493 if (len(trim(adjustl(opt_full))) < 2) then
494 arg % opt_table(table_size + 1) % options(i) = &
495 & '-' // trim(adjustl(opt_full))
496 else
497 arg % opt_table(table_size + 1) % options(i) = &
498 & '--' // trim(adjustl(opt_full))
499 end if
500 end if
501 end do
502
503 ! arg % cmd_opts_list 内の探査と flag, value への代入
504 ! 呼ばれたものに関しては arg % cmd_opts_list % flag_called を
505 ! .true. に
506 do i = 1, options_size
507 do j = 1, size(arg % cmd_opts_list)
508 if (trim(arg % opt_table(table_size + 1) % options(i)) &
509 & == trim(arg % cmd_opts_list(j) % name)) then
510 flag = .true.
511 if (present(value)) then
512 value = arg % cmd_opts_list(j) % value
513 end if
514 arg % cmd_opts_list(j) % flag_called = .true.
515 end if
516 end do
517 end do
518 end subroutine dcargsoption0
519
520 subroutine dcargsdebug0(arg)
521 !
522 ! デバッグオプションの自動設定を行います.
523 !
524 ! -D もしくは --debug が指定された際, 自動的に
525 ! dc_trace#SetDebug を呼び出すよう *arg* を設定します.
526 !
527 use dc_types, only: string
528 use dc_string, only: stoa, stoi
529 use dc_trace, only: setdebug
530 use dc_message, only: messagenotify
531 implicit none
532 type(args), intent(inout) :: arg
533 logical :: OPT_debug
534 character(STRING) :: VAL_debug
535 character(len = *), parameter :: subname = 'DCArgsDebug'
536 continue
537 if (.not. arg % initialized) then
538 call messagenotify('W', subname, 'Call Open before Debug in dc_args.')
539 call dcargsopen(arg)
540 end if
541 call option(arg, stoa('-D', '--debug'), opt_debug, val_debug, &
542 & help="call dc_trace#SetDebug (display a lot of messages for debug). " // &
543 & "VAL is unit number (default is standard output)")
544 if (opt_debug) then
545 if (trim(val_debug) == '') then
546 call setdebug
547 else
548 call setdebug(stoi(val_debug))
549 end if
550 end if
551 return
552 end subroutine dcargsdebug0
553
554
555 subroutine dcargshelp0(arg, force)
556 !
557 ! ヘルプオプションの自動設定を行います.
558 !
559 ! -h, -H, --help のいづれかが指定された際, 自動的に *arg* 内に設定された
560 ! 情報をヘルプメッセージとして表示した後, プログラムを終了させます.
561 ! 原則的に, このサブルーチンよりも前に DCArgsOption, DCArgsDebug
562 ! のサブルーチンを呼んで下さい.
563 !
564 ! *force* に .true. が指定される場合, -H, --help オプションが与え
565 ! られない場合でもヘルプメッセージを表示した後, プログラムを終了さ
566 ! せます.
567 !
568 ! ヘルプメッセージに表示される情報は, DCArgsOption, DCArgsHelpMsg
569 ! サブルーチンによって付加することが可能です.
570 !
571 use dc_types, only: string, stdout
572 use dc_string, only: stoa, stoi, printf, concat, joinchar, uchar, lchar
573 use dc_present, only: present_and_true
574 use dc_message, only: messagenotify
576 implicit none
577 type(args), intent(inout) :: arg
578 logical, intent(in), optional :: force
579 logical :: OPT_help, found, end
580 character(STRING) :: VAL_help, options_msg, help_msg, category
581 character(STRING), pointer :: localopts(:) => null()
582 integer :: unit, i
583 character(len = *), parameter :: subname = 'DCArgsHelp'
584 continue
585 if (.not. arg % initialized) then
586 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
587 call dcargsopen(arg)
588 end if
589 call dcargsoption(arg, stoa('-h', '-H', '--help'), opt_help, val_help, &
590 & help="display this help and exit. " // &
591 & "VAL is unit number (default is standard output)")
592 if (.not. opt_help .and. .not. present_and_true(force)) then
593 return
594 end if
595 if (trim(val_help) == '') then
596 unit = stdout
597 else
598 unit = stoi(val_help)
599 end if
600
601 call printf(unit, '')
602
603 call dchashget(arg % helpmsg, 'TITLE', help_msg, found)
604 if (found) then
605 call printf(unit, '%c', c1=trim(help_msg))
606 call printf(unit, '')
607 call dchashdelete(arg % helpmsg, 'TITLE')
608 end if
609
610 call dchashget(arg % helpmsg, 'OVERVIEW', help_msg, found)
611 if (found) then
612 call printf(unit, 'Overview::')
613 call printautolinefeed(unit, help_msg, indent=' ')
614 call printf(unit, '')
615 call dchashdelete(arg % helpmsg, 'OVERVIEW')
616 end if
617
618 call dchashget(arg % helpmsg, 'USAGE', help_msg, found)
619 if (found) then
620 call printf(unit, 'Usage::')
621 call printautolinefeed(unit, help_msg, indent=' ')
622 call printf(unit, '')
623 call dchashdelete(arg % helpmsg, 'USAGE')
624 end if
625
626 call printf(unit, 'Options::')
627 if ( associated(arg % opt_table) ) then
628 do i = 1, size(arg % opt_table)
629 options_msg = ' '
630 if (arg % opt_table(i) % optvalue_flag) then
631 call concat(arg % opt_table(i) % options, '=VAL', localopts)
632 else
633 allocate(localopts(size(arg % opt_table(i) % options)))
634 localopts = arg % opt_table(i) % options
635 end if
636 options_msg = trim(options_msg) // trim(joinchar(localopts))
637 deallocate(localopts)
638 call printf(unit, ' %c', c1=trim(options_msg))
639 call printautolinefeed(unit, &
640 & arg % opt_table(i) % help_message, indent=' ')
641 call printf(unit, '')
642 end do
643 end if
644
645 call dchashrewind(arg % helpmsg)
646 do
647 call dchashnext(arg % helpmsg, category, help_msg, end)
648 if (end) exit
649
650 call printf(unit, '%c%c::', &
651 & c1=trim(uchar(category(1:1))), c2=trim(lchar(category(2:))))
652 call printautolinefeed(unit, help_msg, indent=' ')
653 call printf(unit, '')
654
655 enddo
656
657 call dcargsclose(arg)
658
659 stop
660 end subroutine dcargshelp0
661
662 subroutine dcargshelpmsg0(arg, category, msg)
663 !
664 ! ヘルプメッセージを追加します.
665 !
666 ! サブルーチン DCArgsHelp を使用した際に出力されるメッセージを
667 ! 付加します. *category* に +Title+, +Overview+, +Usage+ が
668 ! 指定されたものは +Options+ よりも上部に,
669 ! それ以外のものは下部に表示されます.
670 ! *msg* にはメッセージを与えてください.
671 !
672 !=== 例
673 !
674 ! program dc_args_sample3
675 ! use dc_types
676 ! use dc_string, only: StoA
677 ! use dc_args
678 ! implicit none
679 ! type(ARGS) :: arg
680 ! logical :: OPT_namelist
681 ! character(STRING) :: VAL_namelist
682 ! character(STRING), pointer :: argv(:) => null()
683 ! integer :: i
684 !
685 ! call DCArgsOpen( arg = arg ) ! (out)
686 ! call DCArgsHelpMsg( arg = arg, & ! (inout)
687 ! & category = 'Title', & ! (in)
688 ! & msg = 'dcargs $Revision: 1.2 $ ' // &
689 ! & ':: Test program of dc_args' ) ! (in)
690 ! call DCArgsHelpMsg( arg = arg, & ! (inout)
691 ! & category = 'Usage', & ! (in)
692 ! & msg = 'dcargs [Options] arg1, arg2, ...') ! (in)
693 ! call DCArgsOption( arg = arg, & ! (inout)
694 ! & options = StoA('-N', '--namelist'), & ! (in)
695 ! & flag = OPT_namelist, & ! (out)
696 ! & value = VAL_namelist, & ! (out)
697 ! & help = "Namelist filename") ! (in)
698 ! call DCArgsHelpMsg( arg = arg, & ! (inout)
699 ! & category = 'DESCRIPTION', & ! (in)
700 ! & msg = '(1) Define type "HASH". ' // &
701 ! & '(2) Open the variable. ' // &
702 ! & '(3) set HelpMsg. ' // &
703 ! & '(4) set Options. ' // &
704 ! & '(5) call Debug. ' // &
705 ! & '(6) call Help. ' // &
706 ! & '(7) call Strict.') ! (in)
707 ! call DCArgsHelpMsg( arg = arg, & ! (inout)
708 ! & category = 'Copyright', & ! (in)
709 ! & msg = 'Copyright (C) ' // &
710 ! & 'GFD Dennou Club, 2008. All rights reserved.') ! (in)
711 ! call DCArgsDebug( arg = arg ) ! (inout)
712 ! call DCArgsHelp( arg = arg ) ! (inout)
713 ! call DCArgsStrict( arg = arg ) ! (inout)
714 ! call DCArgsGet( arg = arg, & ! (inout)
715 ! & argv = argv ) ! (out)
716 ! write(*,*) '--namelist=', trim( VAL_namelist )
717 ! do i = 1, size(argv)
718 ! write(*,*) argv(i)
719 ! end do
720 ! deallocate( argv )
721 ! call DCArgsClose( arg = arg ) ! (inout)
722 ! program dc_args_sample3
723 !
724 ! コマンドライン引数に '-h', '-H', '--help' のいづれかのオプション
725 ! を指定することで, HelpMsg で与えたメッセージと, オプションの一覧
726 ! が標準出力に表示されます.
727 !
728 use dc_hash, only: dchashput
729 use dc_string, only: uchar
730 use dc_message, only: messagenotify
731 implicit none
732 type(args), intent(inout) :: arg
733 character(*), intent(in) :: category
734 character(*), intent(in) :: msg
735 character(len = *), parameter :: subname = 'DCArgsHelpMsg'
736 continue
737 if (.not. arg % initialized) then
738 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
739 call dcargsopen(arg)
740 end if
741 call dchashput(arg % helpmsg, key=uchar(category), value=msg)
742 end subroutine dcargshelpmsg0
743
744
745 subroutine dcargsstrict0(arg, severe)
746 !
747 ! オプションチェックを行います.
748 !
749 ! コマンドライン引数のオプションとして指定されたものの内,
750 ! DCArgsOption サブルーチンで設定されていないものが存在する
751 ! 場合には警告を返します. *severe* に .true. を指定すると
752 ! エラーを返して終了します.
753 ! このサブルーチンを呼ぶ前に, DCArgsOption, DCArgsDebug,
754 ! DCArgsHelp サブルーチンを呼んでください.
755 !
756 ! 構造体 ARGS の変数に対してこのサブルーチンを適用しておく
757 ! ことで, コマンドライン引数として与えたオプションが正しく
758 ! プログラムが認識しているかどうかをチェックすることができます.
759 !
760 !
761 use dc_types, only: string
762 use dc_present, only: present_and_true
763 use dc_message, only: messagenotify
764 implicit none
765 type(args), intent(inout) :: arg
766 logical, intent(in), optional :: severe
767 character(STRING) :: err_mess
768 integer :: i
769 character(len = *), parameter :: subname = 'DCArgsStrict'
770 continue
771 if (.not. arg % initialized) then
772 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
773 call dcargsopen(arg)
774 end if
775 do i = 1, size(arg % cmd_opts_list)
776 err_mess = trim(arg % cmd_opts_list(i) % name) // ' is invalid option.'
777 if (.not. arg % cmd_opts_list(i) % flag_called) then
778 if (present_and_true(severe)) then
779 call messagenotify('E', subname, err_mess)
780 else
781 call messagenotify('W', subname, err_mess)
782 end if
783 end if
784 end do
785 end subroutine dcargsstrict0
786
787
788 subroutine dcargsget0(arg, argv)
789 !
790 ! コマンドライン引数のうち, オプションではないものを
791 ! *argv* に返します.
792 !
793 ! *argv* は文字型配列のポインタです.
794 ! 引数として与える場合には必ず空状態して与えてください.
795 !
796 use dc_types, only: string
797 use dc_string, only: stoa, stoi, printf, concat, joinchar
798 use dc_present, only: present_and_true
799 use dc_message, only: messagenotify
800 implicit none
801 type(args), intent(inout) :: arg
802 character(*), pointer :: argv(:) !(out)
803 integer :: i, cmd_argv_max
804 character(len = *), parameter :: subname = 'DCArgsGet'
805 continue
806 if (.not. arg % initialized) then
807 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
808 call dcargsopen(arg)
809 end if
810 cmd_argv_max = size(cmd_argv_list)
811 allocate(argv(cmd_argv_max))
812 do i = 1, cmd_argv_max
813 argv(i) = cmd_argv_list(i)
814 end do
815 end subroutine dcargsget0
816
817 function dcargsnumber0(arg) result(result)
818 !
819 ! コマンドライン引数として与えられた引数の数を返します.
820 !
821 use dc_message, only: messagenotify
822 implicit none
823 type(args), intent(inout) :: arg
824 integer :: result
825 character(len = *), parameter :: subname = 'DCArgsNumber'
826 continue
827 if (.not. arg % initialized) then
828 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
829 call dcargsopen(arg)
830 end if
831 result = size(cmd_argv_list)
832 end function dcargsnumber0
833
834 subroutine dcargsputline0(arg)
835 !
836 ! *arg* に関する情報を標準出力に表示します.
837 !
838 use dc_types, only: stdout
839 use dc_string, only: printf, joinchar
840 implicit none
841 type(args), intent(in) :: arg
842 integer :: i
843 continue
844 if (.not. arg % initialized) then
845 call printf(stdout, '#<ARGS:: @initialized=%y>', l=(/arg % initialized/))
846 return
847 end if
848 call printf(stdout, '#<ARGS:: @initialized=%y,', l=(/arg % initialized/))
849 call printf(stdout, ' @opt_table(:)=')
850 if ( associated(arg % opt_table) ) then
851 do i = 1, size(arg % opt_table)
852 call printf(stdout, ' #<OPT_ENTRY:: ')
853 call printf(stdout, ' @options=%c, @help_message=%c, @optvalue_flag=%y', &
854 & c1=trim(joinchar(arg % opt_table(i) % options)), &
855 & c2=trim(arg % opt_table(i) % help_message), &
856 & l=(/arg % opt_table(i) % optvalue_flag/))
857 call printf(stdout, ' >')
858 end do
859 end if
860 call printf(stdout, ' ,')
861 call printf(stdout, ' @cmd_opts_list(:)=')
862 do i = 1, size(arg % cmd_opts_list)
863 call printf(stdout, ' #<CMD_OPTS_INTERNAL:: ')
864 call printf(stdout, ' @name=%c, @value=%c, @flag_called=%y', &
865 & c1=trim(arg % cmd_opts_list(i) % name), &
866 & c2=trim(arg % cmd_opts_list(i) % value), &
867 & l=(/arg % cmd_opts_list(i) % flag_called/))
868 call printf(stdout, ' >')
869 end do
870 call printf(stdout, ' ,')
871 call printf(stdout, ' @cmd_argv_list(:)=%c', &
872 & c1=trim(joinchar(cmd_argv_list)))
873 call printf(stdout, '>')
874
875 end subroutine dcargsputline0
876
877 subroutine printautolinefeed(unit, fmt, length, indent)
878 !
879 ! 文字列を自動改行して出力します.
880 ! このモジュール内部で用いるためのサブルーチンです.
881 !
882 ! *fmt* に与えられた文章を文字数 *length* (指定されない場合 70)
883 ! 以内に改行し, 出力します. 出力の際, *indent* が指定されていると
884 ! その文字列を行頭に挿入して出力を行います.
885 ! 出力先はデフォルトは標準出力となります. *unit* に出力装置番号
886 ! を設定することで出力先を変更できます.
887 !
888 use dc_types, only: string, stdout
889 use dc_string, only: split
890 implicit none
891 character(*), intent(in) :: fmt
892 integer, intent(in), optional :: length ! 一行の長さ
893 character(*), intent(in), optional :: indent ! 字下げ文字列
894 integer, intent(in), optional :: unit ! 出力装置
895 character(STRING), pointer :: carray_tmp(:) => null()
896 character(STRING) :: store_str
897 integer, parameter :: default_len = 70
898 integer :: i, split_len, indent_len, unit_num
899 logical :: new_line_flag
900 continue
901 if (present(unit)) then
902 unit_num = unit
903 else
904 unit_num = stdout
905 end if
906
907 if (present(indent)) then
908 indent_len = len(indent)
909 else
910 indent_len = 0
911 end if
912
913 if (present(length)) then
914 split_len = length - indent_len
915 else
916 split_len = default_len - indent_len
917 end if
918
919
920 nullify(carray_tmp)
921 call split(fmt, carray_tmp, '')
922 store_str = ''
923 new_line_flag = .true.
924 i = 1
925 do
926 if (i > size(carray_tmp)) then
927 write(unit_num, '(A)') trim(store_str)
928 exit
929 end if
930
931 if (len(trim(store_str)) + len(trim(carray_tmp(i))) > split_len) then
932 if (new_line_flag) then
933 write(unit_num, '(A)') trim(carray_tmp(i))
934 i = i + 1
935 else
936 write(unit_num, '(A)') trim(store_str)
937 store_str = ''
938 new_line_flag = .true.
939 end if
940 cycle
941 end if
942
943 if (new_line_flag .and. present(indent)) then
944 store_str = indent // trim(carray_tmp(i))
945 else
946 store_str = trim(store_str) // ' ' // trim(carray_tmp(i))
947 end if
948 new_line_flag = .false.
949 i = i + 1
950 end do
951
952 end subroutine printautolinefeed
953
954 subroutine sortargtable
955 !
956 ! 内部向けの引数振り分けのためのサブルーチンです.
957 !
958 ! BuildArgTable で設定された argind_count, argstr_table を
959 ! 用い, cmd_argv_list, cmd_opts_list を設定します.
960 !
961 ! 既に一度でも呼ばれている場合, 何もせずに終了します.
962 !
963 use dc_types, only: string
964 implicit none
965 character(STRING):: raw_arg, name, value
966 integer:: i, cmd_argv_count, cmd_opts_count, cmd_argv_max, cmd_opts_max
967 continue
968 if (allocated(cmd_opts_list)) return
969 cmd_argv_count = 0
970 cmd_opts_count = 0
971 check_count: do, i = 1, argind_count
972 raw_arg = argstr_table(i)
973 if (dcoptionformc(raw_arg, name, value)) then
974 cmd_opts_count = cmd_opts_count + 1
975 else
976 cmd_argv_count = cmd_argv_count + 1
977 end if
978 end do check_count
979
980 cmd_argv_max = cmd_argv_count
981 cmd_opts_max = cmd_opts_count
982
983 allocate(cmd_argv_list(cmd_argv_max))
984 allocate(cmd_opts_list(cmd_opts_max))
985
986 cmd_argv_count = 0
987 cmd_opts_count = 0
988 arg_get : do, i = 1, argind_count
989 raw_arg = argstr_table(i)
990 if (dcoptionformc(raw_arg, name, value)) then
991 cmd_opts_count = cmd_opts_count + 1
992 cmd_opts_list(cmd_opts_count) % name = name
993 cmd_opts_list(cmd_opts_count) % value = value
994 cmd_opts_list(cmd_opts_count) % flag_called = .false.
995 else
996 cmd_argv_count = cmd_argv_count + 1
997 cmd_argv_list(cmd_argv_count) = raw_arg
998 end if
999 end do arg_get
1000 end subroutine sortargtable
1001
1002 subroutine buildargtable
1003 !
1004 ! 内部向けコマンドライン引数処理のサブルーチンです.
1005 !
1006 ! モジュール sysdep の sysdep#SysdepArgCount, sysdep#ArgGet
1007 ! を呼び出し, その内容を argind_count と argstr_table に格納します.
1008 !
1009 ! 既に一度でも呼ばれている場合, 何もせずに終了します.
1010 !
1012 use dc_types, only: string
1013 implicit none
1014 integer:: i, narg, nargmax
1015 character(len = STRING):: value
1016 character(len = STRING), allocatable:: localtab(:)
1017 continue
1018 if (argind_count >= 0) return
1019 nargmax = sysdepargcount()
1020 allocate(localtab(nargmax))
1021 narg = 0
1022 do, i = 1, nargmax
1023 call sysdepargget(i, value)
1024 narg = narg + 1
1025 localtab(narg) = value
1026 enddo
1027 argind_count = narg
1028 allocate(argstr_table(narg))
1029 argstr_table(1: narg) = localtab(1: narg)
1030 deallocate(localtab)
1031 end subroutine buildargtable
1032
1033 function dcoptionformc(argument, name, value) result(result)
1034 !
1035 ! 引数としてで得られた文字列を *argument* に渡すことで,
1036 ! それがオプションなのかそうでないのかを判別し, もしも
1037 ! オプションと判別した場合には戻り値に .true. を返し,
1038 ! name にオプション名, *value* にその値を返す.
1039 ! オプションに値が付加されない場合は *value* には空白を返す.
1040 !
1041 ! オプションではない場合は戻り値に .false. を返し,
1042 ! *name*, *value* には空白を返す.
1043 !
1044 ! オプションと判定されるのは以下の場合です.
1045 !
1046 ! * 一文字目が '-' の場合. この場合は短いオプションとなり, '-'
1047 ! の次の一文字のみがオプションとして有効になります.
1048 !
1049 ! * 1-2文字目が '--' の場合. この場合は長いオプションとなり,
1050 ! '--' 以降の文字列がオプションとして有効になります.
1051 !
1052 ! オプションの値は, "=" よりも後ろの文字列になります.
1053 !
1054 !=== 例
1055 !
1056 ! *argument* :: <b>name, value, 返り値</b>
1057 ! arg :: 空白, 空白, .false.
1058 ! -O :: -O, 空白, .true.
1059 ! -debug :: -d, 空白, .true.
1060 ! --debug :: --debug, 空白, .true.
1061 ! -I=/usr :: -I, /usr, .true.
1062 ! --include=/usr:: --include, /usr, .true.
1063 !
1064 implicit none
1065 character(len = *), intent(in):: argument
1066 character(len = *), intent(out):: name, value
1067 logical :: result
1068 integer:: equal
1069 continue
1070 equal = index(argument, '=')
1071 if (argument(1:1) == '-' .and. argument(2:2) /= '-') then
1072 ! Short Option
1073 if (equal == 0) then
1074 name = argument(1:2)
1075 value = ""
1076 else
1077 name = argument(1:2)
1078 value = argument(equal+1: )
1079 endif
1080 result = .true.
1081 elseif (argument(1:2) == '--') then
1082 ! Long Option
1083 if (equal == 0) then
1084 name = argument
1085 value = ""
1086 else
1087 name = argument(1:equal-1)
1088 value = argument(equal+1: )
1089 endif
1090 result = .true.
1091! elseif (equal == 0 .and. &
1092! & verify(argument(1:equal-1), WORDCHARS) == 0) then
1093! ! ???
1094! name = argument(1:equal-1)
1095! value = argument(equal+1: )
1096! result = .true.
1097 else
1098 ! No Option (normal arguments)
1099 name = ""
1100 value = ""
1101 result = .false.
1102 endif
1103 end function dcoptionformc
1104
1105
1106
1107end module dc_args
Provides kind type parameter values.
Definition dc_types.f90:49
integer, parameter, public stdout
Unit number for Standard OUTPUT
Definition dc_types.f90:98
integer, parameter, public string
Character length for string
Definition dc_types.f90:118
subroutine, public sysdepargget(index, val)
Definition sysdep.f90:71
integer function, public sysdepargcount()
Definition sysdep.f90:66