Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • bdc/cats
1 result
Select Git revision
  • development
  • main
  • refactor-libraries
  • 1.0.0
  • 1.0.1
  • 1.0.2
  • 1.0.3
  • 1.1.0
8 results
Show changes
Showing
with 368 additions and 71 deletions
......@@ -19,10 +19,11 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "cats_global.h"
#include <inttypes.h>
#include "cats_strings.h"
#include "logging/logging.h"
#include "bdc_strings.h"
#include "bdc_logging/logging.h"
void print_string(int indent, const char *name, const char *value)
{
......@@ -32,7 +33,7 @@ void print_string(int indent, const char *name, const char *value)
}
void print_subcategory(int indent, const char *category_name, int64_t category_number, char *name)
void print_subcategory(int indent, const char *category_name, int64_t category_number, const char *name)
{
indent *= 2;
if (indent > 0) log_message(LOG_RAW, "%*s", indent, "");
......
......@@ -25,8 +25,10 @@
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "string_converters.h"
#include "logging/logging.h"
#include "bdc_logging/logging.h"
const char *true_values[] = {"1", "y", "t"};
const char *false_values[] = {"0", "n", "f"};
......@@ -34,7 +36,7 @@ const int true_counts = (int) (sizeof(true_values) / sizeof(char *));
const int false_counts = (int) (sizeof(false_values) / sizeof(char *));
bool string_to_double(char *string, double *value)
bool string_to_double(const char *string, double *value)
{
if (string == NULL || strlen(string) == 0) return false;
......@@ -82,7 +84,7 @@ bool string_to_float(char *string, float *value)
}
bool string_to_long_double(char *string, long double *value)
bool string_to_long_double(const char *string, long double *value)
{
if (string == NULL || strlen(string) == 0) return false;
......@@ -127,7 +129,7 @@ bool string_to_bool(char *string, bool *value)
}
bool string_to_integer(char *string, int32_t *value)
bool string_to_integer(const char *string, int32_t *value)
{
if (string == NULL || strlen(string) == 0) return false;
......@@ -148,3 +150,7 @@ bool string_to_integer(char *string, int32_t *value)
return false;
}
......@@ -19,12 +19,11 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include "cats_global.h"
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <logging/logging.h>
#include "bdc_logging/logging.h"
#include "bdc_memory/bdc_memory.h"
......@@ -78,6 +77,13 @@ char *left_trim(char *line)
}
char *trim_both(char *line)
{
return left_trim(right_trim(line));
}
size_t substring_count(const char *haystack, const char *needle)
{
size_t count = 0;
......@@ -134,8 +140,8 @@ char *replace_substring(const char *original, const char *search, const char *re
exit(EXIT_FAILURE);
}
size_t occurrences = substring_count(original, search);
size_t result_len = strlen(original) + strlen(replacement) * occurrences - strlen(search) * occurrences + 1;
size_t n_occurrences = substring_count(original, search);
size_t result_len = strlen(original) + strlen(replacement) * n_occurrences - strlen(search) * n_occurrences + 1;
char *result = calloc_or_die(1, result_len);
......@@ -144,20 +150,24 @@ char *replace_substring(const char *original, const char *search, const char *re
size_t bytes_copied = 0;
for (size_t i = 0; i < occurrences; i++) {
for (size_t i = 0; i < n_occurrences; i++) {
char *next_occurrence = strstr(orig_loc, search);
if (next_occurrence == NULL) { break; }
if (next_occurrence == NULL || strlen(next_occurrence) == 0) { break; }
// how many bytes are before our first hit?
size_t bytes_to_copy = strlen(orig_loc) - strlen(next_occurrence);
if (bytes_to_copy) {
bytes_copied += bytes_to_copy;
strncpy(result_loc, orig_loc, bytes_to_copy);
result_loc += bytes_to_copy;
orig_loc += bytes_to_copy + search_len;
orig_loc += bytes_to_copy;
}
strncpy(result_loc, replacement, replacement_len);
result_loc += replacement_len;
orig_loc += search_len;
}
if (bytes_copied < original_len) {
......
// SPDX-License-Identifier: GPL-3.0-or-later
//
// string_substitution.c
//
// Copyright (C) 2011-2024, University of Vienna and Vienna Institute for Nature Conservation & Analyses, Andreas Gattringer.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <string.h>
#include "bdc_memory/bdc_memory.h"
#include "bdc_logging/logging.h"
#include "bdc_hashtable/bdc_hashtable.h"
#include "bdc_strings.h"
struct string_substitution {
struct bdc_hash_table *substitution_strings;
struct bdc_hash_table *integer_patterns;
struct string_array *keys;
};
struct string_substitution *new_substituter()
{
struct string_substitution *new = calloc_or_die(1, sizeof(struct string_substitution));
new->substitution_strings = new_hash_table();
new->integer_patterns = new_hash_table();
new->keys = new_string_array();
return new;
}
void set_integer_pattern(struct string_substitution *substituter, const char *key, const char *pattern)
{
if (substituter == NULL) {
log_message(LOG_ERROR, "%s: substituter == NULL", __func__);
exit(EXIT_FAILURE);
}
bdc_ht_add_string(substituter->integer_patterns, key, pattern);
}
void add_substitution_integer(struct string_substitution *substituter, const char *key, int32_t initial_value)
{
if (substituter == NULL) {
log_message(LOG_ERROR, "%s: substituter == NULL", __func__);
exit(EXIT_FAILURE);
}
char *default_pattern = "%d";
char *pattern = NULL;
char *loaded_pattern = NULL;
bdc_ht_get_string_from_key(substituter->integer_patterns, key, &loaded_pattern);
if (!loaded_pattern) {
pattern = default_pattern;
} else {
pattern = loaded_pattern;
}
char *value = NULL;
int rc = asprintf(&value, pattern, initial_value);
asprintf_check(rc);
add_substitution(substituter, key, value);
free(value);
free(loaded_pattern);
}
void add_substitution(struct string_substitution *substituter, const char *key, const char *initial_value)
{
if (!bdc_key_in_hash_table(substituter->substitution_strings, key)) {
string_array_add(substituter->keys, key);
}
bdc_ht_add_string(substituter->substitution_strings, key, initial_value);
}
char *substitute_string(const char *string, const struct string_substitution *substituter)
{
if (substituter == NULL) {
log_message(LOG_ERROR, "%s: substituter == NULL", __func__);
exit(EXIT_FAILURE);
}
if (substituter->keys == NULL) {
log_message(LOG_ERROR, "%s: substituter invalid, keys = NULL", __func__);
exit(EXIT_FAILURE);
}
log_message(LOG_INFO, "substituting string '%s' with %d potential substitutions", string, get_string_count(substituter->keys));
const int count = get_string_count(substituter->keys);
char *copy = strdup(string);
char *result = strdup(string);
for (int i = 0; i < count; i++) {
const char *key = get_string(substituter->keys, i);
char *value = NULL;
bool found = bdc_ht_get_string_from_key(substituter->substitution_strings, key, &value);
if (! found) {
continue;
}
free(result);
result = replace_substring(copy, key, value);
free(copy);
copy = strdup(result);
}
free(copy);
return result;
}
void destroy_substituter(struct string_substitution **substituter)
{
if (substituter == NULL || *substituter == NULL) return;
struct string_substitution *s = *substituter;
free_string_array(&s->keys);
destroy_hash_table(&s->substitution_strings);
destroy_hash_table(&s->integer_patterns);
free(s);
*substituter = NULL;
}
struct string_substitution *copy_substituter(const struct string_substitution *from)
{
if (from == NULL) return NULL;
struct string_substitution *to = new_substituter();
const struct string_array *keys = from->keys;
const int32_t count = get_string_count(keys);
for (int32_t i = 0; i< count; i++) {
const char *key = get_string(keys, i);
char *value = NULL;
bdc_ht_get_string_from_key(from->substitution_strings, key, &value);
if (value) {
add_substitution(to, key, value);
}
bdc_ht_get_string_from_key(from->integer_patterns, key, &value);
if (value) {
set_integer_pattern(to, key, value);
}
}
return to;
}
\ No newline at end of file
add_library(bdc_time STATIC "" ../bdc_cross_platform/bdc_cross_platform.h)
target_sources(bdc_time
PRIVATE
bdc_time.c
bdc_timer.c
PUBLIC
bdc_time.h
)
set_property(TARGET bdc_time PROPERTY POSITION_INDEPENDENT_CODE ON)
# bdc_time
This is a library to handle time.
## Dependencies
* bdc_cross_platform (header only)
\ No newline at end of file
// SPDX-License-Identifier: GPL-3.0-or-later
//
// cats_time.c
// bdc_time.c
//
// Copyright (C) 2011-2024, University of Vienna and Vienna Institute for Nature Conservation & Analyses, Andreas Gattringer.
//
......@@ -21,16 +21,19 @@
#include <time.h>
#include <stdio.h>
#include "cats_time.h"
#include <sys/time.h>
#ifdef CATS_ON_WINDOWS
#include "bdc_time.h"
#ifdef BDC_ON_WINDOWS
#include <profileapi.h>
#endif
void get_time(struct timeval *tv)
{
#if defined(CATS_ON_WINDOWS) && ! defined(__MINGW32__)
#if defined(BDC_ON_WINDOWS) && ! defined(__MINGW32__)
struct timespec ts;
timespec_get(&ts, TIME_UTC);
tv->tv_sec = (long) ts.tv_sec;
......@@ -42,9 +45,9 @@ void get_time(struct timeval *tv)
}
void time_now(struct cats_time *time_info)
void time_now(struct bdc_time *time_info)
{
#ifdef CATS_ON_WINDOWS
#ifdef BDC_ON_WINDOWS
LARGE_INTEGER zero = {0};
QueryPerformanceCounter(&time_info->clock_monotonic);
if (time_info->clock_monotonic.QuadPart == zero.QuadPart) {
......@@ -59,9 +62,9 @@ void time_now(struct cats_time *time_info)
}
double get_elapsed_seconds_monotonic(struct cats_time *start_time, struct cats_time *end_time)
double get_elapsed_seconds_monotonic(struct bdc_time *start_time, struct bdc_time *end_time)
{
#ifdef CATS_ON_WINDOWS
#ifdef BDC_ON_WINDOWS
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return (double) (end_time->clock_monotonic.QuadPart - start_time->clock_monotonic.QuadPart) / frequency.QuadPart;
......@@ -73,9 +76,9 @@ double get_elapsed_seconds_monotonic(struct cats_time *start_time, struct cats_t
}
double seconds_monotonic_since(struct cats_time *start_time)
double seconds_monotonic_since(struct bdc_time *start_time)
{
struct cats_time now;
struct bdc_time now;
time_now(&now);
return get_elapsed_seconds_monotonic(start_time, &now);
}
\ No newline at end of file
// SPDX-License-Identifier: GPL-3.0-or-later
//
// cats_time.h
// bdc_time.h
//
// Copyright (C) 2011-2024, University of Vienna and Vienna Institute for Nature Conservation & Analyses, Andreas Gattringer.
//
......@@ -19,22 +19,22 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifndef CATS_CATS_TIME_H
#define CATS_CATS_TIME_H
#ifndef BDC_TIME_H
#define BDC_TIME_H
#include "../cats_defs.h"
#include <stdint.h>
#ifdef CATS_ON_WINDOWS
#ifdef BDC_ON_WINDOWS
#include <winsock.h>
#else
#include <sys/time.h>
#endif
struct cats_time {
#include <time.h>
struct bdc_time {
// monotonic time stamps, used for total elapsed time
#ifdef CATS_ON_WINDOWS
#ifdef BDC_ON_WINDOWS
LARGE_INTEGER clock_monotonic;
#else
struct timespec clock_monotonic;
......@@ -43,12 +43,27 @@ struct cats_time {
struct timeval current_time;
};
double seconds_monotonic_since(struct cats_time *start_time);
double seconds_monotonic_since(struct bdc_time *start_time);
void time_now(struct cats_time *time_info);
void time_now(struct bdc_time *time_info);
double get_elapsed_seconds_monotonic(struct cats_time *start_time, struct cats_time *end_time);
double get_elapsed_seconds_monotonic(struct bdc_time *start_time, struct bdc_time *end_time);
void get_time(struct timeval *tv);
#endif //CATS_CATS_TIME_H
struct bdc_timer {
clock_t start_clock;
struct timeval start_timeval;
double time_normal;
double time_real;
};
struct bdc_timer start_new_timer(void);
void start_timer(struct bdc_timer *t);
void stop_timer(struct bdc_timer *t);
#endif //BDC_TIME_H
// SPDX-License-Identifier: GPL-3.0-or-later
//
// bdc_timer.c
//
// Copyright (C) 2011-2024, University of Vienna and Vienna Institute for Nature Conservation & Analyses, Andreas Gattringer.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <assert.h>
#include <stdlib.h>
#include "bdc_memory/bdc_memory.h"
#include "bdc_time.h"
struct timeval *time_difference(struct timeval *start, struct timeval *end)
{
struct timeval *diff = malloc_or_die(sizeof(struct timeval));
if (start->tv_sec == end->tv_sec) {
diff->tv_sec = 0;
diff->tv_usec = end->tv_usec - start->tv_usec;
} else {
diff->tv_usec = 1000000 - start->tv_usec;
diff->tv_sec = end->tv_sec - (start->tv_sec + 1);
diff->tv_usec += end->tv_usec;
if (diff->tv_usec >= 1000000) {
diff->tv_usec -= 1000000;
diff->tv_sec += 1;
}
}
return diff;
}
struct bdc_timer start_new_timer(void)
{
struct bdc_timer t = {0};
t.start_clock = clock();
get_time(&t.start_timeval);
return t;
}
void start_timer(struct bdc_timer *t)
{
assert(t != NULL);
t->start_clock = clock();
get_time(&t->start_timeval);
}
void stop_timer(struct bdc_timer *t)
{
assert(t != NULL);
clock_t now = clock();
struct timeval time_now;
double elapsed_time;
get_time(&time_now);
elapsed_time = ((double) (now - t->start_clock) / CLOCKS_PER_SEC);
t->time_normal = elapsed_time;
double difference_real;
struct timeval *difference;
difference = time_difference(&t->start_timeval, &time_now);
difference_real = (double) difference->tv_sec + (double) difference->tv_usec / (1000.0 * 1000.0);
t->time_real = difference_real;
free(difference);
}
add_subdirectory(logging)
add_subdirectory(cats)
add_subdirectory(cats_time)
add_subdirectory(cats_strings)
add_subdirectory(cats_ini)
add_subdirectory(cats_csv)
add_subdirectory(modules/cats_test_module)
......
......@@ -44,8 +44,6 @@ target_include_directories(libcats PUBLIC ".")
target_sources(libcats PRIVATE
../cats_defs.h
../cats_time/cats_time.c
../cats_time/cats_time.h
defaults.h
......@@ -218,8 +216,7 @@ target_sources(libcats PRIVATE
performance/performance_stats.c
performance/performance_stats.h
performance/timer.c
performance/timer.h
performance/timer.c performance/timer.h
plants/clonal_growth.c
plants/clonal_growth.h
......@@ -321,15 +318,15 @@ set(CATS_SOURCES_MPI
)
add_executable(cats cats.c)
target_link_libraries(libcats cats_logging bdc cats_strings cats_ini cats_csv)
target_link_libraries(cats libcats cats_logging bdc cats_strings cats_ini cats_csv)
target_link_libraries(libcats bdc_logging bdc bdc_strings cats_ini cats_csv)
target_link_libraries(cats libcats bdc_logging bdc bdc_strings cats_ini cats_csv)
if (MSVC)
# target_include_directories(cats PRIVATE ${GDAL_INCLUDE_DIRS})
# target_link_libraries(cats cats_logging cats_memory cats_strings cats_ini cats_csv ${GDAL_LIBRARIES})
# target_link_libraries(cats bdc_logging bdc_memory bdc_strings cats_ini cats_csv ${GDAL_LIBRARIES})
else ()
target_link_libraries(cats cats_logging bdc cats_strings cats_ini cats_csv)
target_link_libraries(cats bdc_logging bdc bdc_strings cats_ini cats_csv)
endif ()
......@@ -337,7 +334,7 @@ if (MPI_FOUND)
add_executable(cats-mpi cats.c ${CATS_SOURCES_MPI})
target_link_libraries(cats-mpi ${MPI_C_LIBRARIES} cats_logging bdc_memory cats_strings cats_ini cats_csv libcats)
target_link_libraries(cats-mpi ${MPI_C_LIBRARIES} bdc_logging bdc_memory bdc_strings cats_ini cats_csv libcats)
target_compile_options(cats-mpi PRIVATE -DUSEMPI)
......
......@@ -23,13 +23,14 @@
#include <assert.h>
#include "threading/threading-helpers.h"
#include "configuration/configuration.h"
#include "performance/timer.h"
#include "bdc_time/bdc_time.h"
#include "stats/grid_stats.h"
#include "stats/global_stats.h"
#include "actions/cats_actions.h"
#include "inline_overlays.h"
#include "inline_population.h"
#include "inline.h"
#include "performance/timer.h"
#ifdef USEMPI
#include "mpi/mpi_stats.h"
......@@ -104,7 +105,7 @@ enum action_status action_write_plant_stats(struct cats_grid *grid, struct cats_
if (conf->command_line_options.lambda_test) return ACTION_NOT_RUN;
// calculate grid statistics
struct cats_timer timer = start_new_timer();
struct bdc_timer timer = start_new_timer();
if (grid->id == 0) {
threaded_action(&area_gather_stats, grid, conf, TS_BLOCK);
}
......
......@@ -24,6 +24,7 @@
#include "configuration/configuration.h"
#include "logging.h"
#include "cats_actions.h"
#include "bdc_time/bdc_time.h"
#include "performance/timer.h"
const char *status_strings[] = {"SKIPPED: ",
......@@ -57,7 +58,7 @@ void run_simulation_phase(struct cats_grid **grid, struct cats_configuration *co
log_message(LOG_MARK, "\nSTARTING %s %d", conf->time.phase_name, time);
log_message(LOG_INFO, "CYCLE::START::%s::%d", conf->time.phase_name, time);
struct cats_timer year_timer = start_new_timer();
struct bdc_timer year_timer = start_new_timer();
enum cats_simulation_stages stage = get_run_actions(conf);
......@@ -67,7 +68,7 @@ void run_simulation_phase(struct cats_grid **grid, struct cats_configuration *co
}
conf->cycle.current_action = action;
struct cats_timer timer = start_new_timer();
struct bdc_timer timer = start_new_timer();
log_message(LOG_IMPORTANT, "START: %s : %"PRId64"",
conf->cycle.actions[action].message, conf->cycle.action_counter);
bool did_run = false;
......
......@@ -26,7 +26,7 @@
#include "configuration/configuration.h"
#include "logging.h"
#include "plants/seeds.h"
#include "performance/timer.h"
#include "bdc_time/bdc_time.h"
#include "grids/gdal_save.h"
#include "dispersal/dispersal.h"
#include "threading/threading.h"
......@@ -41,6 +41,7 @@
#include "inline_overlays.h"
#include "actions/cats_actions.h"
#include "temporal/years.h"
#include "performance/timer.h"
void area_post_process_seeds(struct cats_grid *grid, struct cats_thread_info *ts);
......@@ -113,7 +114,7 @@ enum action_status process_disperse_seeds(struct cats_grid *grid, struct cats_co
grid->stats.stats[CS_SEEDS_AFTER_POISSON] = 0;
grid->stats.stats[CS_SEEDS_BEFORE_POISSON] = 0;
struct cats_timer timer = start_new_timer();
struct bdc_timer timer = start_new_timer();
threaded_action(&dispersal_wrapper, grid, conf, TS_DISPERSAL);
stop_log_and_restart_timer(&timer, "actual dispersal", LOG_INFO, &conf->time, conf);
......
......@@ -28,7 +28,7 @@
#include "actions/setup_actions.h"
#include "actions/cats_actions.h"
#include "actions/process_inter_period_survival.h"
#include "cats_strings/cats_strings.h"
#include "bdc_strings/bdc_strings.h"
#include "dispersal/dispersal.h"
#include "bdc_memory/bdc_memory.h"
......
......@@ -31,7 +31,7 @@
#include "cats_global.h"
#include <cats_ini/cats_ini.h>
#include <logging/logging.h>
#include <bdc_logging/logging.h>
#include "cats/command_line/command_line_info.h"
#include "cats/command_line/command_line_options.h"
......
......@@ -30,12 +30,11 @@
//#error "CATS assumes IEC 559 support"
#endif
// INCLUDE STATEMENTS
#include <stdio.h>
#include <stdlib.h>
#include "data/cats_datatypes.h"
#include "cats_time/cats_time.h"
#include "bdc_time/bdc_time.h"
#include "cats_defs.h"
#include "cats_windows.h"
......@@ -68,7 +67,7 @@ struct cats_global {
bool enable_json_output;
char *program_name;
int mpi_world_rank;
struct cats_time time_info;
struct bdc_time time_info;
float poisson_dampening_factor;
float poisson_dampening_minimum;
float poisson_maximum;
......
......@@ -24,7 +24,7 @@
#include "vital_rates/vital_rates_helper.h"
#include "command_line_options.h"
#include "command_line_info.h"
#include "logging/logging.h"
#include "bdc_logging/logging.h"
#include "cats_ini/cats_ini.h"
#include "defaults.h"
#include "cats_global.h"
......
......@@ -25,7 +25,7 @@
#include <getopt.h>
#include <stdlib.h>
#include <stdbool.h>
#include "logging/logging.h"
#include "bdc_logging/logging.h"
#include "cats_global.h"
......@@ -114,7 +114,7 @@ struct program_options {
bool lambda_test;
enum cats_debug_flags debug_flags;
enum cats_log_level default_log_level;
enum bdc_log_level default_log_level;
bool show_unused_config_values;
bool show_unspecified_config_values;
bool have_poisson_dampening_factor;
......
......@@ -25,7 +25,7 @@
#include "misc/misc.h"
#include "logging.h"
#include "cats_ini/cats_ini.h"
#include "cats_strings/cats_strings.h"
#include "bdc_strings/bdc_strings.h"
#include "load_configuration_temporal.h"
#include "paths/paths.h"
#include "grids/gdal_helper.h"
......@@ -34,7 +34,7 @@
void load_simulation_geometry_from_initial_population(struct cats_configuration *conf, struct cats_ini *ini)
{
struct string_array *species_sections = get_sections_with_prefix(ini, "species");
if (species_sections->count == 0) {
if (get_string_count(species_sections) == 0) {
log_message(LOG_ERROR, "%s: could not load any species information", __func__);
exit_cats(EXIT_FAILURE);
}
......@@ -53,9 +53,9 @@ void load_simulation_geometry_from_initial_population(struct cats_configuration
}
char *file_name = NULL;
bool load_ini_pop = ! conf->command_line_options.no_input_rasters_required;
for (int32_t i = 0; i < species_sections->count; i++) {
char *species_section = species_sections->string[i];
size_t count = get_string_count(species_sections);
for (int32_t i = 0; i < count; i++) {
const char *species_section = get_string(species_sections, i);
load_conf_value(load_ini_pop, ini, species_section, "initial population filename", &file_name); // VR::ignored::
break;
}
......