gtool5 Fortran 90/95 ライブラリ 1.0.0-rc5
English
Loading...
Searching...
No Matches
dc_args.f90
Go to the documentation of this file.
1!-----------------------------------------------------------------------
2! Copyright (c) 2000-2026 Gtool Development Group. All rights reserved.
3!-----------------------------------------------------------------------
192
194 use dc_types, only : string
195 use dc_hash, only: hash
196 implicit none
197 private
198
199 public:: args
203 public:: dcargsnumber
204
205 !-----------------------------------------------
206 ! 後方互換用
207 ! For backward compatibility
208 public:: Open, Close, option, putline, debug, help, helpmsg, strict, get
209 public:: number
210
231 type args
232 private
233 type(OPT_ENTRY), pointer :: opt_table(:) => null()
234
236 logical :: initialized = .false.
237
239 type(cmd_opts_internal), pointer :: cmd_opts_list(:) => null()
240
242 type(hash) :: helpmsg
243
245 end type args
246
253 type opt_entry
254 character(STRING), pointer:: options(:) => null()
255
257 character(STRING) :: help_message
258
260 logical :: optvalue_flag
261
263 end type opt_entry
264
271 type cmd_opts_internal
272 character(STRING) :: name
273
275 character(STRING) :: value
276
278 logical:: flag_called = .false.
279
281 end type cmd_opts_internal
282
283 interface dcargsopen
284 module procedure dcargsopen0
285 end interface
286
287 interface dcargsclose
288 module procedure dcargsclose0
289 end interface
290
291 interface dcargsoption
292 module procedure dcargsoption0
293 end interface
294
296 module procedure dcargsputline0
297 end interface
298
299 interface dcargsdebug
300 module procedure dcargsdebug0
301 end interface
302
303 interface dcargshelp
304 module procedure dcargshelp0
305 end interface
306
308 module procedure dcargshelpmsg0
309 end interface
310
311 interface dcargsstrict
312 module procedure dcargsstrict0
313 end interface
314
315 interface dcargsget
316 module procedure dcargsget0
317 end interface
318
319 interface dcargsnumber
320 module procedure dcargsnumber0
321 end interface
322
323 !-----------------------------------------------
324 ! 後方互換用
325 ! For backward compatibility
326 interface open
327 module procedure dcargsopen0
328 end interface
329
330 interface close
331 module procedure dcargsclose0
332 end interface
333
334 interface option
335 module procedure dcargsoption0
336 end interface
337
338 interface putline
339 module procedure dcargsputline0
340 end interface
341
342 interface debug
343 module procedure dcargsdebug0
344 end interface
345
346 interface help
347 module procedure dcargshelp0
348 end interface
349
350 interface helpmsg
351 module procedure dcargshelpmsg0
352 end interface
353
354 interface strict
355 module procedure dcargsstrict0
356 end interface
357
358 interface get
359 module procedure dcargsget0
360 end interface
361
362 interface number
363 module procedure dcargsnumber0
364 end interface
365
366
367 !-------------------------------------
370
371 character(STRING), allocatable, save:: argstr_table(:)
372
376
377 integer, save:: argind_count = -1
378
380
381 !-------------------------------------
384
385 type(CMD_OPTS_INTERNAL), allocatable, save :: cmd_opts_list(:)
386
390
391 character(STRING), allocatable, save:: cmd_argv_list(:)
392
396
397contains
398
427 subroutine dcargsopen0(arg)
428 use dc_message, only: messagenotify
429 implicit none
430 type(args), intent(out) :: arg
431 integer:: cmd_opts_max
432 character(len = *), parameter :: subname = 'DCArgsOpen'
433 continue
434 if (arg % initialized) then
435 call messagenotify('W', subname, 'This argument (type ARGS) is already opend.')
436 return
437 end if
438 call buildargtable
439 call sortargtable
440 cmd_opts_max = size(cmd_opts_list)
441 allocate(arg % cmd_opts_list(cmd_opts_max))
442 arg % cmd_opts_list = cmd_opts_list
443 nullify( arg % opt_table )
444 arg % initialized = .true.
445 end subroutine dcargsopen0
446
462 subroutine dcargsclose0(arg)
463 use dc_hash, only: dchashdelete
464 implicit none
465 type(args), intent(inout) :: arg
466 integer :: i
467 continue
468 if (arg % initialized) then
469 if ( associated( arg % opt_table ) ) then
470 do i = 1, size(arg % opt_table)
471 deallocate(arg % opt_table(i) % options)
472 end do
473
474 deallocate(arg % opt_table)
475 end if
476
477 deallocate(arg % cmd_opts_list)
478 deallocate(argstr_table)
479 deallocate(cmd_argv_list)
480 deallocate(cmd_opts_list)
481
482 call dchashdelete(arg % helpmsg)
483 end if
484 end subroutine dcargsclose0
485
558 subroutine dcargsoption0(arg, options, flag, value, help)
559 use dc_message, only: messagenotify
560 implicit none
561 type(args), intent(inout) :: arg
562 character(len = *), intent(in) :: options(:)
563 logical, intent(out) :: flag
564 character(len = *), intent(out), optional :: value
565 character(len = *), intent(in), optional :: help
566 integer :: i, j, options_size, table_size
567 type(opt_entry), allocatable :: local_tables(:)
568 character(len = STRING) :: opt_name, opt_value, opt_full
569 character(len = *), parameter :: subname = 'DCArgsOption'
570 continue
571 flag = .false.
572 if (present(value)) value = ''
573 if (.not. arg % initialized) then
574 call messagenotify('W', subname, 'Call Open before Option in dc_args.')
575 call dcargsopen(arg)
576 end if
577 options_size = size(options)
578 if (options_size < 1) then
579 return
580 end if
581
582 !-----------------------------------
583 ! 構造体 ARGS へのヘルプメッセージ用の情報登録
584 ! * まずはテーブル arg % opt_table を一つ広げる.
585 !-----------------------------------
586 if ( .not. associated( arg % opt_table ) ) then
587 ! 1 つめのオプション指定
588 !
589 table_size = 0
590 allocate(arg % opt_table(table_size + 1))
591 else
592 ! 2 つめ以降のオプション指定
593 !
594 table_size = size(arg % opt_table)
595 allocate(local_tables(table_size))
596 local_tables(1:table_size) = arg % opt_table(1:table_size)
597 deallocate(arg % opt_table)
598 allocate(arg % opt_table(table_size + 1))
599 arg % opt_table(1:table_size) = local_tables(1:table_size)
600 deallocate(local_tables)
601 end if
602
603 !----- 値の代入 -----
604 allocate(arg % opt_table(table_size + 1) % options(options_size))
605 arg % opt_table(table_size + 1) % options = options
606 arg % opt_table(table_size + 1) % help_message = ''
607 if (present(help)) then
608 arg % opt_table(table_size + 1) % help_message = help
609 end if
610 arg % opt_table(table_size + 1) % optvalue_flag = present(value)
611
612
613 !----- options の正規化 -----
614 do i = 1, options_size
615 opt_full = arg % opt_table(table_size + 1) % options(i)
616 if (dcoptionformc(opt_full, opt_name, opt_value)) then
617 arg % opt_table(table_size + 1) % options(i) = opt_name
618 else
619 if (len(trim(adjustl(opt_full))) < 2) then
620 arg % opt_table(table_size + 1) % options(i) = &
621 & '-' // trim(adjustl(opt_full))
622 else
623 arg % opt_table(table_size + 1) % options(i) = &
624 & '--' // trim(adjustl(opt_full))
625 end if
626 end if
627 end do
628
629 ! arg % cmd_opts_list 内の探査と flag, value への代入
630 ! 呼ばれたものに関しては arg % cmd_opts_list % flag_called を
631 ! .true. に
632 do i = 1, options_size
633 do j = 1, size(arg % cmd_opts_list)
634 if (trim(arg % opt_table(table_size + 1) % options(i)) &
635 & == trim(arg % cmd_opts_list(j) % name)) then
636 flag = .true.
637 if (present(value)) then
638 value = arg % cmd_opts_list(j) % value
639 end if
640 arg % cmd_opts_list(j) % flag_called = .true.
641 end if
642 end do
643 end do
644 end subroutine dcargsoption0
645
667 subroutine dcargsdebug0(arg)
668 use dc_types, only: string
669 use dc_string, only: stoa, stoi
670 use dc_trace, only: setdebug
671 use dc_message, only: messagenotify
672 implicit none
673 type(args), intent(inout) :: arg
674 logical :: OPT_debug
675 character(STRING) :: VAL_debug
676 character(len = *), parameter :: subname = 'DCArgsDebug'
677 continue
678 if (.not. arg % initialized) then
679 call messagenotify('W', subname, 'Call Open before Debug in dc_args.')
680 call dcargsopen(arg)
681 end if
682 call option(arg, stoa('-D', '--debug'), opt_debug, val_debug, &
683 & help="call dc_trace#SetDebug (display a lot of messages for debug). " // &
684 & "VAL is unit number (default is standard output)")
685 if (opt_debug) then
686 if (trim(val_debug) == '') then
687 call setdebug
688 else
689 call setdebug(stoi(val_debug))
690 end if
691 end if
692 return
693 end subroutine dcargsdebug0
694
695
737 subroutine dcargshelp0(arg, force)
738 use dc_types, only: string, stdout
741 use dc_message, only: messagenotify
743 implicit none
744 type(args), intent(inout) :: arg
745 logical, intent(in), optional :: force
746 logical :: OPT_help, found, end
747 character(STRING) :: VAL_help, options_msg, help_msg, category
748 character(STRING), pointer :: localopts(:) => null()
749 integer :: unit, i
750 character(len = *), parameter :: subname = 'DCArgsHelp'
751 continue
752 if (.not. arg % initialized) then
753 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
754 call dcargsopen(arg)
755 end if
756 call dcargsoption(arg, stoa('-h', '-H', '--help'), opt_help, val_help, &
757 & help="display this help and exit. " // &
758 & "VAL is unit number (default is standard output)")
759 if (.not. opt_help .and. .not. present_and_true(force)) then
760 return
761 end if
762 if (trim(val_help) == '') then
763 unit = stdout
764 else
765 unit = stoi(val_help)
766 end if
767
768 call printf(unit, '')
769
770 call dchashget(arg % helpmsg, 'TITLE', help_msg, found)
771 if (found) then
772 call printf(unit, '%c', c1=trim(help_msg))
773 call printf(unit, '')
774 call dchashdelete(arg % helpmsg, 'TITLE')
775 end if
776
777 call dchashget(arg % helpmsg, 'OVERVIEW', help_msg, found)
778 if (found) then
779 call printf(unit, 'Overview::')
780 call printautolinefeed(unit, help_msg, indent=' ')
781 call printf(unit, '')
782 call dchashdelete(arg % helpmsg, 'OVERVIEW')
783 end if
784
785 call dchashget(arg % helpmsg, 'USAGE', help_msg, found)
786 if (found) then
787 call printf(unit, 'Usage::')
788 call printautolinefeed(unit, help_msg, indent=' ')
789 call printf(unit, '')
790 call dchashdelete(arg % helpmsg, 'USAGE')
791 end if
792
793 call printf(unit, 'Options::')
794 if ( associated(arg % opt_table) ) then
795 do i = 1, size(arg % opt_table)
796 options_msg = ' '
797 if (arg % opt_table(i) % optvalue_flag) then
798 call concat(arg % opt_table(i) % options, '=VAL', localopts)
799 else
800 allocate(localopts(size(arg % opt_table(i) % options)))
801 localopts = arg % opt_table(i) % options
802 end if
803 options_msg = trim(options_msg) // trim(joinchar(localopts))
804 deallocate(localopts)
805 call printf(unit, ' %c', c1=trim(options_msg))
806 call printautolinefeed(unit, &
807 & arg % opt_table(i) % help_message, indent=' ')
808 call printf(unit, '')
809 end do
810 end if
811
812 call dchashrewind(arg % helpmsg)
813 do
814 call dchashnext(arg % helpmsg, category, help_msg, end)
815 if (end) exit
816
817 call printf(unit, '%c%c::', &
818 & c1=trim(uchar(category(1:1))), c2=trim(lchar(category(2:))))
819 call printautolinefeed(unit, help_msg, indent=' ')
820 call printf(unit, '')
821
822 enddo
823
824 call dcargsclose(arg)
825
826 stop
827 end subroutine dcargshelp0
828
939 subroutine dcargshelpmsg0(arg, category, msg)
940 use dc_hash, only: dchashput
941 use dc_string, only: uchar
942 use dc_message, only: messagenotify
943 implicit none
944 type(args), intent(inout) :: arg
945 character(*), intent(in) :: category
946 character(*), intent(in) :: msg
947 character(len = *), parameter :: subname = 'DCArgsHelpMsg'
948 continue
949 if (.not. arg % initialized) then
950 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
951 call dcargsopen(arg)
952 end if
953 call dchashput(arg % helpmsg, key=uchar(category), value=msg)
954 end subroutine dcargshelpmsg0
955
956
996 subroutine dcargsstrict0(arg, severe)
997 use dc_types, only: string
999 use dc_message, only: messagenotify
1000 implicit none
1001 type(args), intent(inout) :: arg
1002 logical, intent(in), optional :: severe
1003 character(STRING) :: err_mess
1004 integer :: i
1005 character(len = *), parameter :: subname = 'DCArgsStrict'
1006 continue
1007 if (.not. arg % initialized) then
1008 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
1009 call dcargsopen(arg)
1010 end if
1011 do i = 1, size(arg % cmd_opts_list)
1012 err_mess = trim(arg % cmd_opts_list(i) % name) // ' is invalid option.'
1013 if (.not. arg % cmd_opts_list(i) % flag_called) then
1014 if (present_and_true(severe)) then
1015 call messagenotify('E', subname, err_mess)
1016 else
1017 call messagenotify('W', subname, err_mess)
1018 end if
1019 end if
1020 end do
1021 end subroutine dcargsstrict0
1022
1023
1048 subroutine dcargsget0(arg, argv)
1049 use dc_string, only: stoa, stoi, printf, concat, joinchar
1050 use dc_present, only: present_and_true
1051 use dc_message, only: messagenotify
1052 implicit none
1053 type(args), intent(inout) :: arg
1054 character(*), pointer :: argv(:) !(out)
1055 integer :: i, cmd_argv_max
1056 character(len = *), parameter :: subname = 'DCArgsGet'
1057 continue
1058 if (.not. arg % initialized) then
1059 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
1060 call dcargsopen(arg)
1061 end if
1062 cmd_argv_max = size(cmd_argv_list)
1063 allocate(argv(cmd_argv_max))
1064 do i = 1, cmd_argv_max
1065 argv(i) = cmd_argv_list(i)
1066 end do
1067 end subroutine dcargsget0
1068
1086 function dcargsnumber0(arg) result(result)
1087 use dc_message, only: messagenotify
1088 implicit none
1089 type(args), intent(inout) :: arg
1090 integer :: result
1091 character(len = *), parameter :: subname = 'DCArgsNumber'
1092 continue
1093 if (.not. arg % initialized) then
1094 call messagenotify('W', subname, 'Call Open before Help in dc_args.')
1095 call dcargsopen(arg)
1096 end if
1097 result = size(cmd_argv_list)
1098 end function dcargsnumber0
1099
1117 subroutine dcargsputline0(arg)
1118 use dc_types, only: stdout
1119 use dc_string, only: printf, joinchar
1120 implicit none
1121 type(args), intent(in) :: arg
1122 integer :: i
1123 continue
1124 if (.not. arg % initialized) then
1125 call printf(stdout, '#<ARGS:: @initialized=%y>', l=(/arg % initialized/))
1126 return
1127 end if
1128 call printf(stdout, '#<ARGS:: @initialized=%y,', l=(/arg % initialized/))
1129 call printf(stdout, ' @opt_table(:)=')
1130 if ( associated(arg % opt_table) ) then
1131 do i = 1, size(arg % opt_table)
1132 call printf(stdout, ' #<OPT_ENTRY:: ')
1133 call printf(stdout, ' @options=%c, @help_message=%c, @optvalue_flag=%y', &
1134 & c1=trim(joinchar(arg % opt_table(i) % options)), &
1135 & c2=trim(arg % opt_table(i) % help_message), &
1136 & l=(/arg % opt_table(i) % optvalue_flag/))
1137 call printf(stdout, ' >')
1138 end do
1139 end if
1140 call printf(stdout, ' ,')
1141 call printf(stdout, ' @cmd_opts_list(:)=')
1142 do i = 1, size(arg % cmd_opts_list)
1143 call printf(stdout, ' #<CMD_OPTS_INTERNAL:: ')
1144 call printf(stdout, ' @name=%c, @value=%c, @flag_called=%y', &
1145 & c1=trim(arg % cmd_opts_list(i) % name), &
1146 & c2=trim(arg % cmd_opts_list(i) % value), &
1147 & l=(/arg % cmd_opts_list(i) % flag_called/))
1148 call printf(stdout, ' >')
1149 end do
1150 call printf(stdout, ' ,')
1151 call printf(stdout, ' @cmd_argv_list(:)=%c', &
1152 & c1=trim(joinchar(cmd_argv_list)))
1153 call printf(stdout, '>')
1154
1155 end subroutine dcargsputline0
1156
1192 subroutine printautolinefeed(unit, fmt, length, indent)
1193 use dc_types, only: string, stdout
1194 use dc_string, only: split
1195 implicit none
1196 character(*), intent(in) :: fmt
1197 integer, intent(in), optional :: length ! 一行の長さ
1198 character(*), intent(in), optional :: indent ! 字下げ文字列
1199 integer, intent(in), optional :: unit ! 出力装置
1200 character(STRING), pointer :: carray_tmp(:) => null()
1201 character(STRING) :: store_str
1202 integer, parameter :: default_len = 70
1203 integer :: i, split_len, indent_len, unit_num
1204 logical :: new_line_flag
1205 continue
1206 if (present(unit)) then
1207 unit_num = unit
1208 else
1209 unit_num = stdout
1210 end if
1211
1212 if (present(indent)) then
1213 indent_len = len(indent)
1214 else
1215 indent_len = 0
1216 end if
1217
1218 if (present(length)) then
1219 split_len = length - indent_len
1220 else
1221 split_len = default_len - indent_len
1222 end if
1223
1224
1225 nullify(carray_tmp)
1226 call split(fmt, carray_tmp, '')
1227 store_str = ''
1228 new_line_flag = .true.
1229 i = 1
1230 do
1231 if (i > size(carray_tmp)) then
1232 write(unit_num, '(A)') trim(store_str)
1233 exit
1234 end if
1235
1236 if (len(trim(store_str)) + len(trim(carray_tmp(i))) > split_len) then
1237 if (new_line_flag) then
1238 write(unit_num, '(A)') trim(carray_tmp(i))
1239 i = i + 1
1240 else
1241 write(unit_num, '(A)') trim(store_str)
1242 store_str = ''
1243 new_line_flag = .true.
1244 end if
1245 cycle
1246 end if
1247
1248 if (new_line_flag .and. present(indent)) then
1249 store_str = indent // trim(carray_tmp(i))
1250 else
1251 store_str = trim(store_str) // ' ' // trim(carray_tmp(i))
1252 end if
1253 new_line_flag = .false.
1254 i = i + 1
1255 end do
1256
1257 end subroutine printautolinefeed
1258
1280 subroutine sortargtable
1281 use dc_types, only: string
1282 implicit none
1283 character(STRING):: raw_arg, name, value
1284 integer:: i, cmd_argv_count, cmd_opts_count, cmd_argv_max, cmd_opts_max
1285 continue
1286 if (allocated(cmd_opts_list)) return
1287 cmd_argv_count = 0
1288 cmd_opts_count = 0
1289 check_count: do, i = 1, argind_count
1290 raw_arg = argstr_table(i)
1291 if (dcoptionformc(raw_arg, name, value)) then
1292 cmd_opts_count = cmd_opts_count + 1
1293 else
1294 cmd_argv_count = cmd_argv_count + 1
1295 end if
1296 end do check_count
1297
1298 cmd_argv_max = cmd_argv_count
1299 cmd_opts_max = cmd_opts_count
1300
1301 allocate(cmd_argv_list(cmd_argv_max))
1302 allocate(cmd_opts_list(cmd_opts_max))
1303
1304 cmd_argv_count = 0
1305 cmd_opts_count = 0
1306 arg_get : do, i = 1, argind_count
1307 raw_arg = argstr_table(i)
1308 if (dcoptionformc(raw_arg, name, value)) then
1309 cmd_opts_count = cmd_opts_count + 1
1310 cmd_opts_list(cmd_opts_count) % name = name
1311 cmd_opts_list(cmd_opts_count) % value = value
1312 cmd_opts_list(cmd_opts_count) % flag_called = .false.
1313 else
1314 cmd_argv_count = cmd_argv_count + 1
1315 cmd_argv_list(cmd_argv_count) = raw_arg
1316 end if
1317 end do arg_get
1318 end subroutine sortargtable
1319
1341 subroutine buildargtable
1343 use dc_types, only: string
1344 implicit none
1345 integer:: i, narg, nargmax
1346 character(len = STRING):: value
1347 character(len = STRING), allocatable:: localtab(:)
1348 continue
1349 if (argind_count >= 0) return
1350 nargmax = sysdepargcount()
1351 allocate(localtab(nargmax))
1352 narg = 0
1353 do, i = 1, nargmax
1354 call sysdepargget(i, value)
1355 narg = narg + 1
1356 localtab(narg) = value
1357 enddo
1358 argind_count = narg
1359 allocate(argstr_table(narg))
1360 argstr_table(1: narg) = localtab(1: narg)
1361 deallocate(localtab)
1362 end subroutine buildargtable
1363
1441 function dcoptionformc(argument, name, value) result(result)
1442 implicit none
1443 character(len = *), intent(in):: argument
1444 character(len = *), intent(out):: name, value
1445 logical :: result
1446 integer:: equal
1447 continue
1448 equal = index(argument, '=')
1449 if (argument(1:1) == '-' .and. argument(2:2) /= '-') then
1450 ! Short Option
1451 if (equal == 0) then
1452 name = argument(1:2)
1453 value = ""
1454 else
1455 name = argument(1:2)
1456 value = argument(equal+1: )
1457 endif
1458 result = .true.
1459 elseif (argument(1:2) == '--') then
1460 ! Long Option
1461 if (equal == 0) then
1462 name = argument
1463 value = ""
1464 else
1465 name = argument(1:equal-1)
1466 value = argument(equal+1: )
1467 endif
1468 result = .true.
1469! elseif (equal == 0 .and. &
1470! & verify(argument(1:equal-1), WORDCHARS) == 0) then
1471! ! ???
1472! name = argument(1:equal-1)
1473! value = argument(equal+1: )
1474! result = .true.
1475 else
1476 ! No Option (normal arguments)
1477 name = ""
1478 value = ""
1479 result = .false.
1480 endif
1481 end function dcoptionformc
1482
1483
1484
1485end module dc_args
コマンドライン引数の解析
Definition dc_args.f90:193
ハッシュ (連想配列) モジュール
Definition dc_hash.f90:143
メッセージの出力
省略可能な制御パラメータの判定
logical function, public present_and_true(arg)
文字型変数の操作
Definition dc_string.f90:83
character(string) function, public joinchar(carray, expr)
デバッグ時の追跡用モジュール
Definition dc_trace.f90:150
subroutine, public setdebug(debug)
Definition dc_trace.f90:336
種別型パラメタを提供します。
Definition dc_types.f90:55
integer, parameter, public stdout
標準出力の装置番号
Definition dc_types.f90:117
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition dc_types.f90:137
システムに依存する手続きのインタフェースを提供します
Definition sysdep.f90:54
subroutine, public sysdepargget(index, val)
コマンドライン引数を取得します
Definition sysdep.f90:138
integer function, public sysdepargcount()
コマンドライン引数の数を取得します
Definition sysdep.f90:114