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 
11 module 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 
211  character(STRING), pointer:: options(:) => null()
212  ! オプション名リスト
213  character(STRING) :: help_message
214  ! ヘルプメッセージ
215  logical :: optvalue_flag
216  ! オプションの値の有無
217  end type opt_entry
218 
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 
239  interface dcargsputline
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 
251  interface dcargshelpmsg
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 
334 contains
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
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  !
1011  use sysdep, only: sysdepargcount, sysdepargget
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 
1107 end module dc_args
subroutine sortargtable
Definition: dc_args.f90:955
type(cmd_opts_internal), dimension(:), allocatable, save cmd_opts_list
Definition: dc_args.f90:324
subroutine, public setdebug(debug)
Definition: dc_trace.f90:288
subroutine sysdepargget(idx_given, result)
Definition: sysdeparg.f90:55
logical function, public present_and_true(arg)
Definition: dc_present.f90:80
subroutine dcargsdebug0(arg)
Definition: dc_args.f90:521
subroutine dcargsget0(arg, argv)
Definition: dc_args.f90:789
integer function sysdepargcount()
Definition: sysdeparg.f90:35
subroutine dcargsputline0(arg)
Definition: dc_args.f90:835
subroutine dcargsopen0(arg)
Definition: dc_args.f90:337
character(string) function, public joinchar(carray, expr)
Definition: dc_string.f90:861
subroutine dcargshelp0(arg, force)
Definition: dc_args.f90:556
subroutine buildargtable
Definition: dc_args.f90:1003
subroutine dcargshelpmsg0(arg, category, msg)
Definition: dc_args.f90:663
subroutine dcargsclose0(arg)
Definition: dc_args.f90:368
subroutine printautolinefeed(unit, fmt, length, indent)
Definition: dc_args.f90:878
Definition: dc_args.f90:210
integer, parameter, public stdout
標準出力の装置番号
Definition: dc_types.f90:98
character(string), dimension(:), allocatable, save argstr_table
Definition: dc_args.f90:313
文字型変数の操作.
Definition: dc_string.f90:24
種別型パラメタを提供します。
Definition: dc_types.f90:49
integer function dcargsnumber0(arg)
Definition: dc_args.f90:818
subroutine dcargsoption0(arg, options, flag, value, help)
Definition: dc_args.f90:395
character(string), dimension(:), allocatable, save cmd_argv_list
Definition: dc_args.f90:329
logical function dcoptionformc(argument, name, value)
Definition: dc_args.f90:1034
subroutine dcargsstrict0(arg, severe)
Definition: dc_args.f90:746
integer, save argind_count
Definition: dc_args.f90:318
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition: dc_types.f90:118