11 integer,
parameter :: dp = kind(0.0d0)
13 integer,
parameter :: CFG_num_types = 4
18 integer,
parameter :: cfg_unknown_type = 0
21 integer,
parameter :: cfg_set_by_default = 1
23 integer,
parameter :: cfg_set_by_arg = 2
25 integer,
parameter :: cfg_set_by_file = 3
29 [character(len=10) ::
"storage",
"integer",
"real",
"string ",
"logical"]
39 character,
parameter :: tab_char = char(9)
42 character(len=*),
parameter :: cfg_separators =
" ,'"""//tab_char
45 character(len=*),
parameter :: cfg_category_separator =
"%"
48 character(len=*),
parameter :: unstored_data_string =
"__UNSTORED_DATA_STRING"
54 character(len=CFG_name_len) :: var_name
56 character(len=CFG_string_len) :: description
62 logical :: dynamic_size
66 integer :: set_by = cfg_set_by_default
68 character(len=CFG_max_line_len) :: stored_data
72 real(dp),
allocatable :: real_data(:)
73 integer,
allocatable :: int_data(:)
74 character(len=CFG_string_len),
allocatable :: char_data(:)
75 logical,
allocatable :: logic_data(:)
80 logical :: sorted = .false.
81 integer :: num_vars = 0
82 type(cfg_var_t),
allocatable :: vars(:)
87 module procedure add_real, add_real_array
88 module procedure add_int, add_int_array
89 module procedure add_string, add_string_array
90 module procedure add_logic, add_logic_array
95 module procedure get_real, get_real_array
96 module procedure get_int, get_int_array
97 module procedure get_logic, get_logic_array
98 module procedure get_string, get_string_array
103 module procedure add_get_real, add_get_real_array
104 module procedure add_get_int, add_get_int_array
105 module procedure add_get_logic, add_get_logic_array
106 module procedure add_get_string, add_get_string_array
146 type(
cfg_t),
intent(inout) :: cfg
148 logical,
intent(in),
optional :: ignore_unknown
149 character(len=CFG_max_line_len) :: arg
150 integer :: ix, n, arg_status
151 logical :: valid_syntax, strict
152 character(len=4) :: extension
154 strict = .true.;
if (
present(ignore_unknown)) strict = .not. ignore_unknown
156 do ix = 1, command_argument_count()
157 call get_command_argument(ix, arg, status=arg_status)
159 if (arg_status > 0)
then
160 call handle_error(
"Error in get_command_argument (status > 0)")
161 else if (arg_status == -1)
then
162 call handle_error(
"Argument too long, increase CFG_max_line_len")
166 if (n > 3) extension = arg(n-3:)
169 if (arg(1:1) ==
'-' .and. arg(2:2) /=
'-')
then
171 call parse_line(cfg, cfg_set_by_arg, arg(2:), valid_syntax)
173 if (.not. valid_syntax)
then
174 call handle_error(
"Invalid syntax on command line: " // trim(arg))
176 else if (arg(1:1) /=
'-' .and. &
177 (extension ==
".cfg" .or. extension ==
".txt"))
then
180 else if (strict)
then
181 print *,
"This error message can be disabled by setting"
182 print *,
"ignore_unknown = .true. for CFG_update_from_arguments"
183 call handle_error(
"Unknown argument: " // trim(arg))
190 type(
cfg_t),
intent(inout) :: cfg
191 character(len=*),
intent(in) :: line
192 logical :: valid_syntax
195 call parse_line(cfg, cfg_set_by_arg, line, valid_syntax)
197 if (.not. valid_syntax)
then
198 call handle_error(
"CFG_set: invalid syntax")
204 subroutine handle_error(err_string)
205 character(len=*),
intent(in) :: err_string
207 print *,
"The following error occured in m_config:"
208 print *, trim(err_string)
213 end subroutine handle_error
216 subroutine get_var_index(cfg, var_name, ix)
217 type(
cfg_t),
intent(in) :: cfg
218 character(len=*),
intent(in) :: var_name
219 integer,
intent(out) :: ix
223 call binary_search_variable(cfg, var_name, ix)
226 do i = 1, cfg%num_vars
227 if (cfg%vars(i)%var_name == var_name)
exit
231 if (i == cfg%num_vars + 1) i = -1
235 end subroutine get_var_index
239 type(
cfg_t),
intent(inout) :: cfg
240 character(len=*),
intent(in) :: filename
242 integer,
parameter :: my_unit = 123
244 integer :: line_number
245 logical :: valid_syntax
246 character(len=CFG_name_len) :: line_fmt
247 character(len=CFG_string_len) :: err_string
248 character(len=CFG_max_line_len) :: line
249 character(len=CFG_name_len) :: category
251 open(my_unit, file=trim(filename), status=
"old", action=
"read")
258 read(my_unit, fmt=trim(line_fmt), err=998,
end=999) line
259 line_number = line_number + 1
262 write(err_string, *)
"Possible truncation in line ", line_number, &
263 " from ", trim(filename)
264 call handle_error(err_string)
267 call parse_line(cfg, cfg_set_by_file, line, valid_syntax, category)
269 if (.not. valid_syntax)
then
270 write(err_string, *)
"Cannot read line ", line_number, &
271 " from ", trim(filename)
272 call handle_error(err_string)
277998
write(err_string,
"(A,I0,A,I0)")
" IOSTAT = ", io_state, &
278 " while reading from " // trim(filename) //
" at line ", &
280 call handle_error(
"CFG_read_file:" // err_string)
283999
close(my_unit, iostat=io_state)
288 subroutine parse_line(cfg, set_by, line_arg, valid_syntax, category_arg)
289 type(
cfg_t),
intent(inout) :: cfg
290 integer,
intent(in) :: set_by
291 character(len=*),
intent(in) :: line_arg
292 logical,
intent(out) :: valid_syntax
293 character(len=CFG_name_len),
intent(inout),
optional :: category_arg
294 character(len=CFG_name_len) :: var_name, category
295 integer :: ix, equal_sign_ix
297 character(len=CFG_max_line_len) :: line
299 valid_syntax = .true.
304 if (
present(category_arg)) category = category_arg
306 call trim_comment(line,
'#;')
309 if (line ==
"")
return
312 equal_sign_ix = scan(line,
'=')
315 if (equal_sign_ix == 0)
then
320 if (line(1:1) /=
'[' .or. ix == 0)
then
321 valid_syntax = .false.
324 if (
present(category_arg)) category_arg = line(2:ix-1)
329 if (line(equal_sign_ix-1:equal_sign_ix) ==
'+=')
then
331 var_name = line(1 : equal_sign_ix - 2)
334 var_name = line(1 : equal_sign_ix - 1)
338 if (var_name(1:2) /=
" " .and. var_name(1:1) /= tab_char)
then
343 ix = verify(var_name, tab_char)
344 var_name(1:ix-1) =
""
347 var_name = adjustl(var_name)
350 if (category /=
"")
then
351 var_name = trim(category) // cfg_category_separator // var_name
354 line = line(equal_sign_ix + 1:)
357 call get_var_index(cfg, var_name, ix)
361 call prepare_store_var(cfg, trim(var_name), cfg_unknown_type, 1, &
362 "Not yet created", ix, .false.)
363 cfg%vars(ix)%stored_data = line
366 cfg%vars(ix)%stored_data = &
367 trim(cfg%vars(ix)%stored_data) // trim(line)
369 cfg%vars(ix)%stored_data = line
373 if (cfg%vars(ix)%var_type /= cfg_unknown_type)
then
374 call read_variable(cfg%vars(ix))
379 cfg%vars(ix)%set_by = set_by
381 end subroutine parse_line
383 subroutine read_variable(var)
384 type(cfg_var_t),
intent(inout) :: var
385 integer :: n, n_entries
390 call get_fields_string(var%stored_data, cfg_separators, &
393 if (var%var_size /= n_entries)
then
395 if (.not. var%dynamic_size)
then
398 var%char_data(1) = trim(var%stored_data(ix_start(1):ix_end(n_entries)))
401 call handle_error(
"read_variable: variable [" // &
402 & trim(var%var_name) //
"] has the wrong size")
405 var%var_size = n_entries
406 call resize_storage(var)
412 select case (var%var_type)
414 read(var%stored_data(ix_start(n):ix_end(n)), *, iostat=stat) var%int_data(n)
416 read(var%stored_data(ix_start(n):ix_end(n)), *, iostat=stat) var%real_data(n)
418 var%char_data(n) = trim(var%stored_data(ix_start(n):ix_end(n)))
420 read(var%stored_data(ix_start(n):ix_end(n)), *, iostat=stat) var%logic_data(n)
424 write (*, *)
"** m_config error **"
425 write (*, *)
"reading variable: ", trim(var%var_name)
426 write (*, *)
"variable type: ", trim(
cfg_type_names(var%var_type))
427 write (*, *)
"parsing value: ", var%stored_data(ix_start(n):ix_end(n))
428 write (*,
"(A,I0)")
" iostat value: ", stat
432 end subroutine read_variable
434 subroutine trim_comment(line, comment_chars)
435 character(len=*),
intent(inout) :: line
436 character(len=*),
intent(in) :: comment_chars
437 character :: current_char, need_char
445 current_char = line(n:n)
447 if (need_char ==
"")
then
448 if (current_char ==
"'")
then
450 else if (current_char ==
'"')
then
452 else if (index(comment_chars, current_char) /= 0)
then
456 else if (current_char == need_char)
then
462 end subroutine trim_comment
465 type(
cfg_t),
intent(in) :: cfg
467 character(len=CFG_string_len) :: err_string
469 do n = 1, cfg%num_vars
470 if (cfg%vars(n)%var_type == cfg_unknown_type)
then
471 write(err_string, *)
"CFG_check: unknown variable ", &
472 trim(cfg%vars(n)%var_name),
" specified"
473 call handle_error(err_string)
479 subroutine cfg_write(cfg_in, filename, hide_unused, custom_first)
481 type(
cfg_t),
intent(in) :: cfg_in
482 character(len=*),
intent(in) :: filename
484 logical,
intent(in),
optional :: hide_unused
486 logical,
intent(in),
optional :: custom_first
487 logical :: hide_not_used, sort_set_by
489 integer :: i, j, n, io_state, myunit
490 integer :: n_custom_set
491 integer,
allocatable :: cfg_order(:)
492 character(len=CFG_name_len) :: name_format, var_name
493 character(len=CFG_name_len) :: category, prev_category
494 character(len=CFG_string_len) :: err_string
496 hide_not_used = .false.
497 if (
present(hide_unused)) hide_not_used = hide_unused
499 sort_set_by = .false.
500 if (
present(custom_first)) sort_set_by = custom_first
504 if (.not. cfg%sorted)
call cfg_sort(cfg)
506 write(name_format, fmt=
"(A,I0,A)")
"(A,A",
cfg_name_len,
",A)"
508 if (filename ==
"stdout")
then
511 open(newunit=myunit, file=filename, action=
"WRITE")
517 allocate(cfg_order(cfg%num_vars))
518 if (sort_set_by)
then
520 do i = 1, cfg%num_vars
521 if (cfg%vars(i)%set_by /= cfg_set_by_default)
then
528 do i = 1, cfg%num_vars
529 if (cfg%vars(i)%set_by == cfg_set_by_default)
then
536 cfg_order(:) = [(i, i = 1, cfg%num_vars)]
539 do n = 1, cfg%num_vars
542 if (.not. cfg%vars(i)%used .and. hide_not_used) cycle
543 if (cfg%vars(i)%var_type == cfg_unknown_type) cycle
545 if (sort_set_by .and. n == n_custom_set + 1)
then
546 write(myunit, err=998, fmt=
"(A)")
'# Variables below have default values'
547 write(myunit, err=998, fmt=
"(A)")
''
551 call split_category(cfg%vars(i), category, var_name)
553 if (category /= prev_category .and. category /=
'')
then
554 write(myunit, err=998, fmt=
"(A)")
'[' // trim(category) //
']'
555 prev_category = category
559 if (category /=
"")
then
560 write(myunit, err=998, fmt=
"(A,A,A)")
" # ", &
561 trim(cfg%vars(i)%description),
":"
562 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
563 " " // trim(var_name) //
" ="
565 write(myunit, err=998, fmt=
"(A,A,A)")
"# ", &
566 trim(cfg%vars(i)%description),
":"
567 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
568 trim(var_name) //
" ="
571 select case(cfg%vars(i)%var_type)
573 do j = 1, cfg%vars(i)%var_size
574 write(myunit, advance=
"NO", err=998, fmt=
"(A,I0)") &
575 " ", cfg%vars(i)%int_data(j)
578 do j = 1, cfg%vars(i)%var_size
579 write(myunit, advance=
"NO", err=998, fmt=
"(A,ES11.4)") &
580 " ", cfg%vars(i)%real_data(j)
583 do j = 1, cfg%vars(i)%var_size
584 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
585 " '" // trim(cfg%vars(i)%char_data(j)) //
"'"
588 do j = 1, cfg%vars(i)%var_size
589 write(myunit, advance=
"NO", err=998, fmt=
"(A,L1)") &
590 " ", cfg%vars(i)%logic_data(j)
593 write(myunit, err=998, fmt=
"(A)")
""
594 write(myunit, err=998, fmt=
"(A)")
""
597 if (myunit /= output_unit)
close(myunit, err=999, iostat=io_state)
602 write(err_string, *)
"CFG_write error: io_state = ", io_state, &
603 " while writing ", trim(var_name),
" to ", filename
604 call handle_error(err_string)
607 write(err_string, *)
"CFG_write error: io_state = ", io_state, &
608 " while writing to ", filename
609 call handle_error(err_string)
616 type(
cfg_t),
intent(in) :: cfg_in
617 character(len=*),
intent(in) :: filename
618 logical,
intent(in),
optional :: hide_unused
619 logical :: hide_not_used
620 integer :: i, j, io_state, myunit
622 character(len=CFG_name_len) :: name_format, var_name
623 character(len=CFG_name_len) :: category, prev_category
624 character(len=CFG_string_len) :: err_string
626 hide_not_used = .false.
627 if (
present(hide_unused)) hide_not_used = hide_unused
631 if (.not. cfg%sorted)
call cfg_sort(cfg)
633 write(name_format, fmt=
"(A,I0,A)")
"(A,A",
cfg_name_len,
",A)"
635 if (filename ==
"stdout")
then
639 open(myunit, file=filename, action=
"WRITE")
644 write(myunit, err=998, fmt=
"(A)")
"# Configuration file (markdown format)"
645 write(myunit, err=998, fmt=
"(A)")
""
647 do i = 1, cfg%num_vars
649 if (.not. cfg%vars(i)%used .and. hide_not_used) cycle
650 if (cfg%vars(i)%var_type == cfg_unknown_type) cycle
653 call split_category(cfg%vars(i), category, var_name)
655 if (category /= prev_category)
then
656 if (category ==
"") category =
"No category"
657 write(myunit, err=998, fmt=
"(A)")
'## ' // trim(category)
658 write(myunit, err=998, fmt=
"(A)")
""
659 prev_category = category
662 write(myunit, err=998, fmt=
"(A)")
"* " // trim(cfg%vars(i)%description)
663 write(myunit, err=998, fmt=
"(A)")
""
664 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
665 ' ' // trim(var_name) //
" ="
667 select case(cfg%vars(i)%var_type)
669 do j = 1, cfg%vars(i)%var_size
670 write(myunit, advance=
"NO", err=998, fmt=
"(A,I0)") &
671 " ", cfg%vars(i)%int_data(j)
674 do j = 1, cfg%vars(i)%var_size
675 write(myunit, advance=
"NO", err=998, fmt=
"(A,E11.4)") &
676 " ", cfg%vars(i)%real_data(j)
679 do j = 1, cfg%vars(i)%var_size
680 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
681 " '" // trim(cfg%vars(i)%char_data(j)) //
"'"
684 do j = 1, cfg%vars(i)%var_size
685 write(myunit, advance=
"NO", err=998, fmt=
"(A,L1)") &
686 " ", cfg%vars(i)%logic_data(j)
689 write(myunit, err=998, fmt=
"(A)")
""
690 write(myunit, err=998, fmt=
"(A)")
""
693 if (myunit /= output_unit)
close(myunit, err=999, iostat=io_state)
698 write(err_string, *)
"CFG_write_markdown error: io_state = ", io_state, &
699 " while writing ", trim(var_name),
" to ", filename
700 call handle_error(err_string)
703 write(err_string, *)
"CFG_write_markdown error: io_state = ", io_state, &
704 " while writing to ", filename
705 call handle_error(err_string)
709 subroutine split_category(variable, category, var_name)
710 type(cfg_var_t),
intent(in) :: variable
711 character(CFG_name_len),
intent(out) :: category
712 character(CFG_name_len),
intent(out) :: var_name
715 ix = index(variable%var_name, cfg_category_separator)
719 var_name = variable%var_name
721 category = variable%var_name(1:ix-1)
722 var_name = variable%var_name(ix+1:)
725 end subroutine split_category
729 subroutine resize_storage(variable)
730 type(cfg_var_t),
intent(inout) :: variable
732 select case (variable%var_type)
734 deallocate( variable%int_data )
735 allocate( variable%int_data(variable%var_size) )
737 deallocate( variable%logic_data )
738 allocate( variable%logic_data(variable%var_size) )
740 deallocate( variable%real_data )
741 allocate( variable%real_data(variable%var_size) )
743 deallocate( variable%char_data )
744 allocate( variable%char_data(variable%var_size) )
746 end subroutine resize_storage
750 subroutine prepare_store_var(cfg, var_name, var_type, var_size, &
751 description, ix, dynamic_size)
752 type(
cfg_t),
intent(inout) :: cfg
753 character(len=*),
intent(in) :: var_name, description
754 integer,
intent(in) :: var_type, var_size
755 integer,
intent(out) :: ix
756 logical,
intent(in),
optional :: dynamic_size
759 call get_var_index(cfg, var_name, ix)
762 call ensure_free_storage(cfg)
764 ix = cfg%num_vars + 1
765 cfg%num_vars = cfg%num_vars + 1
766 cfg%vars(ix)%used = .false.
767 cfg%vars(ix)%stored_data = unstored_data_string
770 if (cfg%vars(ix)%var_type /= cfg_unknown_type)
then
771 call handle_error(
"prepare_store_var: variable [" // &
772 & trim(var_name) //
"] already exists")
776 cfg%vars(ix)%var_name = var_name
777 cfg%vars(ix)%description = description
778 cfg%vars(ix)%var_type = var_type
779 cfg%vars(ix)%var_size = var_size
781 if (
present(dynamic_size))
then
782 cfg%vars(ix)%dynamic_size = dynamic_size
784 cfg%vars(ix)%dynamic_size = .false.
787 select case (var_type)
789 allocate( cfg%vars(ix)%int_data(var_size) )
791 allocate( cfg%vars(ix)%real_data(var_size) )
793 allocate( cfg%vars(ix)%char_data(var_size) )
795 allocate( cfg%vars(ix)%logic_data(var_size) )
798 end subroutine prepare_store_var
802 subroutine prepare_get_var(cfg, var_name, var_type, var_size, ix)
803 type(
cfg_t),
intent(inout) :: cfg
804 character(len=*),
intent(in) :: var_name
805 integer,
intent(in) :: var_type, var_size
806 integer,
intent(out) :: ix
807 character(len=CFG_string_len) :: err_string
809 call get_var_index(cfg, var_name, ix)
812 call handle_error(
"CFG_get: variable ["//var_name//
"] not found")
813 else if (cfg%vars(ix)%var_type /= var_type)
then
814 write(err_string, fmt=
"(A)")
"CFG_get: variable [" &
815 // var_name //
"] has different type (" // &
818 call handle_error(err_string)
819 else if (cfg%vars(ix)%var_size /= var_size)
then
820 write(err_string, fmt=
"(A,I0,A,I0,A)")
"CFG_get: variable [" &
821 // var_name //
"] has different size (", cfg%vars(ix)%var_size, &
822 ") than requested (", var_size,
")"
823 call handle_error(err_string)
825 cfg%vars(ix)%used = .true.
827 end subroutine prepare_get_var
830 subroutine add_real(cfg, var_name, real_data, comment)
831 type(
cfg_t),
intent(inout) :: cfg
832 character(len=*),
intent(in) :: var_name, comment
833 real(dp),
intent(in) :: real_data
836 call prepare_store_var(cfg, var_name,
cfg_real_type, 1, comment, ix)
838 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
839 call read_variable(cfg%vars(ix))
841 cfg%vars(ix)%real_data(1) = real_data
843 end subroutine add_real
847 subroutine add_real_array(cfg, var_name, real_data, comment, dynamic_size)
848 type(
cfg_t),
intent(inout) :: cfg
849 character(len=*),
intent(in) :: var_name, comment
850 real(dp),
intent(in) :: real_data(:)
851 logical,
intent(in),
optional :: dynamic_size
855 size(real_data), comment, ix, dynamic_size)
857 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
858 call read_variable(cfg%vars(ix))
860 cfg%vars(ix)%real_data = real_data
862 end subroutine add_real_array
865 subroutine add_int(cfg, var_name, int_data, comment)
866 type(
cfg_t),
intent(inout) :: cfg
867 character(len=*),
intent(in) :: var_name, comment
868 integer,
intent(in) :: int_data
873 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
874 call read_variable(cfg%vars(ix))
876 cfg%vars(ix)%int_data(1) = int_data
878 end subroutine add_int
881 subroutine add_int_array(cfg, var_name, int_data, comment, dynamic_size)
882 type(
cfg_t),
intent(inout) :: cfg
883 character(len=*),
intent(in) :: var_name, comment
884 integer,
intent(in) :: int_data(:)
885 logical,
intent(in),
optional :: dynamic_size
889 size(int_data), comment, ix, dynamic_size)
891 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
892 call read_variable(cfg%vars(ix))
894 cfg%vars(ix)%int_data = int_data
896 end subroutine add_int_array
899 subroutine add_string(cfg, var_name, char_data, comment)
900 type(
cfg_t),
intent(inout) :: cfg
901 character(len=*),
intent(in) :: var_name, comment, char_data
905 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
906 call read_variable(cfg%vars(ix))
908 cfg%vars(ix)%char_data(1) = char_data
910 end subroutine add_string
913 subroutine add_string_array(cfg, var_name, char_data, &
914 comment, dynamic_size)
915 type(
cfg_t),
intent(inout) :: cfg
916 character(len=*),
intent(in) :: var_name, comment, char_data(:)
917 logical,
intent(in),
optional :: dynamic_size
921 size(char_data), comment, ix, dynamic_size)
923 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
924 call read_variable(cfg%vars(ix))
926 cfg%vars(ix)%char_data = char_data
928 end subroutine add_string_array
931 subroutine add_logic(cfg, var_name, logic_data, comment)
932 type(
cfg_t),
intent(inout) :: cfg
933 character(len=*),
intent(in) :: var_name, comment
934 logical,
intent(in) :: logic_data
937 call prepare_store_var(cfg, var_name,
cfg_logic_type, 1, comment, ix)
939 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
940 call read_variable(cfg%vars(ix))
942 cfg%vars(ix)%logic_data(1) = logic_data
944 end subroutine add_logic
947 subroutine add_logic_array(cfg, var_name, logic_data, &
948 comment, dynamic_size)
949 type(
cfg_t),
intent(inout) :: cfg
950 character(len=*),
intent(in) :: var_name, comment
951 logical,
intent(in) :: logic_data(:)
952 logical,
intent(in),
optional :: dynamic_size
956 size(logic_data), comment, ix, dynamic_size)
958 if (cfg%vars(ix)%stored_data /= unstored_data_string)
then
959 call read_variable(cfg%vars(ix))
961 cfg%vars(ix)%logic_data = logic_data
963 end subroutine add_logic_array
966 subroutine get_real_array(cfg, var_name, real_data)
967 type(
cfg_t),
intent(inout) :: cfg
968 character(len=*),
intent(in) :: var_name
969 real(dp),
intent(inout) :: real_data(:)
974 real_data = cfg%vars(ix)%real_data
975 end subroutine get_real_array
978 subroutine get_int_array(cfg, var_name, int_data)
979 type(
cfg_t),
intent(inout) :: cfg
980 character(len=*),
intent(in) :: var_name
981 integer,
intent(inout) :: int_data(:)
986 int_data = cfg%vars(ix)%int_data
987 end subroutine get_int_array
990 subroutine get_string_array(cfg, var_name, char_data)
991 type(
cfg_t),
intent(inout) :: cfg
992 character(len=*),
intent(in) :: var_name
993 character(len=*),
intent(inout) :: char_data(:)
998 char_data = cfg%vars(ix)%char_data
999 end subroutine get_string_array
1002 subroutine get_logic_array(cfg, var_name, logic_data)
1003 type(
cfg_t),
intent(inout) :: cfg
1004 character(len=*),
intent(in) :: var_name
1005 logical,
intent(inout) :: logic_data(:)
1009 size(logic_data), ix)
1010 logic_data = cfg%vars(ix)%logic_data
1011 end subroutine get_logic_array
1014 subroutine get_real(cfg, var_name, res)
1015 type(
cfg_t),
intent(inout) :: cfg
1016 character(len=*),
intent(in) :: var_name
1017 real(dp),
intent(out) :: res
1021 res = cfg%vars(ix)%real_data(1)
1022 end subroutine get_real
1025 subroutine get_int(cfg, var_name, res)
1026 type(
cfg_t),
intent(inout) :: cfg
1027 character(len=*),
intent(in) :: var_name
1028 integer,
intent(inout) :: res
1032 res = cfg%vars(ix)%int_data(1)
1033 end subroutine get_int
1036 subroutine get_logic(cfg, var_name, res)
1037 type(
cfg_t),
intent(inout) :: cfg
1038 character(len=*),
intent(in) :: var_name
1039 logical,
intent(out) :: res
1043 res = cfg%vars(ix)%logic_data(1)
1044 end subroutine get_logic
1047 subroutine get_string(cfg, var_name, res)
1048 type(
cfg_t),
intent(inout) :: cfg
1049 character(len=*),
intent(in) :: var_name
1050 character(len=*),
intent(out) :: res
1054 res = cfg%vars(ix)%char_data(1)
1055 end subroutine get_string
1058 subroutine add_get_real_array(cfg, var_name, real_data, &
1059 comment, dynamic_size)
1060 type(
cfg_t),
intent(inout) :: cfg
1061 character(len=*),
intent(in) :: var_name, comment
1062 real(dp),
intent(inout) :: real_data(:)
1063 logical,
intent(in),
optional :: dynamic_size
1065 call add_real_array(cfg, var_name, real_data, comment, dynamic_size)
1066 call get_real_array(cfg, var_name, real_data)
1067 end subroutine add_get_real_array
1070 subroutine add_get_int_array(cfg, var_name, int_data, &
1071 comment, dynamic_size)
1072 type(
cfg_t),
intent(inout) :: cfg
1073 character(len=*),
intent(in) :: var_name, comment
1074 integer,
intent(inout) :: int_data(:)
1075 logical,
intent(in),
optional :: dynamic_size
1077 call add_int_array(cfg, var_name, int_data, comment, dynamic_size)
1078 call get_int_array(cfg, var_name, int_data)
1079 end subroutine add_get_int_array
1082 subroutine add_get_string_array(cfg, var_name, char_data, &
1083 comment, dynamic_size)
1084 type(
cfg_t),
intent(inout) :: cfg
1085 character(len=*),
intent(in) :: var_name, comment
1086 character(len=*),
intent(inout) :: char_data(:)
1087 logical,
intent(in),
optional :: dynamic_size
1089 call add_string_array(cfg, var_name, char_data, comment, dynamic_size)
1090 call get_string_array(cfg, var_name, char_data)
1091 end subroutine add_get_string_array
1094 subroutine add_get_logic_array(cfg, var_name, logic_data, &
1095 comment, dynamic_size)
1096 type(
cfg_t),
intent(inout) :: cfg
1097 character(len=*),
intent(in) :: var_name, comment
1098 logical,
intent(inout) :: logic_data(:)
1099 logical,
intent(in),
optional :: dynamic_size
1101 call add_logic_array(cfg, var_name, logic_data, comment, dynamic_size)
1102 call get_logic_array(cfg, var_name, logic_data)
1103 end subroutine add_get_logic_array
1106 subroutine add_get_real(cfg, var_name, real_data, comment)
1107 type(
cfg_t),
intent(inout) :: cfg
1108 character(len=*),
intent(in) :: var_name, comment
1109 real(dp),
intent(inout) :: real_data
1111 call add_real(cfg, var_name, real_data, comment)
1112 call get_real(cfg, var_name, real_data)
1113 end subroutine add_get_real
1116 subroutine add_get_int(cfg, var_name, int_data, comment)
1117 type(
cfg_t),
intent(inout) :: cfg
1118 character(len=*),
intent(in) :: var_name, comment
1119 integer,
intent(inout) :: int_data
1121 call add_int(cfg, var_name, int_data, comment)
1122 call get_int(cfg, var_name, int_data)
1123 end subroutine add_get_int
1126 subroutine add_get_logic(cfg, var_name, logical_data, comment)
1127 type(
cfg_t),
intent(inout) :: cfg
1128 character(len=*),
intent(in) :: var_name, comment
1129 logical,
intent(inout) :: logical_data
1131 call add_logic(cfg, var_name, logical_data, comment)
1132 call get_logic(cfg, var_name, logical_data)
1133 end subroutine add_get_logic
1136 subroutine add_get_string(cfg, var_name, string_data, comment)
1137 type(
cfg_t),
intent(inout) :: cfg
1138 character(len=*),
intent(in) :: var_name, comment
1139 character(len=*),
intent(inout) :: string_data
1141 call add_string(cfg, var_name, string_data, comment)
1142 call get_string(cfg, var_name, string_data)
1143 end subroutine add_get_string
1147 type(
cfg_t),
intent(in) :: cfg
1148 character(len=*),
intent(in) :: var_name
1149 integer,
intent(out) :: res
1152 call get_var_index(cfg, var_name, ix)
1154 res = cfg%vars(ix)%var_size
1157 call handle_error(
"CFG_get_size: variable ["//var_name//
"] not found")
1163 type(
cfg_t),
intent(in) :: cfg
1164 character(len=*),
intent(in) :: var_name
1165 integer,
intent(out) :: res
1168 call get_var_index(cfg, var_name, ix)
1171 res = cfg%vars(ix)%var_type
1174 call handle_error(
"CFG_get_type: variable ["//var_name//
"] not found")
1181 subroutine ensure_free_storage(cfg)
1182 type(
cfg_t),
intent(inout) :: cfg
1183 type(cfg_var_t),
allocatable :: cfg_copy(:)
1184 integer,
parameter :: min_dyn_size = 100
1185 integer :: cur_size, new_size
1187 if (
allocated(cfg%vars))
then
1188 cur_size =
size(cfg%vars)
1190 if (cur_size < cfg%num_vars + 1)
then
1191 new_size = 2 * cur_size
1192 allocate(cfg_copy(cur_size))
1194 deallocate(cfg%vars)
1195 allocate(cfg%vars(new_size))
1196 cfg%vars(1:cur_size) = cfg_copy
1199 allocate(cfg%vars(min_dyn_size))
1202 end subroutine ensure_free_storage
1205 subroutine get_fields_string(line, delims, n_max, n_found, ixs_start, ixs_end)
1207 character(len=*),
intent(in) :: line
1209 character(len=*),
intent(in) :: delims
1211 integer,
intent(in) :: n_max
1213 integer,
intent(inout) :: n_found
1215 integer,
intent(inout) :: ixs_start(n_max)
1217 integer,
intent(inout) :: ixs_end(n_max)
1219 integer :: ix, ix_prev
1224 do while (n_found < n_max)
1227 ix = verify(line(ix_prev+1:), delims)
1230 n_found = n_found + 1
1231 ixs_start(n_found) = ix_prev + ix
1234 ix = scan(line(ixs_start(n_found)+1:), delims) - 1
1237 ixs_end(n_found) = len(line)
1239 ixs_end(n_found) = ixs_start(n_found) + ix
1242 ix_prev = ixs_end(n_found)
1245 end subroutine get_fields_string
1248 subroutine binary_search_variable(cfg, var_name, ix)
1249 type(
cfg_t),
intent(in) :: cfg
1250 character(len=*),
intent(in) :: var_name
1251 integer,
intent(out) :: ix
1252 integer :: i_min, i_max, i_mid
1255 i_max = cfg%num_vars
1258 do while (i_min < i_max)
1259 i_mid = i_min + (i_max - i_min) / 2
1260 if ( llt(cfg%vars(i_mid)%var_name, var_name) )
then
1268 if (i_max == i_min .and. cfg%vars(i_min)%var_name == var_name)
then
1273 end subroutine binary_search_variable
1277 type(
cfg_t),
intent(inout) :: cfg
1279 call qsort_config(cfg%vars(1:cfg%num_vars))
1284 recursive subroutine qsort_config(list)
1285 type(cfg_var_t),
intent(inout) :: list(:)
1286 integer :: split_pos
1288 if (
size(list) > 1)
then
1289 call parition_var_list(list, split_pos)
1290 call qsort_config( list(:split_pos-1) )
1291 call qsort_config( list(split_pos:) )
1293 end subroutine qsort_config
1296 subroutine parition_var_list(list, marker)
1297 type(cfg_var_t),
intent(inout) :: list(:)
1298 integer,
intent(out) :: marker
1299 integer :: left, right, pivot_ix
1300 type(cfg_var_t) :: temp
1301 character(len=CFG_name_len) :: pivot_value
1304 right =
size(list) + 1
1307 pivot_ix =
size(list) / 2
1308 pivot_value = list(pivot_ix)%var_name
1310 do while (left < right)
1313 do while (lgt(list(right)%var_name, pivot_value))
1318 do while (lgt(pivot_value, list(left)%var_name))
1322 if (left < right)
then
1324 list(left) = list(right)
1329 if (left == right)
then
1334 end subroutine parition_var_list
1342 cfg%sorted = .false.
1344 if(
allocated(cfg%vars))
then
1345 deallocate(cfg%vars)
Interface to get variables from the configuration.
Interface to add variables to the configuration.
Interface to get variables from the configuration.
Module that allows working with a configuration file.
integer, parameter, public cfg_real_type
Real number type.
subroutine, public cfg_write(cfg_in, filename, hide_unused, custom_first)
This routine writes the current configuration to a file with descriptions.
character(len=10), dimension(0:cfg_num_types), parameter, public cfg_type_names
Names of the types.
subroutine, public cfg_get_size(cfg, var_name, res)
Get the size of a variable.
integer, parameter, public cfg_max_array_size
Maximum number of entries in a variable (if it's an array)
integer, parameter, public cfg_string_len
Fixed length of string type.
integer, parameter, public cfg_logic_type
Boolean/logical type.
subroutine, public cfg_update_from_line(cfg, line)
Update the configuration by parsing a line.
integer, parameter, public cfg_name_len
Maximum length of variable names.
integer, parameter, public cfg_integer_type
Integer type.
subroutine, public cfg_write_markdown(cfg_in, filename, hide_unused)
This routine writes the current configuration to a markdown file.
subroutine, public cfg_sort(cfg)
Sort the variables for faster lookup.
subroutine, public cfg_clear(cfg)
Clear all data from a CFG_t object, so that it can be reused. Note that this also happens automatical...
subroutine, public cfg_update_from_arguments(cfg, ignore_unknown)
Read command line arguments. Both files and variables can be specified, for example as: ....
subroutine, public cfg_get_type(cfg, var_name, res)
Get the type of a given variable of a configuration type.
integer, parameter, public cfg_max_line_len
Maximum length of line containing multiple arguments/values.
integer, parameter, public cfg_string_type
String type.
subroutine, public cfg_read_file(cfg, filename)
Update the variables in the configartion with the values found in 'filename'.
subroutine, public cfg_check(cfg)
The configuration that contains all the variables.