8 integer,
parameter :: dp = kind(0.0d0)
10 integer,
parameter :: CFG_num_types = 4
15 integer,
parameter :: cfg_unknown_type = 0
19 [character(len=10) ::
"storage",
"integer",
"real",
"string ",
"logical"]
28 character(len=*),
parameter :: cfg_separators =
" ,'"""//char(9)
31 character(len=*),
parameter :: cfg_category_separator =
"%"
37 character(len=CFG_name_len) :: var_name
39 character(len=CFG_string_len) :: description
45 logical :: dynamic_size
49 character(len=CFG_string_len) :: stored_data
53 real(dp),
allocatable :: real_data(:)
54 integer,
allocatable :: int_data(:)
55 character(len=CFG_string_len),
allocatable :: char_data(:)
56 logical,
allocatable :: logic_data(:)
61 logical :: sorted = .false.
62 integer :: num_vars = 0
63 type(cfg_var_t),
allocatable :: vars(:)
68 module procedure :: add_real, add_real_array
69 module procedure :: add_int, add_int_array
70 module procedure :: add_string, add_string_array
71 module procedure :: add_logic, add_logic_array
76 module procedure :: get_real, get_real_array
77 module procedure :: get_int, get_int_array
78 module procedure :: get_logic, get_logic_array
79 module procedure :: get_string, get_string_array
84 module procedure :: add_get_real, add_get_real_array
85 module procedure :: add_get_int, add_get_int_array
86 module procedure :: add_get_logic, add_get_logic_array
87 module procedure :: add_get_string, add_get_string_array
88 end interface cfg_add_get
106 public :: cfg_add_get
119 type(cfg_t),
intent(inout) :: cfg
120 character(len=100) :: cfg_name
123 do ix = 1, command_argument_count()
124 call get_command_argument(ix, cfg_name)
131 subroutine handle_error(err_string)
132 character(len=*),
intent(in) :: err_string
134 print *,
"The following error occured in mod_config:"
135 print *, trim(err_string)
140 end subroutine handle_error
143 subroutine get_var_index(cfg, var_name, ix)
144 type(cfg_t),
intent(in) :: cfg
145 character(len=*),
intent(in) :: var_name
146 integer,
intent(out) :: ix
150 call binary_search_variable(cfg, var_name, ix)
153 do i = 1, cfg%num_vars
154 if (cfg%vars(i)%var_name == var_name)
exit
158 if (i == cfg%num_vars + 1) i = -1
162 end subroutine get_var_index
166 type(cfg_t),
intent(inout) :: cfg
167 character(len=*),
intent(in) :: filename
169 integer,
parameter :: my_unit = 123
170 integer :: io_state, equal_sign_ix
171 integer :: ix, line_number
172 character(len=CFG_name_len) :: var_name, category
173 character(len=CFG_name_len) :: line_fmt
174 character(len=CFG_string_len) :: err_string
175 character(len=CFG_string_len) :: line
177 open(my_unit, file=trim(filename), status =
"OLD", &
178 action=
"READ", err=998, iostat=io_state)
187 read(my_unit, fmt=trim(line_fmt), err=998,
end=999) line
188 line_number = line_number + 1
190 call trim_comment(line,
'#')
193 if (line ==
"") cycle
196 equal_sign_ix = scan(line,
'=')
199 if (equal_sign_ix == 0)
then
204 if (line(1:1) /=
'[' .or. ix == 0)
then
205 write(err_string, *)
"Cannot read line ", line_number, &
206 " from ", trim(filename)
207 call handle_error(err_string)
209 category = line(2:ix-1)
214 var_name = line(1 : equal_sign_ix - 1)
217 if (var_name(1:1) /=
" " .and. var_name(1:1) /= char(9))
then
222 var_name = adjustl(var_name)
225 if (category /=
"")
then
226 var_name = trim(category) // cfg_category_separator // var_name
229 line = line(equal_sign_ix + 1:)
233 call get_var_index(cfg, var_name, ix)
237 call prepare_store_var(cfg, trim(var_name), cfg_unknown_type, 1, &
238 "Not yet created", ix, .false.)
239 cfg%vars(ix)%stored_data = line
241 cfg%vars(ix)%stored_data = line
242 call read_variable(cfg%vars(ix))
246 998
write(err_string, *)
"io_state = ", io_state,
" while reading from ", &
247 trim(filename),
" at line ", line_number
248 call handle_error(
"CFG_read_file:" // err_string)
251 999
close(my_unit, iostat=io_state)
255 subroutine read_variable(var)
256 type(cfg_var_t),
intent(inout) :: var
257 integer :: n, n_entries
262 call get_fields_string(var%stored_data, cfg_separators, &
265 if (var%var_size /= n_entries)
then
266 if (.not. var%dynamic_size)
then
267 call handle_error(
"read_variable: variable [" // &
268 & trim(var%var_name) //
"] has the wrong size")
270 var%var_size = n_entries
271 call resize_storage(var)
276 select case (var%var_type)
278 read(var%stored_data(ix_start(n):ix_end(n)), *) var%int_data(n)
280 read(var%stored_data(ix_start(n):ix_end(n)), *) var%real_data(n)
282 var%char_data(n) = trim(var%stored_data(ix_start(n):ix_end(n)))
284 read(var%stored_data(ix_start(n):ix_end(n)), *) var%logic_data(n)
287 end subroutine read_variable
289 subroutine trim_comment(line, comment_chars)
290 character(len=*),
intent(inout) :: line
291 character(len=*),
intent(in) :: comment_chars
292 character :: current_char, need_char
300 current_char = line(n:n)
302 if (need_char ==
"")
then
303 if (current_char ==
"'")
then
305 else if (current_char ==
'"')
then
307 else if (index(current_char, comment_chars) /= 0)
then
311 else if (current_char == need_char)
then
317 end subroutine trim_comment
320 type(cfg_t),
intent(in) :: cfg
322 character(len=CFG_string_len) :: err_string
324 do n = 1, cfg%num_vars
325 if (cfg%vars(n)%var_type == cfg_unknown_type)
then
326 write(err_string, *)
"CFG_check: unknown variable ", &
327 trim(cfg%vars(n)%var_name),
" in a config file"
328 call handle_error(err_string)
336 type(cfg_t),
intent(in) :: cfg_in
337 character(len=*),
intent(in) :: filename
338 logical,
intent(in),
optional :: hide_unused
339 logical :: hide_not_used
341 integer :: i, j, io_state, myunit
342 character(len=CFG_name_len) :: name_format, var_name
343 character(len=CFG_name_len) :: category, prev_category
344 character(len=CFG_string_len) :: err_string
346 hide_not_used = .false.
347 if (
present(hide_unused)) hide_not_used = hide_unused
351 if (.not. cfg%sorted)
call cfg_sort(cfg)
353 write(name_format, fmt=
"(A,I0,A)")
"(A,A",
cfg_name_len,
",A)"
355 if (filename ==
"stdout")
then
359 open(myunit, file=filename, action=
"WRITE", err=999, iostat=io_state)
365 do i = 1, cfg%num_vars
366 if (.not. cfg%vars(i)%used .and. hide_not_used) cycle
367 if (cfg%vars(i)%var_type == cfg_unknown_type) cycle
372 if (category /= prev_category .and. category /=
'')
then
373 write(myunit, err=998, fmt=
"(A)")
'[' // trim(category) //
']'
374 prev_category = category
378 if (category /=
"")
then
379 write(myunit, err=998, fmt=
"(A,A,A)")
" # ", &
380 trim(cfg%vars(i)%description),
":"
381 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
382 " " // trim(var_name) //
" ="
384 write(myunit, err=998, fmt=
"(A,A,A)")
"# ", &
385 trim(cfg%vars(i)%description),
":"
386 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
387 trim(var_name) //
" ="
390 select case(cfg%vars(i)%var_type)
392 do j = 1, cfg%vars(i)%var_size
393 write(myunit, advance=
"NO", err=998, fmt=
"(A,I0)") &
394 " ", cfg%vars(i)%int_data(j)
397 do j = 1, cfg%vars(i)%var_size
398 write(myunit, advance=
"NO", err=998, fmt=
"(A,E11.4)") &
399 " ", cfg%vars(i)%real_data(j)
402 do j = 1, cfg%vars(i)%var_size
403 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
404 " '" // trim(cfg%vars(i)%char_data(j)) //
"'"
407 do j = 1, cfg%vars(i)%var_size
408 write(myunit, advance=
"NO", err=998, fmt=
"(A,L1)") &
409 " ", cfg%vars(i)%logic_data(j)
412 write(myunit, err=998, fmt=
"(A)")
""
413 write(myunit, err=998, fmt=
"(A)")
""
416 if (myunit /= output_unit)
close(myunit, err=999, iostat=io_state)
421 write(err_string, *)
"CFG_write error: io_state = ", io_state, &
422 " while writing ", trim(var_name),
" to ", filename
423 call handle_error(err_string)
426 write(err_string, *)
"CFG_write error: io_state = ", io_state, &
427 " while writing to ", filename
428 call handle_error(err_string)
435 type(cfg_t),
intent(in) :: cfg_in
436 character(len=*),
intent(in) :: filename
437 logical,
intent(in),
optional :: hide_unused
438 logical :: hide_not_used
439 integer :: i, j, io_state, myunit
441 character(len=CFG_name_len) :: name_format, var_name
442 character(len=CFG_name_len) :: category, prev_category
443 character(len=CFG_string_len) :: err_string
445 hide_not_used = .false.
446 if (
present(hide_unused)) hide_not_used = hide_unused
450 if (.not. cfg%sorted)
call cfg_sort(cfg)
452 write(name_format, fmt=
"(A,I0,A)")
"(A,A",
cfg_name_len,
",A)"
454 if (filename ==
"stdout")
then
458 open(myunit, file=filename, action=
"WRITE", err=999, iostat=io_state)
463 write(myunit, err=998, fmt=
"(A)")
"# Configuration file (markdown format)"
464 write(myunit, err=998, fmt=
"(A)")
""
466 do i = 1, cfg%num_vars
468 if (.not. cfg%vars(i)%used .and. hide_not_used) cycle
469 if (cfg%vars(i)%var_type == cfg_unknown_type) cycle
474 if (category /= prev_category)
then
475 if (category ==
"") category =
"No category"
476 write(myunit, err=998, fmt=
"(A)")
'## ' // trim(category)
477 write(myunit, err=998, fmt=
"(A)")
""
478 prev_category = category
481 write(myunit, err=998, fmt=
"(A)")
"* " // trim(cfg%vars(i)%description)
482 write(myunit, err=998, fmt=
"(A)")
""
483 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
484 ' ' // trim(var_name) //
" ="
486 select case(cfg%vars(i)%var_type)
488 do j = 1, cfg%vars(i)%var_size
489 write(myunit, advance=
"NO", err=998, fmt=
"(A,I0)") &
490 " ", cfg%vars(i)%int_data(j)
493 do j = 1, cfg%vars(i)%var_size
494 write(myunit, advance=
"NO", err=998, fmt=
"(A,E11.4)") &
495 " ", cfg%vars(i)%real_data(j)
498 do j = 1, cfg%vars(i)%var_size
499 write(myunit, advance=
"NO", err=998, fmt=
"(A)") &
500 " '" // trim(cfg%vars(i)%char_data(j)) //
"'"
503 do j = 1, cfg%vars(i)%var_size
504 write(myunit, advance=
"NO", err=998, fmt=
"(A,L1)") &
505 " ", cfg%vars(i)%logic_data(j)
508 write(myunit, err=998, fmt=
"(A)")
""
509 write(myunit, err=998, fmt=
"(A)")
""
512 if (myunit /= output_unit)
close(myunit, err=999, iostat=io_state)
517 write(err_string, *)
"CFG_write_markdown error: io_state = ", io_state, &
518 " while writing ", trim(var_name),
" to ", filename
519 call handle_error(err_string)
522 write(err_string, *)
"CFG_write_markdown error: io_state = ", io_state, &
523 " while writing to ", filename
524 call handle_error(err_string)
529 type(cfg_var_t),
intent(in) :: variable
530 character(CFG_name_len),
intent(out) :: category
531 character(CFG_name_len),
intent(out) :: var_name
534 ix = index(variable%var_name, cfg_category_separator)
538 var_name = variable%var_name
540 category = variable%var_name(1:ix-1)
541 var_name = variable%var_name(ix+1:)
548 subroutine resize_storage(variable)
549 type(cfg_var_t),
intent(inout) :: variable
551 select case (variable%var_type)
553 deallocate( variable%int_data )
554 allocate( variable%int_data(variable%var_size) )
556 deallocate( variable%logic_data )
557 allocate( variable%logic_data(variable%var_size) )
559 deallocate( variable%real_data )
560 allocate( variable%real_data(variable%var_size) )
562 deallocate( variable%char_data )
563 allocate( variable%char_data(variable%var_size) )
565 end subroutine resize_storage
569 subroutine prepare_store_var(cfg, var_name, var_type, var_size, &
570 description, ix, dynamic_size)
571 type(cfg_t),
intent(inout) :: cfg
572 character(len=*),
intent(in) :: var_name, description
573 integer,
intent(in) :: var_type, var_size
574 integer,
intent(out) :: ix
575 logical,
intent(in),
optional :: dynamic_size
578 call get_var_index(cfg, var_name, ix)
581 call ensure_free_storage(cfg)
583 ix = cfg%num_vars + 1
584 cfg%num_vars = cfg%num_vars + 1
585 cfg%vars(ix)%used = .false.
586 cfg%vars(ix)%stored_data =
""
589 if (cfg%vars(ix)%var_type /= cfg_unknown_type)
then
590 call handle_error(
"prepare_store_var: variable [" // &
591 & trim(var_name) //
"] already exists")
595 cfg%vars(ix)%var_name = var_name
596 cfg%vars(ix)%description = description
597 cfg%vars(ix)%var_type = var_type
598 cfg%vars(ix)%var_size = var_size
600 if (
present(dynamic_size))
then
601 cfg%vars(ix)%dynamic_size = dynamic_size
603 cfg%vars(ix)%dynamic_size = .false.
606 select case (var_type)
608 allocate( cfg%vars(ix)%int_data(var_size) )
610 allocate( cfg%vars(ix)%real_data(var_size) )
612 allocate( cfg%vars(ix)%char_data(var_size) )
614 allocate( cfg%vars(ix)%logic_data(var_size) )
617 end subroutine prepare_store_var
621 subroutine prepare_get_var(cfg, var_name, var_type, var_size, ix)
622 type(cfg_t),
intent(inout) :: cfg
623 character(len=*),
intent(in) :: var_name
624 integer,
intent(in) :: var_type, var_size
625 integer,
intent(out) :: ix
626 character(len=CFG_string_len) :: err_string
628 call get_var_index(cfg, var_name, ix)
631 call handle_error(
"CFG_get: variable ["//var_name//
"] not found")
632 else if (cfg%vars(ix)%var_type /= var_type)
then
633 write(err_string, fmt=
"(A)")
"CFG_get: variable [" &
634 // var_name //
"] has different type (" // &
637 call handle_error(err_string)
638 else if (cfg%vars(ix)%var_size /= var_size)
then
639 write(err_string, fmt=
"(A,I0,A,I0,A)")
"CFG_get: variable [" &
640 // var_name //
"] has different size (", cfg%vars(ix)%var_size, &
641 ") than requested (", var_size,
")"
642 call handle_error(err_string)
644 cfg%vars(ix)%used = .true.
646 end subroutine prepare_get_var
649 subroutine add_real(cfg, var_name, real_data, comment)
650 type(cfg_t),
intent(inout) :: cfg
651 character(len=*),
intent(in) :: var_name, comment
652 real(dp),
intent(in) :: real_data
655 call prepare_store_var(cfg, var_name,
cfg_real_type, 1, comment, ix)
657 if (cfg%vars(ix)%stored_data /=
"")
then
658 call read_variable(cfg%vars(ix))
660 cfg%vars(ix)%real_data(1) = real_data
662 end subroutine add_real
666 subroutine add_real_array(cfg, var_name, real_data, comment, dynamic_size)
667 type(cfg_t),
intent(inout) :: cfg
668 character(len=*),
intent(in) :: var_name, comment
669 real(dp),
intent(in) :: real_data(:)
670 logical,
intent(in),
optional :: dynamic_size
674 size(real_data), comment, ix, dynamic_size)
676 if (cfg%vars(ix)%stored_data /=
"")
then
677 call read_variable(cfg%vars(ix))
679 cfg%vars(ix)%real_data = real_data
681 end subroutine add_real_array
684 subroutine add_int(cfg, var_name, int_data, comment)
685 type(cfg_t),
intent(inout) :: cfg
686 character(len=*),
intent(in) :: var_name, comment
687 integer,
intent(in) :: int_data
692 if (cfg%vars(ix)%stored_data /=
"")
then
693 call read_variable(cfg%vars(ix))
695 cfg%vars(ix)%int_data(1) = int_data
697 end subroutine add_int
700 subroutine add_int_array(cfg, var_name, int_data, comment, dynamic_size)
701 type(cfg_t),
intent(inout) :: cfg
702 character(len=*),
intent(in) :: var_name, comment
703 integer,
intent(in) :: int_data(:)
704 logical,
intent(in),
optional :: dynamic_size
708 size(int_data), comment, ix, dynamic_size)
710 if (cfg%vars(ix)%stored_data /=
"")
then
711 call read_variable(cfg%vars(ix))
713 cfg%vars(ix)%int_data = int_data
715 end subroutine add_int_array
718 subroutine add_string(cfg, var_name, char_data, comment)
719 type(cfg_t),
intent(inout) :: cfg
720 character(len=*),
intent(in) :: var_name, comment, char_data
724 if (cfg%vars(ix)%stored_data /=
"")
then
725 call read_variable(cfg%vars(ix))
727 cfg%vars(ix)%char_data(1) = char_data
729 end subroutine add_string
732 subroutine add_string_array(cfg, var_name, char_data, &
733 comment, dynamic_size)
734 type(cfg_t),
intent(inout) :: cfg
735 character(len=*),
intent(in) :: var_name, comment, char_data(:)
736 logical,
intent(in),
optional :: dynamic_size
740 size(char_data), comment, ix, dynamic_size)
742 if (cfg%vars(ix)%stored_data /=
"")
then
743 call read_variable(cfg%vars(ix))
745 cfg%vars(ix)%char_data = char_data
747 end subroutine add_string_array
750 subroutine add_logic(cfg, var_name, logic_data, comment)
751 type(cfg_t),
intent(inout) :: cfg
752 character(len=*),
intent(in) :: var_name, comment
753 logical,
intent(in) :: logic_data
756 call prepare_store_var(cfg, var_name,
cfg_logic_type, 1, comment, ix)
758 if (cfg%vars(ix)%stored_data /=
"")
then
759 call read_variable(cfg%vars(ix))
761 cfg%vars(ix)%logic_data(1) = logic_data
763 end subroutine add_logic
766 subroutine add_logic_array(cfg, var_name, logic_data, &
767 comment, dynamic_size)
768 type(cfg_t),
intent(inout) :: cfg
769 character(len=*),
intent(in) :: var_name, comment
770 logical,
intent(in) :: logic_data(:)
771 logical,
intent(in),
optional :: dynamic_size
775 size(logic_data), comment, ix, dynamic_size)
777 if (cfg%vars(ix)%stored_data /=
"")
then
778 call read_variable(cfg%vars(ix))
780 cfg%vars(ix)%logic_data = logic_data
782 end subroutine add_logic_array
785 subroutine get_real_array(cfg, var_name, real_data)
786 type(cfg_t),
intent(inout) :: cfg
787 character(len=*),
intent(in) :: var_name
788 real(dp),
intent(inout) :: real_data(:)
793 real_data = cfg%vars(ix)%real_data
794 end subroutine get_real_array
797 subroutine get_int_array(cfg, var_name, int_data)
798 type(cfg_t),
intent(inout) :: cfg
799 character(len=*),
intent(in) :: var_name
800 integer,
intent(inout) :: int_data(:)
805 int_data = cfg%vars(ix)%int_data
806 end subroutine get_int_array
809 subroutine get_string_array(cfg, var_name, char_data)
810 type(cfg_t),
intent(inout) :: cfg
811 character(len=*),
intent(in) :: var_name
812 character(len=*),
intent(inout) :: char_data(:)
817 char_data = cfg%vars(ix)%char_data
818 end subroutine get_string_array
821 subroutine get_logic_array(cfg, var_name, logic_data)
822 type(cfg_t),
intent(inout) :: cfg
823 character(len=*),
intent(in) :: var_name
824 logical,
intent(inout) :: logic_data(:)
828 size(logic_data), ix)
829 logic_data = cfg%vars(ix)%logic_data
830 end subroutine get_logic_array
833 subroutine get_real(cfg, var_name, res)
834 type(cfg_t),
intent(inout) :: cfg
835 character(len=*),
intent(in) :: var_name
836 real(dp),
intent(out) :: res
840 res = cfg%vars(ix)%real_data(1)
841 end subroutine get_real
844 subroutine get_int(cfg, var_name, res)
845 type(cfg_t),
intent(inout) :: cfg
846 character(len=*),
intent(in) :: var_name
847 integer,
intent(inout) :: res
851 res = cfg%vars(ix)%int_data(1)
852 end subroutine get_int
855 subroutine get_logic(cfg, var_name, res)
856 type(cfg_t),
intent(inout) :: cfg
857 character(len=*),
intent(in) :: var_name
858 logical,
intent(out) :: res
862 res = cfg%vars(ix)%logic_data(1)
863 end subroutine get_logic
866 subroutine get_string(cfg, var_name, res)
867 type(cfg_t),
intent(inout) :: cfg
868 character(len=*),
intent(in) :: var_name
869 character(len=*),
intent(out) :: res
873 res = cfg%vars(ix)%char_data(1)
874 end subroutine get_string
877 subroutine add_get_real_array(cfg, var_name, real_data, &
878 comment, dynamic_size)
879 type(cfg_t),
intent(inout) :: cfg
880 character(len=*),
intent(in) :: var_name, comment
881 real(dp),
intent(inout) :: real_data(:)
882 logical,
intent(in),
optional :: dynamic_size
884 call add_real_array(cfg, var_name, real_data, comment, dynamic_size)
885 call get_real_array(cfg, var_name, real_data)
886 end subroutine add_get_real_array
889 subroutine add_get_int_array(cfg, var_name, int_data, &
890 comment, dynamic_size)
891 type(cfg_t),
intent(inout) :: cfg
892 character(len=*),
intent(in) :: var_name, comment
893 integer,
intent(inout) :: int_data(:)
894 logical,
intent(in),
optional :: dynamic_size
896 call add_int_array(cfg, var_name, int_data, comment, dynamic_size)
897 call get_int_array(cfg, var_name, int_data)
898 end subroutine add_get_int_array
901 subroutine add_get_string_array(cfg, var_name, char_data, &
902 comment, dynamic_size)
903 type(cfg_t),
intent(inout) :: cfg
904 character(len=*),
intent(in) :: var_name, comment
905 character(len=*),
intent(inout) :: char_data(:)
906 logical,
intent(in),
optional :: dynamic_size
908 call add_string_array(cfg, var_name, char_data, comment, dynamic_size)
909 call get_string_array(cfg, var_name, char_data)
910 end subroutine add_get_string_array
913 subroutine add_get_logic_array(cfg, var_name, logic_data, &
914 comment, dynamic_size)
915 type(cfg_t),
intent(inout) :: cfg
916 character(len=*),
intent(in) :: var_name, comment
917 logical,
intent(inout) :: logic_data(:)
918 logical,
intent(in),
optional :: dynamic_size
920 call add_logic_array(cfg, var_name, logic_data, comment, dynamic_size)
921 call get_logic_array(cfg, var_name, logic_data)
922 end subroutine add_get_logic_array
925 subroutine add_get_real(cfg, var_name, real_data, comment)
926 type(cfg_t),
intent(inout) :: cfg
927 character(len=*),
intent(in) :: var_name, comment
928 real(dp),
intent(inout) :: real_data
930 call add_real(cfg, var_name, real_data, comment)
931 call get_real(cfg, var_name, real_data)
932 end subroutine add_get_real
935 subroutine add_get_int(cfg, var_name, int_data, comment)
936 type(cfg_t),
intent(inout) :: cfg
937 character(len=*),
intent(in) :: var_name, comment
938 integer,
intent(inout) :: int_data
940 call add_int(cfg, var_name, int_data, comment)
941 call get_int(cfg, var_name, int_data)
942 end subroutine add_get_int
945 subroutine add_get_logic(cfg, var_name, logical_data, comment)
946 type(cfg_t),
intent(inout) :: cfg
947 character(len=*),
intent(in) :: var_name, comment
948 logical,
intent(inout) :: logical_data
950 call add_logic(cfg, var_name, logical_data, comment)
951 call get_logic(cfg, var_name, logical_data)
952 end subroutine add_get_logic
955 subroutine add_get_string(cfg, var_name, string_data, comment)
956 type(cfg_t),
intent(inout) :: cfg
957 character(len=*),
intent(in) :: var_name, comment
958 character(len=*),
intent(inout) :: string_data
960 call add_string(cfg, var_name, string_data, comment)
961 call get_string(cfg, var_name, string_data)
962 end subroutine add_get_string
966 type(cfg_t),
intent(in) :: cfg
967 character(len=*),
intent(in) :: var_name
968 integer,
intent(out) :: res
971 call get_var_index(cfg, var_name, ix)
973 res = cfg%vars(ix)%var_size
976 call handle_error(
"CFG_get_size: variable ["//var_name//
"] not found")
982 type(cfg_t),
intent(in) :: cfg
983 character(len=*),
intent(in) :: var_name
984 integer,
intent(out) :: res
987 call get_var_index(cfg, var_name, ix)
990 res = cfg%vars(ix)%var_type
993 call handle_error(
"CFG_get_type: variable ["//var_name//
"] not found")
1000 subroutine ensure_free_storage(cfg)
1001 type(cfg_t),
intent(inout) :: cfg
1002 type(cfg_var_t),
allocatable :: cfg_copy(:)
1003 integer,
parameter :: min_dyn_size = 100
1004 integer :: cur_size, new_size
1006 if (
allocated(cfg%vars))
then
1007 cur_size =
size(cfg%vars)
1009 if (cur_size < cfg%num_vars + 1)
then
1010 new_size = 2 * cur_size
1011 allocate(cfg_copy(cur_size))
1013 deallocate(cfg%vars)
1014 allocate(cfg%vars(new_size))
1015 cfg%vars(1:cur_size) = cfg_copy
1018 allocate(cfg%vars(min_dyn_size))
1021 end subroutine ensure_free_storage
1024 subroutine get_fields_string(line, delims, n_max, n_found, ixs_start, ixs_end)
1026 character(len=*),
intent(in) :: line
1028 character(len=*),
intent(in) :: delims
1030 integer,
intent(in) :: n_max
1032 integer,
intent(inout) :: n_found
1034 integer,
intent(inout) :: ixs_start(n_max)
1036 integer,
intent(inout) :: ixs_end(n_max)
1038 integer :: ix, ix_prev
1043 do while (n_found < n_max)
1046 ix = verify(line(ix_prev+1:), delims)
1049 n_found = n_found + 1
1050 ixs_start(n_found) = ix_prev + ix
1053 ix = scan(line(ixs_start(n_found)+1:), delims) - 1
1056 ixs_end(n_found) = len(line)
1058 ixs_end(n_found) = ixs_start(n_found) + ix
1061 ix_prev = ixs_end(n_found)
1064 end subroutine get_fields_string
1067 subroutine binary_search_variable(cfg, var_name, ix)
1068 type(cfg_t),
intent(in) :: cfg
1069 character(len=*),
intent(in) :: var_name
1070 integer,
intent(out) :: ix
1071 integer :: i_min, i_max, i_mid
1074 i_max = cfg%num_vars
1077 do while (i_min < i_max)
1078 i_mid = i_min + (i_max - i_min) / 2
1079 if ( llt(cfg%vars(i_mid)%var_name, var_name) )
then
1087 if (i_max == i_min .and. cfg%vars(i_min)%var_name == var_name)
then
1092 end subroutine binary_search_variable
1096 type(cfg_t),
intent(inout) :: cfg
1098 call qsort_config(cfg%vars(1:cfg%num_vars))
1103 recursive subroutine qsort_config(list)
1104 type(cfg_var_t),
intent(inout) :: list(:)
1105 integer :: split_pos
1107 if (
size(list) > 1)
then
1108 call parition_var_list(list, split_pos)
1109 call qsort_config( list(:split_pos-1) )
1110 call qsort_config( list(split_pos:) )
1112 end subroutine qsort_config
1115 subroutine parition_var_list(list, marker)
1116 type(cfg_var_t),
intent(inout) :: list(:)
1117 integer,
intent(out) :: marker
1118 integer :: left, right, pivot_ix
1119 type(cfg_var_t) :: temp
1120 character(len=CFG_name_len) :: pivot_value
1123 right =
size(list) + 1
1126 pivot_ix =
size(list) / 2
1127 pivot_value = list(pivot_ix)%var_name
1129 do while (left < right)
1132 do while (lgt(list(right)%var_name, pivot_value))
1137 do while (lgt(pivot_value, list(left)%var_name))
1141 if (left < right)
then
1143 list(left) = list(right)
1148 if (left == right)
then
1153 end subroutine parition_var_list
Module that allows working with a configuration file.
subroutine, public cfg_get_size(cfg, var_name, res)
Get the size of a variable.
integer, parameter, public cfg_real_type
Real number type.
subroutine split_category(variable, category, var_name)
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'.
integer, parameter, public cfg_name_len
Maximum length of variable names.
integer, parameter, public cfg_string_len
Fixed length of string type.
subroutine, public cfg_check(cfg)
subroutine, public cfg_get_type(cfg, var_name, res)
Get the type of a given variable of a configuration type.
subroutine, public cfg_update_from_arguments(cfg)
integer, parameter, public cfg_logic_type
Boolean/logical type.
subroutine, public cfg_write(cfg_in, filename, hide_unused)
This routine writes the current configuration to a file with descriptions.
integer, parameter, public cfg_max_array_size
Maximum number of entries in a variable (if it's an array)
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.
integer, parameter, public cfg_integer_type
Integer type.
character(len=10), dimension(0:cfg_num_types), parameter, public cfg_type_names
Names of the types.