Body of read_config: build the strict schema (capturing
defaults from the pristine cfg field initialisers), parse the
file (validate + apply straight into cfg), run the post-parse
time-unit cascade.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | filename |
Path to the namelist input file |
||
| type(config_t), | intent(out), | target | :: | cfg |
Populated configuration |
|
| type(nml_schema_t), | intent(out) | :: | sch |
Built + parsed schema (aliases into |
||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a strict-parse failure when present; absent
behaves as today ( |
subroutine read_config_impl(filename, cfg, sch, ierr) !! Body of [[read_config]]: build the strict schema (capturing !! defaults from the pristine `cfg` field initialisers), parse the !! file (validate + apply straight into `cfg`), run the post-parse !! time-unit cascade. character(len=*), intent(in) :: filename !! Path to the namelist input file type(config_t), target, intent(out) :: cfg !! Populated configuration type(nml_schema_t), intent(out) :: sch !! Built + parsed schema (aliases into `cfg`) integer, intent(out), optional :: ierr !! Non-zero on a strict-parse failure when present; absent !! behaves as today (`error stop`). ! `cfg` arrives at its pristine field-initialiser defaults. Every ! namelist group is now on the strict schema: build it (capturing ! those defaults), then parse — which validates AND applies every ! override straight into `cfg` via the schema's key pointers. No ! native readers, no flat shadow locals, no copy-back remain. ! Build the strict schema so its key constructors capture defaults ! from the pristine `cfg` field initialisers. call build_rdb_schema(cfg, sch) ! A missing namelist file is not an error — the pristine `cfg` ! defaults stand (production main.F90 fails loudly on a missing ! file earlier; tests + the FFI rely on this defaults-on-absent ! behaviour). Guard the strict parse so it never error-stops on ! "cannot open file". block logical :: file_exists inquire (file=trim(filename), exist=file_exists) if (.not. file_exists) then call logger%debug("Namelist file not found, keeping defaults: "//trim(filename)) if (present(ierr)) ierr = OCEAN_STATUS_OK return end if end block ! Strict schema parse: validate + APPLY every group straight into ! `cfg`. When `ierr` is present, route through the schema's own ! non-aborting `status`/`errors` pair (already implemented in ! `rdb_nml_schema`) instead of the bare (strict, error-stopping) ! form — every collected message is still logged, just without the ! `error stop`. Absent `ierr` ⇒ unchanged bare call, for EVERY ! existing caller (driver, benchmarks, unit tests). if (present(ierr)) then block integer :: parse_status, e character(len=:), allocatable :: parse_errors(:) call sch%parse(trim(filename), status=parse_status, errors=parse_errors) if (parse_status /= 0) then if (allocated(parse_errors)) then do e = 1, size(parse_errors) call error_ring_push(trim(parse_errors(e))) call logger%error(trim(parse_errors(e))) end do end if ierr = OCEAN_STATUS_ERR_CONFIG_PARSE return end if end block else call sch%parse(trim(filename)) end if call apply_time_unit_cascade(cfg) call apply_cartesian_degrees(cfg) if (present(ierr)) ierr = OCEAN_STATUS_OK end subroutine read_config_impl