From 9f6178dafd730a78bc96da90ad6be9d480230b3c Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 29 Oct 2024 14:04:59 +0100 Subject: [PATCH] src: format using clang-format --- src/at.c | 54 +- src/at.h | 25 +- src/config.c | 10 +- src/gnss.c | 150 +- src/gnss.h | 6 +- src/gpio.c | 98 +- src/gpio.h | 4 +- src/manager.c | 66 +- src/manager.h | 73 +- src/mm-iface.c | 70 +- src/ofono-iface.c | 43 +- src/suspend.c | 123 +- src/suspend.h | 6 +- src/toml.c | 3685 +++++++++++++++++++++++---------------------- src/toml.h | 159 +- src/udev.c | 19 +- src/udev.h | 4 +- 17 files changed, 2364 insertions(+), 2231 deletions(-) diff --git a/src/at.c b/src/at.c index 327b394..a206414 100644 --- a/src/at.c +++ b/src/at.c @@ -6,9 +6,9 @@ #include "at.h" #include "config.h" -#include "suspend.h" -#include "gpio.h" #include "gnss.h" +#include "gpio.h" +#include "suspend.h" #include #include @@ -28,7 +28,7 @@ static GArray *reset_commands = NULL; static int configure_serial(const char *tty) { struct termios ttycfg; - int fd; + int fd; fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd > 0) { @@ -50,7 +50,7 @@ static int configure_serial(const char *tty) static void at_free_command(gpointer cmd, gpointer data) { - struct AtCommand *at_cmd = cmd; + struct AtCommand *at_cmd = cmd; struct EG25Manager *manager = data; if (!at_cmd) @@ -68,9 +68,9 @@ static void at_free_command(gpointer cmd, gpointer data) gboolean at_send_command(struct EG25Manager *manager) { - char command[256]; + char command[256]; struct AtCommand *at_cmd = manager->at_cmds ? g_list_nth_data(manager->at_cmds, 0) : NULL; - int ret, len = 0, pos = 0; + int ret, len = 0, pos = 0; if (at_cmd) { /* Wake up the modem from soft sleep before sending an AT command */ @@ -82,20 +82,26 @@ gboolean at_send_command(struct EG25Manager *manager) else if (at_cmd->subcmd == NULL && at_cmd->value == NULL) len = snprintf(command, sizeof(command), "AT+%s?\r\n", at_cmd->cmd); else if (at_cmd->subcmd == NULL && at_cmd->value) - len = snprintf(command, sizeof(command),"AT+%s=%s\r\n", at_cmd->cmd, at_cmd->value); + len = snprintf(command, sizeof(command), "AT+%s=%s\r\n", at_cmd->cmd, at_cmd->value); else if (at_cmd->subcmd && at_cmd->value == NULL) len = snprintf(command, sizeof(command), "AT+%s=\"%s\"\r\n", at_cmd->cmd, at_cmd->subcmd); else if (at_cmd->subcmd && at_cmd->value) - len = snprintf(command, sizeof(command), "AT+%s=\"%s\",%s\r\n", at_cmd->cmd, at_cmd->subcmd, at_cmd->value); + len = snprintf(command, + sizeof(command), + "AT+%s=\"%s\",%s\r\n", + at_cmd->cmd, + at_cmd->subcmd, + at_cmd->value); if (len < 0) { g_warning("snprintf(3) failed"); at_next_command(manager); return FALSE; - } - else if (len >= sizeof(command)) { + } else if (len >= sizeof(command)) { g_warning("AT command does not fit into buffer " - "(%d bytes required, %zu available)", len, sizeof(command)); + "(%d bytes required, %zu available)", + len, + sizeof(command)); at_next_command(manager); return FALSE; } @@ -117,8 +123,7 @@ gboolean at_send_command(struct EG25Manager *manager) at_next_command(manager); return FALSE; } - } - else { + } else { len -= ret; pos += ret; } @@ -176,8 +181,7 @@ static void retry_at_command(struct EG25Manager *manager) } } -void at_process_result(struct EG25Manager *manager, - const char *response) +void at_process_result(struct EG25Manager *manager, const char *response) { struct AtCommand *at_cmd = manager->at_cmds ? g_list_nth_data(manager->at_cmds, 0) : NULL; @@ -201,9 +205,7 @@ int at_append_command(struct EG25Manager *manager, const char *subcmd, const char *value, const char *expected, - void (*callback) - (struct EG25Manager *manager, - const char *response)) + void (*callback)(struct EG25Manager *manager, const char *response)) { struct AtCommand *at_cmd = calloc(1, sizeof(struct AtCommand)); @@ -227,14 +229,12 @@ int at_append_command(struct EG25Manager *manager, #define READ_BUFFER_SIZE 256 -static gboolean modem_response(gint fd, - GIOCondition event, - gpointer data) +static gboolean modem_response(gint fd, GIOCondition event, gpointer data) { struct EG25Manager *manager = data; - char response[READ_BUFFER_SIZE*4+1]; - char tmp[READ_BUFFER_SIZE]; - ssize_t ret, pos = 0; + char response[READ_BUFFER_SIZE * 4 + 1]; + char tmp[READ_BUFFER_SIZE]; + ssize_t ret, pos = 0; /* * Several reads can be necessary to get the full response, so we loop @@ -319,8 +319,8 @@ static void parse_commands_list(toml_array_t *array, GArray **cmds) g_array_set_size(*cmds, (guint)len); for (int i = 0; i < len; i++) { struct AtCommand *cmd = &g_array_index(*cmds, struct AtCommand, i); - toml_table_t *table = toml_table_at(array, i); - toml_datum_t value; + toml_table_t *table = toml_table_at(array, i); + toml_datum_t value; if (!table) continue; @@ -346,7 +346,7 @@ static void parse_commands_list(toml_array_t *array, GArray **cmds) int at_init(struct EG25Manager *manager, toml_table_t *config[]) { toml_array_t *commands = NULL; - gchar *uart_port = NULL; + gchar *uart_port = NULL; toml_table_t *at_config[EG25_CONFIG_COUNT]; for (int i = 0; i < EG25_CONFIG_COUNT; i++) diff --git a/src/at.h b/src/at.h index 8e6c5d1..8325ae4 100644 --- a/src/at.h +++ b/src/at.h @@ -13,25 +13,22 @@ typedef struct AtCommand { char *subcmd; char *value; char *expected; - void (*callback)(struct EG25Manager *manager, const char *response); - int retries; + void (*callback)(struct EG25Manager *manager, const char *response); + int retries; } AtCommand; -int at_init(struct EG25Manager *manager, toml_table_t *config[]); +int at_init(struct EG25Manager *manager, toml_table_t *config[]); void at_destroy(struct EG25Manager *manager); -void at_process_result(struct EG25Manager *manager, - const char *response); -void at_next_command(struct EG25Manager *manager); +void at_process_result(struct EG25Manager *manager, const char *response); +void at_next_command(struct EG25Manager *manager); gboolean at_send_command(struct EG25Manager *manager); -int at_append_command(struct EG25Manager *manager, - const char *cmd, - const char *subcmd, - const char *value, - const char *expected, - void (*callback) - (struct EG25Manager *manager, - const char *response)); +int at_append_command(struct EG25Manager *manager, + const char *cmd, + const char *subcmd, + const char *value, + const char *expected, + void (*callback)(struct EG25Manager *manager, const char *response)); void at_sequence_configure(struct EG25Manager *manager); void at_sequence_suspend(struct EG25Manager *manager); diff --git a/src/config.c b/src/config.c index 2c5aafa..105d6e3 100644 --- a/src/config.c +++ b/src/config.c @@ -9,7 +9,7 @@ gboolean config_get_bool(toml_table_t **config, const gchar *key, gboolean *result) { - toml_datum_t value = { .ok = 0 }; + toml_datum_t value = {.ok = 0}; if (config[EG25_CONFIG_USER]) value = toml_bool_in(config[EG25_CONFIG_USER], key); @@ -23,7 +23,7 @@ gboolean config_get_bool(toml_table_t **config, const gchar *key, gboolean *resu gboolean config_get_int(toml_table_t **config, const gchar *key, gint *result) { - toml_datum_t value = { .ok = 0 }; + toml_datum_t value = {.ok = 0}; if (config[EG25_CONFIG_USER]) value = toml_int_in(config[EG25_CONFIG_USER], key); @@ -37,7 +37,7 @@ gboolean config_get_int(toml_table_t **config, const gchar *key, gint *result) gboolean config_get_uint(toml_table_t **config, const gchar *key, guint *result) { - gint value; + gint value; gboolean found; found = config_get_int(config, key, &value); @@ -49,14 +49,14 @@ gboolean config_get_uint(toml_table_t **config, const gchar *key, guint *result) } if (found && result) - *result = (guint) value; + *result = (guint)value; return found; } gboolean config_get_string(toml_table_t **config, const gchar *key, gchar **result) { - toml_datum_t value = { .ok = 0 }; + toml_datum_t value = {.ok = 0}; if (config[EG25_CONFIG_USER]) value = toml_string_in(config[EG25_CONFIG_USER], key); diff --git a/src/gnss.c b/src/gnss.c index a43827a..06630c2 100644 --- a/src/gnss.c +++ b/src/gnss.c @@ -4,18 +4,18 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -#include "config.h" #include "gnss.h" -#include "manager.h" #include "at.h" +#include "config.h" +#include "manager.h" +#include #include #include -#include -#define BUFFER_SIZE 256 -#define UPLOAD_DELAY_US 25000 -#define UPLOAD_TIMEOUT_S 10 +#define BUFFER_SIZE 256 +#define UPLOAD_DELAY_US 25000 +#define UPLOAD_TIMEOUT_S 10 #define RESCHEDULE_IN_SECS 30 static void gnss_step(struct EG25Manager *manager); @@ -29,26 +29,25 @@ gboolean gnss_upload_assistance_data(struct EG25Manager *manager) if (manager->gnss_assistance_step < EG25_GNSS_STEP_LAST) { g_warning("GNSS assistance data upload already in process (%d/%d)", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); return FALSE; } /* data upload isn't necessary to bring the modem onine, so we should wait * until we've finished the rest of our configuration */ - if (!manager->modem_iface || - manager->modem_state < EG25_STATE_CONFIGURED || - manager->modem_state > EG25_STATE_CONNECTED) { - g_message ("Rescheduling upload since modem isn't online yet, in %ds", - RESCHEDULE_IN_SECS); + if (!manager->modem_iface || manager->modem_state < EG25_STATE_CONFIGURED || + manager->modem_state > EG25_STATE_CONNECTED) { + g_message("Rescheduling upload since modem isn't online yet, in %ds", RESCHEDULE_IN_SECS); manager->gnss_assistance_step = EG25_GNSS_STEP_LAST; return TRUE; } #ifdef HAVE_MMGLIB /* ModemManager's Location is only available after unlocking */ - if(manager->modem_iface == MODEM_IFACE_MODEMMANAGER && !manager->mm_location) { - g_message ("Rescheduling upload since Location interface is not available, in %ds", - RESCHEDULE_IN_SECS); + if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER && !manager->mm_location) { + g_message("Rescheduling upload since Location interface is not available, in %ds", + RESCHEDULE_IN_SECS); manager->gnss_assistance_step = EG25_GNSS_STEP_LAST; return TRUE; } @@ -62,7 +61,7 @@ gboolean gnss_upload_assistance_data(struct EG25Manager *manager) void gnss_init(struct EG25Manager *manager, toml_table_t *config[]) { toml_table_t *gnss_config[EG25_CONFIG_COUNT]; - g_autoptr (GError) error = NULL; + g_autoptr(GError) error = NULL; for (int i = 0; i < EG25_CONFIG_COUNT; i++) gnss_config[i] = config[i] ? toml_table_in(config[i], "gnss") : NULL; @@ -92,12 +91,11 @@ void gnss_init(struct EG25Manager *manager, toml_table_t *config[]) /* Create temporary file to store assistance data */ manager->gnss_assistance_fd = g_file_open_tmp(NULL, NULL, &error); if (error != NULL) - g_error ("Unable to create temporary file: %s", error->message); + g_error("Unable to create temporary file: %s", error->message); /* Initialize state and schedule upload */ manager->gnss_assistance_step = EG25_GNSS_STEP_LAST; - g_timeout_add_seconds(RESCHEDULE_IN_SECS, - G_SOURCE_FUNC(gnss_upload_assistance_data), manager); + g_timeout_add_seconds(RESCHEDULE_IN_SECS, G_SOURCE_FUNC(gnss_upload_assistance_data), manager); } void gnss_destroy(struct EG25Manager *manager) @@ -113,8 +111,8 @@ void gnss_destroy(struct EG25Manager *manager) static void disable_mm_gnss(struct EG25Manager *manager) { MMModemLocationSource sources; - gboolean signals_location; - g_autoptr (GError) error = NULL; + gboolean signals_location; + g_autoptr(GError) error = NULL; sources = mm_modem_location_get_enabled(manager->mm_location); signals_location = mm_modem_location_signals_location(manager->mm_location); @@ -140,17 +138,14 @@ static void disable_mm_gnss(struct EG25Manager *manager) sources &= ~MM_MODEM_LOCATION_SOURCE_GPS_RAW; sources &= ~MM_MODEM_LOCATION_SOURCE_GPS_NMEA; sources &= ~MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED; - mm_modem_location_setup_sync(manager->mm_location, sources, - signals_location, NULL, &error); + mm_modem_location_setup_sync(manager->mm_location, sources, signals_location, NULL, &error); if (error != NULL) { - g_warning("Unable to disable GNSS engine through ModemManager: %s", - error->message); + g_warning("Unable to disable GNSS engine through ModemManager: %s", error->message); } } #endif -static void disable_at_gnss_cb(struct EG25Manager *manager, - const char *response) +static void disable_at_gnss_cb(struct EG25Manager *manager, const char *response) { /* Clear QGPSEND AT command and process next */ at_next_command(manager); @@ -199,27 +194,25 @@ static void state_at_gnss(struct EG25Manager *manager) static void fetch_assistance_data(struct EG25Manager *manager) { - CURLcode response; - curl_off_t downloaded; - CURL *curl = NULL; + CURLcode response; + curl_off_t downloaded; + CURL *curl = NULL; g_autofree gchar *url = NULL; - FILE *tmp_file = NULL; - gchar errbuf[CURL_ERROR_SIZE]; + FILE *tmp_file = NULL; + gchar errbuf[CURL_ERROR_SIZE]; errbuf[0] = 0; /* Fetch assistance data with curl */ tmp_file = fdopen(manager->gnss_assistance_fd, "wb+"); if (tmp_file == NULL) { - g_critical("Unable to open file to save assistance data: %s", - g_strerror(errno)); + g_critical("Unable to open file to save assistance data: %s", g_strerror(errno)); goto bail; } lseek(manager->gnss_assistance_fd, 0, SEEK_SET); if (ftruncate(manager->gnss_assistance_fd, 0) < 0) g_warning("Unable to truncate file, assistance data might be invalid!"); - url = g_strconcat(manager->gnss_assistance_url, "/", - manager->gnss_assistance_file, NULL); + url = g_strconcat(manager->gnss_assistance_url, "/", manager->gnss_assistance_file, NULL); curl = curl_easy_init(); if (!curl) { @@ -237,7 +230,8 @@ static void fetch_assistance_data(struct EG25Manager *manager) response = curl_easy_perform(curl); if (response != CURLE_OK) { g_warning("Unable to fetch GNSS assistance data from %s: %s", - url, strlen(errbuf) ? errbuf : curl_easy_strerror(response)); + url, + strlen(errbuf) ? errbuf : curl_easy_strerror(response)); goto bail; } @@ -268,8 +262,7 @@ bail: /******************************************************************************/ -static void init_assistance_data_upload_ready(struct EG25Manager *manager, - const char *response) +static void init_assistance_data_upload_ready(struct EG25Manager *manager, const char *response) { /* Search for 'CONNECT' in response to start upload */ if (strstr(response, "CONNECT")) { @@ -285,8 +278,7 @@ static void init_assistance_data_upload_ready(struct EG25Manager *manager, } } -static void init_assistance_data_upload_start(struct EG25Manager *manager, - const char *response) +static void init_assistance_data_upload_start(struct EG25Manager *manager, const char *response) { gchar value[BUFFER_SIZE]; off_t size; @@ -305,11 +297,14 @@ static void init_assistance_data_upload_start(struct EG25Manager *manager, lseek(manager->gnss_assistance_fd, 0, SEEK_SET); /* Start upload */ - g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\",%ld,%d", - manager->gnss_assistance_file, size, UPLOAD_TIMEOUT_S); + g_snprintf(value, + BUFFER_SIZE, + "\"RAM:%s\",%ld,%d", + manager->gnss_assistance_file, + size, + UPLOAD_TIMEOUT_S); g_message("Initiate GNSS assistance data upload: %s", value); - at_append_command(manager, "QFUPL", NULL, value, NULL, - init_assistance_data_upload_ready); + at_append_command(manager, "QFUPL", NULL, value, NULL, init_assistance_data_upload_ready); at_send_command(manager); } @@ -319,16 +314,15 @@ static void init_assistance_data_upload(struct EG25Manager *manager) * Delete all previous GNSS assistance data files in RAM * and start uploading the latest one to RAM. */ - at_append_command(manager, "QFDEL", NULL, "\"RAM:*\"\r\n", - NULL, init_assistance_data_upload_start); + at_append_command(manager, "QFDEL", NULL, "\"RAM:*\"\r\n", NULL, init_assistance_data_upload_start); at_send_command(manager); } static void upload_assistance_data(struct EG25Manager *manager) { - gint error; - off_t written_total = 0; - gint ret; + gint error; + off_t written_total = 0; + gint ret; struct stat sb; if (fstat(manager->gnss_assistance_fd, &sb) != 0) { @@ -357,8 +351,7 @@ static void upload_assistance_data(struct EG25Manager *manager) } } -static void finish_assistance_data_upload_cb(struct EG25Manager *manager, - const char *response) +static void finish_assistance_data_upload_cb(struct EG25Manager *manager, const char *response) { /* Process response */ at_process_result(manager, response); @@ -371,23 +364,20 @@ static void finish_assistance_data_upload_cb(struct EG25Manager *manager, static void finish_assistance_data_upload(struct EG25Manager *manager) { - gchar value[BUFFER_SIZE]; + gchar value[BUFFER_SIZE]; GDateTime *datetime; - gchar *timestring; + gchar *timestring; /* Configure GNSS assistance clock to current system time (UTC) */ datetime = g_date_time_new_now_utc(); timestring = g_date_time_format(datetime, "0,\"%Y/%m/%d,%H:%M:%S\""); g_message("Setting GNSS assistance UTC clock to: %s", timestring); - at_append_command(manager, "QGPSXTRATIME", NULL, timestring, NULL, - at_process_result); + at_append_command(manager, "QGPSXTRATIME", NULL, timestring, NULL, at_process_result); /* Configure GNSS engine to use uploaded GNSS assistance data */ - g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\"", - manager->gnss_assistance_file); + g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\"", manager->gnss_assistance_file); g_message("Setting GNSS assistance file to: %s", value); - at_append_command(manager, "QGPSXTRADATA", NULL, value, NULL, - finish_assistance_data_upload_cb); + at_append_command(manager, "QGPSXTRADATA", NULL, value, NULL, finish_assistance_data_upload_cb); at_send_command(manager); } @@ -396,7 +386,7 @@ static void finish_assistance_data_upload(struct EG25Manager *manager) #ifdef HAVE_MMGLIB static void enable_mm_gnss(struct EG25Manager *manager) { - g_autoptr (GError) error = NULL; + g_autoptr(GError) error = NULL; MMModemLocationSource sources = mm_modem_location_get_enabled(manager->mm_location); gboolean signal_location = mm_modem_location_signals_location(manager->mm_location); @@ -407,11 +397,9 @@ static void enable_mm_gnss(struct EG25Manager *manager) if (manager->gnss_sources & EG25_GNSS_SOURCE_RAW) sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW; - mm_modem_location_setup_sync(manager->mm_location, sources, - signal_location, NULL, &error); + mm_modem_location_setup_sync(manager->mm_location, sources, signal_location, NULL, &error); if (error != NULL) - g_warning("Unable to enable GNSS engine through ModemManager: %s", - error->message); + g_warning("Unable to enable GNSS engine through ModemManager: %s", error->message); } #endif @@ -424,8 +412,7 @@ static void enable_at_gnss_cb(struct EG25Manager *manager, const char *response) static void enable_at_gnss(struct EG25Manager *manager) { if (manager->gnss_sources & EG25_GNSS_SOURCE_QGPS) { - at_append_command(manager, "QGPS", NULL, "1", NULL, - enable_at_gnss_cb); + at_append_command(manager, "QGPS", NULL, "1", NULL, enable_at_gnss_cb); at_send_command(manager); return; } @@ -437,7 +424,7 @@ static void enable_at_gnss(struct EG25Manager *manager) void gnss_step(struct EG25Manager *manager) { - switch(manager->gnss_assistance_step) { + switch (manager->gnss_assistance_step) { case EG25_GNSS_STEP_FIRST: manager->gnss_assistance_step++; g_message("GNSS assistance upload started..."); @@ -446,7 +433,8 @@ void gnss_step(struct EG25Manager *manager) case EG25_GNSS_STEP_FETCH_ASSISTANCE_DATA: g_message("GNSS assistance upload step (%d/%d): " "fetching assistance data", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); fetch_assistance_data(manager); break; @@ -455,7 +443,8 @@ void gnss_step(struct EG25Manager *manager) if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) { g_message("GNSS assistance upload step (%d/%d): " "disabling GNSS engine through ModemManager", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); disable_mm_gnss(manager); } manager->gnss_assistance_step++; @@ -465,26 +454,30 @@ void gnss_step(struct EG25Manager *manager) case EG25_GNSS_STEP_AT_GNSS_DISABLE: g_message("GNSS assistance upload step (%d/%d): " "disabling GNSS engine through AT+QGPS", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); state_at_gnss(manager); break; case EG25_GNSS_STEP_INIT_UPLOAD: g_message("GNSS assistance upload step (%d/%d): initiating upload", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); init_assistance_data_upload(manager); break; case EG25_GNSS_STEP_UPLOAD: g_message("GNSS assistance upload step (%d/%d): " "uploading assistance data", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); upload_assistance_data(manager); break; case EG25_GNSS_STEP_FINISH_UPLOAD: g_message("GNSS assistance upload step (%d/%d): finishing upload", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); finish_assistance_data_upload(manager); break; @@ -493,7 +486,8 @@ void gnss_step(struct EG25Manager *manager) if (manager->modem_iface == MODEM_IFACE_MODEMMANAGER) { g_message("GNSS assistance upload step (%d/%d): " "re-enabling GNSS through ModemManager", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); enable_mm_gnss(manager); } manager->gnss_assistance_step++; @@ -503,13 +497,15 @@ void gnss_step(struct EG25Manager *manager) case EG25_GNSS_STEP_AT_QGPS_ENABLE: g_message("GNSS assistance upload step (%d/%d): " "re-enabling GNSS through AT+QGPS", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); enable_at_gnss(manager); break; case EG25_GNSS_STEP_LAST: g_message("GNSS assistance upload step (%d/%d): finished", - manager->gnss_assistance_step, EG25_GNSS_STEP_LAST); + manager->gnss_assistance_step, + EG25_GNSS_STEP_LAST); break; } } diff --git a/src/gnss.h b/src/gnss.h index 78bdc18..080d5ae 100644 --- a/src/gnss.h +++ b/src/gnss.h @@ -6,12 +6,12 @@ #pragma once +#include #include #include -#include #include "manager.h" -void gnss_init(struct EG25Manager *manager, toml_table_t *config[]); -void gnss_destroy(struct EG25Manager *manager); +void gnss_init(struct EG25Manager *manager, toml_table_t *config[]); +void gnss_destroy(struct EG25Manager *manager); gboolean gnss_upload_assistance_data(struct EG25Manager *manager); diff --git a/src/gpio.c b/src/gpio.c index 6f24386..618c757 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -4,16 +4,16 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -#include "config.h" #include "gpio.h" +#include "config.h" -#include #include #include +#include /* Those defines are used for legacy config files only */ -#define GPIO_CHIP1_LABEL "1c20800.pinctrl" -#define GPIO_CHIP2_LABEL "1f02c00.pinctrl" +#define GPIO_CHIP1_LABEL "1c20800.pinctrl" +#define GPIO_CHIP2_LABEL "1f02c00.pinctrl" #define MAX_GPIOCHIP_LINES 352 enum { @@ -42,31 +42,32 @@ static char *gpio_in_names[] = { "status", }; -enum gpiod_line_value gpio_line_get_value(struct EG25Manager *manager, int line) { +enum gpiod_line_value gpio_line_get_value(struct EG25Manager *manager, int line) +{ enum gpiod_line_value value; - unsigned int offset; + unsigned int offset; gpiod_line_request_get_requested_offsets(manager->gpio_in[line], &offset, 1); value = gpiod_line_request_get_value(manager->gpio_in[line], offset); if (value == GPIOD_LINE_VALUE_ERROR) { - g_warning("gpio: couldn't get value on line %d", line); + g_warning("gpio: couldn't get value on line %d", line); } return value; } -int gpio_line_set_value(struct EG25Manager *manager, int line, enum gpiod_line_value value) { +int gpio_line_set_value(struct EG25Manager *manager, int line, enum gpiod_line_value value) +{ unsigned int offset; - int ret; + int ret; gpiod_line_request_get_requested_offsets(manager->gpio_out[line], &offset, 1); ret = gpiod_line_request_set_value(manager->gpio_out[line], offset, value); if (ret) { g_warning("gpio: couldn't set value %d on line %d", value, line); return -1; - } - else { + } else { manager->gpio_out_value[line] = value; return 0; } @@ -159,12 +160,16 @@ int gpio_sequence_sleep(struct EG25Manager *manager) return 0; } -struct gpiod_line_request *gpio_request_line(struct EG25Manager *manager, int chip, unsigned int line, enum gpiod_line_direction direction) { - struct gpiod_line_request *request = NULL; - struct gpiod_line_settings *settings; - struct gpiod_line_config *line_cfg; +struct gpiod_line_request *gpio_request_line(struct EG25Manager *manager, + int chip, + unsigned int line, + enum gpiod_line_direction direction) +{ + struct gpiod_line_request *request = NULL; + struct gpiod_line_settings *settings; + struct gpiod_line_config *line_cfg; struct gpiod_request_config *req_cfg; - int ret; + int ret; settings = gpiod_line_settings_new(); if (!settings) @@ -202,14 +207,13 @@ free_settings: static int gpio_chip_dir_filter(const struct dirent *entry) { struct stat sb; - int ret = 0; - char *path; + int ret = 0; + char *path; if (asprintf(&path, "/dev/%s", entry->d_name) < 0) return 0; - if ((lstat(path, &sb) == 0) && (!S_ISLNK(sb.st_mode)) && - gpiod_is_gpiochip_device(path)) + if ((lstat(path, &sb) == 0) && (!S_ISLNK(sb.st_mode)) && gpiod_is_gpiochip_device(path)) ret = 1; free(path); @@ -219,9 +223,9 @@ static int gpio_chip_dir_filter(const struct dirent *entry) int gpio_all_chip_paths(char ***paths_ptr) { - int i, j, num_chips, ret = 0; + int i, j, num_chips, ret = 0; struct dirent **entries; - char **paths; + char **paths; num_chips = scandir("/dev/", &entries, gpio_chip_dir_filter, alphasort); if (num_chips < 0) @@ -253,10 +257,10 @@ int gpio_all_chip_paths(char ***paths_ptr) struct gpiod_chip *gpio_chip_open_by_label(const char *label) { - int num_chips, i; - char **paths; - const char *clabel; - struct gpiod_chip *chip; + int num_chips, i; + char **paths; + const char *clabel; + struct gpiod_chip *chip; struct gpiod_chip_info *cinfo; num_chips = gpio_all_chip_paths(&paths); @@ -273,6 +277,7 @@ struct gpiod_chip *gpio_chip_open_by_label(const char *label) clabel = gpiod_chip_info_get_label(cinfo); if (strcmp(label, clabel) == 0) { + free(paths); return chip; } @@ -280,13 +285,17 @@ clean_chip_open: gpiod_chip_close(chip); } + if (paths) + free(paths); + return NULL; } -unsigned int gpio_chip_num_lines(struct EG25Manager *manager, unsigned int chip_num) { - struct gpiod_chip *chip = manager->gpiochip[chip_num]; +unsigned int gpio_chip_num_lines(struct EG25Manager *manager, unsigned int chip_num) +{ + struct gpiod_chip *chip = manager->gpiochip[chip_num]; struct gpiod_chip_info *info; - unsigned int num_lines; + unsigned int num_lines; info = gpiod_chip_get_info(chip); if (!info) @@ -301,7 +310,7 @@ unsigned int gpio_chip_num_lines(struct EG25Manager *manager, unsigned int chip_ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) { - int i; + int i; toml_table_t *gpio_config[EG25_CONFIG_COUNT]; for (i = 0; i < EG25_CONFIG_COUNT; i++) @@ -321,9 +330,8 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) * format, but error out if user config overrides gpios using the * old format */ - if (!gpio_config[EG25_CONFIG_USER] || toml_array_in(gpio_config[EG25_CONFIG_USER], "chips")) - { - int numchips; + if (!gpio_config[EG25_CONFIG_USER] || toml_array_in(gpio_config[EG25_CONFIG_USER], "chips")) { + int numchips; toml_array_t *chipslist = NULL; config_get_array(gpio_config, "chips", &chipslist); @@ -342,7 +350,7 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) for (i = 0; i < GPIO_OUT_COUNT; i++) { toml_table_t *table; - toml_datum_t chip, line; + toml_datum_t chip, line; if (!config_get_table(gpio_config, gpio_out_names[i], &table)) g_error("Unable to get config for output GPIO '%s'", gpio_out_names[i]); @@ -354,14 +362,17 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) if (!line.ok || line.u.i < 0 || line.u.i > gpio_chip_num_lines(manager, chip.u.i)) g_error("Wrong line ID for output GPIO '%s'", gpio_out_names[i]); - manager->gpio_out[i] = gpio_request_line(manager, chip.u.i, line.u.i, GPIOD_LINE_DIRECTION_OUTPUT); + manager->gpio_out[i] = gpio_request_line(manager, + chip.u.i, + line.u.i, + GPIOD_LINE_DIRECTION_OUTPUT); if (!manager->gpio_out[i]) g_error("Unable to get output GPIO %d", i); } for (i = 0; i < GPIO_IN_COUNT; i++) { toml_table_t *table; - toml_datum_t chip, line; + toml_datum_t chip, line; if (!config_get_table(gpio_config, gpio_in_names[i], &table)) { // BH edition don't have the STATUS line connected, ignore it @@ -378,7 +389,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) if (!line.ok || line.u.i < 0 || line.u.i > gpio_chip_num_lines(manager, chip.u.i)) g_error("Wrong line ID for input GPIO '%s'", gpio_in_names[i]); - manager->gpio_in[i] = gpio_request_line(manager, chip.u.i, line.u.i, GPIOD_LINE_DIRECTION_INPUT); + manager->gpio_in[i] = gpio_request_line(manager, + chip.u.i, + line.u.i, + GPIOD_LINE_DIRECTION_INPUT); if (!manager->gpio_in[i]) g_error("Unable to get input GPIO %d", i); } @@ -406,7 +420,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) chipidx = 1; } - manager->gpio_out[i] = gpio_request_line(manager, chipidx, offset, GPIOD_LINE_DIRECTION_OUTPUT); + manager->gpio_out[i] = gpio_request_line(manager, + chipidx, + offset, + GPIOD_LINE_DIRECTION_OUTPUT); if (!manager->gpio_out[i]) g_error("Unable to get output GPIO %d", i); } @@ -423,7 +440,10 @@ int gpio_init(struct EG25Manager *manager, toml_table_t *config[]) chipidx = 1; } - manager->gpio_in[i] = gpio_request_line(manager, chipidx, offset, GPIOD_LINE_DIRECTION_INPUT); + manager->gpio_in[i] = gpio_request_line(manager, + chipidx, + offset, + GPIOD_LINE_DIRECTION_INPUT); if (!manager->gpio_in[i]) g_error("Unable to get input GPIO %d", i); } diff --git a/src/gpio.h b/src/gpio.h index 256ef60..f655662 100644 --- a/src/gpio.h +++ b/src/gpio.h @@ -8,7 +8,7 @@ #include "manager.h" -int gpio_init(struct EG25Manager *state, toml_table_t *config[]); +int gpio_init(struct EG25Manager *state, toml_table_t *config[]); void gpio_destroy(struct EG25Manager *state); int gpio_sequence_poweron(struct EG25Manager *state); @@ -18,5 +18,5 @@ int gpio_sequence_resume(struct EG25Manager *state); int gpio_sequence_wake(struct EG25Manager *state); int gpio_sequence_sleep(struct EG25Manager *state); -void gpio_force_off(struct EG25Manager *manager); +void gpio_force_off(struct EG25Manager *manager); gboolean gpio_check_poweroff(struct EG25Manager *manager); diff --git a/src/manager.c b/src/manager.c index 1d578fd..41ae046 100644 --- a/src/manager.c +++ b/src/manager.c @@ -4,19 +4,19 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +#include "manager.h" #include "at.h" #include "config.h" #include "gpio.h" -#include "manager.h" #ifdef HAVE_MMGLIB #include "mm-iface.h" #endif +#include "gnss.h" #include "ofono-iface.h" #include "suspend.h" #include "udev.h" -#include "gnss.h" #include #include @@ -41,7 +41,7 @@ #define EG25_DEFAULT_VENDOR_ID 0x2c7c #define EG25_DEFAULT_PRODUCT_ID 0x0125 -#define POWERON_DELAY_US 100000UL +#define POWERON_DELAY_US 100000UL static gboolean quit_app(struct EG25Manager *manager) { @@ -80,10 +80,10 @@ static gboolean quit_app(struct EG25Manager *manager) static gboolean modem_start(struct EG25Manager *manager) { - ssize_t i, count; - gboolean should_boot = TRUE; - libusb_context *ctx = NULL; - libusb_device **devices = NULL; + ssize_t i, count; + gboolean should_boot = TRUE; + libusb_context *ctx = NULL; + libusb_device **devices = NULL; struct libusb_device_descriptor desc; if (manager->use_libusb) { @@ -154,7 +154,7 @@ static gboolean modem_gpio_reset_done(struct EG25Manager *manager) return G_SOURCE_REMOVE; } -static gboolean modem_at_reset_done(struct EG25Manager* manager) +static gboolean modem_at_reset_done(struct EG25Manager *manager) { /* * If the modem was successfully rebooted, then we should have received @@ -168,12 +168,14 @@ static gboolean modem_at_reset_done(struct EG25Manager* manager) g_message("AT reset failed, falling back to GPIO reset"); gpio_sequence_shutdown(manager); - manager->complete_reset_timer = g_timeout_add_seconds(30, G_SOURCE_FUNC(modem_gpio_reset_done), manager); + manager->complete_reset_timer = g_timeout_add_seconds(30, + G_SOURCE_FUNC(modem_gpio_reset_done), + manager); return G_SOURCE_REMOVE; } -static gboolean modem_rebind_done(struct EG25Manager* manager) +static gboolean modem_rebind_done(struct EG25Manager *manager) { manager->modem_state = EG25_STATE_RESUMING; manager->complete_reset_timer = 0; @@ -271,7 +273,9 @@ error: at_sequence_reset(manager); // Setup timer for making sure we don't queue other reset commands - manager->complete_reset_timer = g_timeout_add_seconds(45, G_SOURCE_FUNC(modem_at_reset_done), manager); + manager->complete_reset_timer = g_timeout_add_seconds(45, + G_SOURCE_FUNC(modem_at_reset_done), + manager); return G_SOURCE_REMOVE; } @@ -301,15 +305,15 @@ void modem_resume_post(struct EG25Manager *manager) static toml_table_t *parse_config_file(char *config_file, gboolean force_default) { toml_table_t *toml_config; - gchar *compatible; - gchar error[256]; - gsize len; - FILE *f = NULL; + gchar *compatible; + gchar error[256]; + gsize len; + FILE *f = NULL; if (config_file) { f = fopen(config_file, "r"); } else if (g_file_get_contents("/proc/device-tree/compatible", &compatible, &len, NULL)) { - g_autoptr (GPtrArray) compat = g_ptr_array_new(); + g_autoptr(GPtrArray) compat = g_ptr_array_new(); gsize pos = 0; /* @@ -324,9 +328,11 @@ static toml_table_t *parse_config_file(char *config_file, gboolean force_default for (pos = 0; pos < compat->len; pos++) { g_autofree gchar *filename = NULL; if (force_default) - filename = g_strdup_printf(EG25_DATADIR "/%s.toml", (gchar *)g_ptr_array_index(compat, pos)); + filename = g_strdup_printf(EG25_DATADIR "/%s.toml", + (gchar *)g_ptr_array_index(compat, pos)); else - filename = g_strdup_printf(EG25_CONFDIR "/%s.toml", (gchar *)g_ptr_array_index(compat, pos)); + filename = g_strdup_printf(EG25_CONFDIR "/%s.toml", + (gchar *)g_ptr_array_index(compat, pos)); if (access(filename, F_OK) == 0) { g_message("Opening config file: %s", filename); @@ -355,15 +361,15 @@ int main(int argc, char *argv[]) g_autoptr(GOptionContext) opt_context = NULL; g_autoptr(GError) err = NULL; struct EG25Manager manager; - gchar *config_file = NULL; - gboolean show_version = FALSE; - gboolean monitor_udev = TRUE; - toml_table_t *toml_config[EG25_CONFIG_COUNT]; - toml_table_t *manager_config[EG25_CONFIG_COUNT]; + gchar *config_file = NULL; + gboolean show_version = FALSE; + gboolean monitor_udev = TRUE; + toml_table_t *toml_config[EG25_CONFIG_COUNT]; + toml_table_t *manager_config[EG25_CONFIG_COUNT]; const GOptionEntry options[] = { - { "config", 'c', 0, G_OPTION_ARG_STRING, &config_file, "Config file to use.", NULL }, - { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, "Display version information and exit.", NULL }, - { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } + {"config", 'c', 0, G_OPTION_ARG_STRING, &config_file, "Config file to use.", NULL}, + {"version", 'v', 0, G_OPTION_ARG_NONE, &show_version, "Display version information and exit.", NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} }; memset(&manager, 0, sizeof(manager)); @@ -372,10 +378,10 @@ int main(int argc, char *argv[]) manager.suspend_delay_fd = -1; manager.suspend_block_fd = -1; - opt_context = g_option_context_new ("- Power management for the Quectel EG25 modem"); - g_option_context_add_main_entries (opt_context, options, NULL); - if (!g_option_context_parse (opt_context, &argc, &argv, &err)) { - g_warning ("%s", err->message); + opt_context = g_option_context_new("- Power management for the Quectel EG25 modem"); + g_option_context_add_main_entries(opt_context, options, NULL); + if (!g_option_context_parse(opt_context, &argc, &argv, &err)) { + g_warning("%s", err->message); return 1; } diff --git a/src/manager.h b/src/manager.h index 6d15ff1..c541947 100644 --- a/src/manager.h +++ b/src/manager.h @@ -41,19 +41,18 @@ typedef enum { EG25_GNSS_SOURCE_QGPS = 1 << 3, } EG25GNSSSource; - enum EG25State { EG25_STATE_INIT = 0, - EG25_STATE_POWERED, // Power-on sequence has been executed, but the modem isn't on yet - EG25_STATE_STARTED, // Modem has been started and declared itdata ready - EG25_STATE_ACQUIRED, // Modem has been probed by ModemManager + EG25_STATE_POWERED, // Power-on sequence has been executed, but the modem isn't on yet + EG25_STATE_STARTED, // Modem has been started and declared itdata ready + EG25_STATE_ACQUIRED, // Modem has been probed by ModemManager EG25_STATE_CONFIGURED, // Modem has been configured through AT commands EG25_STATE_REGISTERED, // Modem is unlocked and registered to a network provider - EG25_STATE_CONNECTED, // Modem is connected (data connection active) + EG25_STATE_CONNECTED, // Modem is connected (data connection active) EG25_STATE_SUSPENDING, // System is going into suspend - EG25_STATE_RESUMING, // System is being resumed, waiting for modem to come back - EG25_STATE_RESETTING, // Something went wrong, we're restarting the modem - EG25_STATE_UPDATING, // Modem is present but being updated + EG25_STATE_RESUMING, // System is being resumed, waiting for modem to come back + EG25_STATE_RESETTING, // Something went wrong, we're restarting the modem + EG25_STATE_UPDATING, // Modem is present but being updated EG25_STATE_FINISHING }; @@ -71,42 +70,42 @@ enum EG25Config { struct EG25Manager { GMainLoop *loop; - guint complete_reset_timer; - guint schedule_reset_timer; - gboolean use_libusb; - guint usb_vid; - guint usb_pid; - guint poweron_delay; + guint complete_reset_timer; + guint schedule_reset_timer; + gboolean use_libusb; + guint usb_vid; + guint usb_pid; + guint poweron_delay; - int at_fd; - guint at_source; + int at_fd; + guint at_source; GList *at_cmds; - void (*at_callback)(struct EG25Manager *manager, const char *response); + void (*at_callback)(struct EG25Manager *manager, const char *response); enum EG25State modem_state; - gchar *modem_usb_id; + gchar *modem_usb_id; - gboolean gnss_assistance_enabled; + gboolean gnss_assistance_enabled; EG25GNSSSource gnss_sources; - EG25GNSSStep gnss_assistance_step; - gint gnss_assistance_fd; - gchar *gnss_assistance_url; - gchar *gnss_assistance_file; + EG25GNSSStep gnss_assistance_step; + gint gnss_assistance_fd; + gchar *gnss_assistance_url; + gchar *gnss_assistance_file; enum ModemIface modem_iface; - guint mm_watch; + guint mm_watch; #ifdef HAVE_MMGLIB - MMManager *mm_manager; - MMModem *mm_modem; + MMManager *mm_manager; + MMModem *mm_modem; MMModemLocation *mm_location; #endif - guint ofono_watch; - GDBOManager *ofono_manager; + guint ofono_watch; + GDBOManager *ofono_manager; GDBusConnection *ofono_connection; GDBusProxy *suspend_proxy; - int suspend_delay_fd; - int suspend_block_fd; + int suspend_delay_fd; + int suspend_block_fd; guint modem_recovery_timer; guint modem_recovery_timeout; @@ -115,18 +114,18 @@ struct EG25Manager { GUdevClient *udev; - struct gpiod_chip *gpiochip[2]; + struct gpiod_chip *gpiochip[2]; struct gpiod_line_request *gpio_out[5]; - guint gpio_out_value[5]; + guint gpio_out_value[5]; struct gpiod_line_request *gpio_in[2]; }; -void modem_configure(struct EG25Manager *data); +void modem_configure(struct EG25Manager *data); gboolean modem_reset(struct EG25Manager *data); -void modem_suspend_pre(struct EG25Manager *data); -void modem_suspend_post(struct EG25Manager *data); -void modem_resume_pre(struct EG25Manager *data); -void modem_resume_post(struct EG25Manager *data); +void modem_suspend_pre(struct EG25Manager *data); +void modem_suspend_post(struct EG25Manager *data); +void modem_resume_pre(struct EG25Manager *data); +void modem_resume_post(struct EG25Manager *data); #ifdef HAVE_MMGLIB void modem_update_state(struct EG25Manager *data, MMModemState state); #endif diff --git a/src/mm-iface.c b/src/mm-iface.c index a55e335..736b7fb 100644 --- a/src/mm-iface.c +++ b/src/mm-iface.c @@ -12,11 +12,11 @@ #include -static void state_changed_cb(MMModem *modem, - MMModemState old, - MMModemState new, - MMModemStateChangeReason reason, - struct EG25Manager *manager) +static void state_changed_cb(MMModem *modem, + MMModemState old, + MMModemState new, + MMModemStateChangeReason reason, + struct EG25Manager *manager) { if (manager->modem_state >= EG25_STATE_CONFIGURED) modem_update_state(manager, new); @@ -24,13 +24,13 @@ static void state_changed_cb(MMModem *modem, static void add_modem(struct EG25Manager *manager, GDBusObject *object) { - const gchar *path; + const gchar *path; MmGdbusModem *gdbus_modem; path = g_dbus_object_get_object_path(object); g_message("Adding new modem `%s'", path); - g_assert(MM_IS_OBJECT (object)); + g_assert(MM_IS_OBJECT(object)); manager->mm_modem = mm_object_get_modem(MM_OBJECT(object)); g_assert_nonnull(manager->mm_modem); @@ -70,15 +70,16 @@ static void add_modem_location(struct EG25Manager *manager, GDBusObject *object) g_assert_nonnull(manager->mm_location); } -static void interface_added_cb (struct EG25Manager *manager, - GDBusObject *object, - GDBusInterface *interface) +static void interface_added_cb(struct EG25Manager *manager, + GDBusObject *object, + GDBusInterface *interface) { GDBusInterfaceInfo *info; info = g_dbus_interface_get_info(interface); g_message("ModemManager interface `%s' found on object `%s'", - info->name, g_dbus_object_get_object_path(object)); + info->name, + g_dbus_object_get_object_path(object)); if (g_strcmp0(info->name, MM_DBUS_INTERFACE_MODEM) == 0) add_modem(manager, object); @@ -87,12 +88,11 @@ static void interface_added_cb (struct EG25Manager *manager, add_modem_location(manager, object); } - static void interface_removed_cb(struct EG25Manager *manager, GDBusObject *object, GDBusInterface *interface) { - const gchar *path; + const gchar *path; GDBusInterfaceInfo *info; path = g_dbus_object_get_object_path(object); @@ -104,7 +104,6 @@ static void interface_removed_cb(struct EG25Manager *manager, manager->mm_modem = NULL; } - static void add_mm_object(struct EG25Manager *manager, GDBusObject *object) { GList *ifaces, *node; @@ -116,7 +115,6 @@ static void add_mm_object(struct EG25Manager *manager, GDBusObject *object) g_list_free_full(ifaces, g_object_unref); } - static void add_mm_objects(struct EG25Manager *manager) { GList *objects, *node; @@ -128,14 +126,12 @@ static void add_mm_objects(struct EG25Manager *manager) g_list_free_full(objects, g_object_unref); } - static void object_added_cb(struct EG25Manager *manager, GDBusObject *object) { g_message("ModemManager object `%s' added", g_dbus_object_get_object_path(object)); add_mm_object(manager, object); } - static void object_removed_cb(struct EG25Manager *manager, GDBusObject *object) { const gchar *path; @@ -146,25 +142,32 @@ static void object_removed_cb(struct EG25Manager *manager, GDBusObject *object) manager->mm_modem = NULL; } - static void mm_manager_new_cb(GDBusConnection *connection, GAsyncResult *res, struct EG25Manager *manager) { - g_autoptr (GError) error = NULL; + g_autoptr(GError) error = NULL; manager->mm_manager = mm_manager_new_finish(res, &error); if (!manager->mm_manager) g_critical("Error creating ModemManager Manager: %s", error->message); g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager), - "interface-added", G_CALLBACK(interface_added_cb), manager); + "interface-added", + G_CALLBACK(interface_added_cb), + manager); g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager), - "interface-removed", G_CALLBACK(interface_removed_cb), manager); + "interface-removed", + G_CALLBACK(interface_removed_cb), + manager); g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager), - "object-added", G_CALLBACK(object_added_cb), manager); + "object-added", + G_CALLBACK(object_added_cb), + manager); g_signal_connect_swapped(G_DBUS_OBJECT_MANAGER(manager->mm_manager), - "object-removed", G_CALLBACK(object_removed_cb), manager); + "object-removed", + G_CALLBACK(object_removed_cb), + manager); add_mm_objects(manager); } @@ -177,13 +180,18 @@ static void mm_appeared_cb(GDBusConnection *connection, g_message("ModemManager appeared on D-Bus"); if (manager->modem_iface != MODEM_IFACE_NONE) { - g_critical("Modem interface already found! Make sure to only run either of ModemManager or oFono."); + g_critical("Modem interface already found! Make sure to only run either of " + "ModemManager or " + "oFono."); return; } manager->modem_iface = MODEM_IFACE_MODEMMANAGER; - mm_manager_new(connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, - NULL, (GAsyncReadyCallback)mm_manager_new_cb, manager); + mm_manager_new(connection, + G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, + NULL, + (GAsyncReadyCallback)mm_manager_new_cb, + manager); } static void mm_iface_clean(struct EG25Manager *manager) @@ -201,9 +209,7 @@ static void mm_iface_clean(struct EG25Manager *manager) } } -static void mm_vanished_cb(GDBusConnection *connection, - const gchar *name, - struct EG25Manager *manager) +static void mm_vanished_cb(GDBusConnection *connection, const gchar *name, struct EG25Manager *manager) { g_message("ModemManager vanished from D-Bus"); mm_iface_clean(manager); @@ -211,11 +217,13 @@ static void mm_vanished_cb(GDBusConnection *connection, void mm_iface_init(struct EG25Manager *manager, toml_table_t *config[]) { - manager->mm_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, MM_DBUS_SERVICE, + manager->mm_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, + MM_DBUS_SERVICE, G_BUS_NAME_WATCHER_FLAGS_AUTO_START, (GBusNameAppearedCallback)mm_appeared_cb, (GBusNameVanishedCallback)mm_vanished_cb, - manager, NULL); + manager, + NULL); } void mm_iface_destroy(struct EG25Manager *manager) diff --git a/src/ofono-iface.c b/src/ofono-iface.c index 6c67396..1a4ad2d 100644 --- a/src/ofono-iface.c +++ b/src/ofono-iface.c @@ -14,9 +14,9 @@ #define OFONO_SERVICE "org.ofono" -static void modem_added_cb(GDBOManager *manager_proxy, - const gchar *path, - GVariant *properties, +static void modem_added_cb(GDBOManager *manager_proxy, + const gchar *path, + GVariant *properties, struct EG25Manager *manager) { GVariant *modem_path; @@ -43,33 +43,28 @@ static void modem_added_cb(GDBOManager *manager_proxy, manager->modem_usb_id = g_strdup(strrchr(g_variant_dup_string(modem_path, NULL), '/') + 1); } -static void modem_removed_cb(GDBOManager *manager_proxy, - const gchar *path, - struct EG25Manager *manager) +static void modem_removed_cb(GDBOManager *manager_proxy, const gchar *path, struct EG25Manager *manager) { } -static void get_modems_cb(GDBOManager *manager_proxy, - GAsyncResult *res, - struct EG25Manager *manager) +static void get_modems_cb(GDBOManager *manager_proxy, GAsyncResult *res, struct EG25Manager *manager) { - gboolean ok; - GVariant *modems; + gboolean ok; + GVariant *modems; GVariantIter *modems_iter = NULL; g_autoptr(GError) error = NULL; const gchar *path; - GVariant *properties; + GVariant *properties; - ok = gdbo_manager_call_get_modems_finish(manager_proxy, &modems, - res, &error); + ok = gdbo_manager_call_get_modems_finish(manager_proxy, &modems, res, &error); if (!ok) { g_warning("Error getting modems from ofono manager: %s", error->message); return; } g_variant_get(modems, "a(oa{sv})", &modems_iter); - while(g_variant_iter_loop(modems_iter, "(&o@a{sv})", &path, &properties)) { + while (g_variant_iter_loop(modems_iter, "(&o@a{sv})", &path, &properties)) { g_debug("Got modem object path '%s'", path); modem_added_cb(manager_proxy, path, properties, manager); } @@ -87,7 +82,9 @@ static void ofono_appeared_cb(GDBusConnection *connection, g_message("oFono appeared on D-Bus"); if (manager->modem_iface != MODEM_IFACE_NONE) { - g_critical("Modem interface already found! Make sure to only run either of ModemManager or oFono."); + g_critical("Modem interface already found! Make sure to only run either of " + "ModemManager or " + "oFono."); return; } /* now connect to oFono! */ @@ -105,14 +102,12 @@ static void ofono_appeared_cb(GDBusConnection *connection, manager->modem_iface = MODEM_IFACE_OFONO; - g_signal_connect(manager->ofono_manager, "modem-added", - G_CALLBACK(modem_added_cb), manager); - g_signal_connect(manager->ofono_manager, "modem-removed", - G_CALLBACK(modem_removed_cb), manager); + g_signal_connect(manager->ofono_manager, "modem-added", G_CALLBACK(modem_added_cb), manager); + g_signal_connect(manager->ofono_manager, "modem-removed", G_CALLBACK(modem_removed_cb), manager); gdbo_manager_call_get_modems(manager->ofono_manager, NULL, - (GAsyncReadyCallback) get_modems_cb, + (GAsyncReadyCallback)get_modems_cb, manager); } @@ -130,11 +125,13 @@ static void ofono_vanished_cb(GDBusConnection *connection, void ofono_iface_init(struct EG25Manager *manager, toml_table_t *config[]) { - manager->ofono_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, OFONO_SERVICE, + manager->ofono_watch = g_bus_watch_name(G_BUS_TYPE_SYSTEM, + OFONO_SERVICE, G_BUS_NAME_WATCHER_FLAGS_AUTO_START, (GBusNameAppearedCallback)ofono_appeared_cb, (GBusNameVanishedCallback)ofono_vanished_cb, - manager, NULL); + manager, + NULL); } void ofono_iface_destroy(struct EG25Manager *manager) diff --git a/src/suspend.c b/src/suspend.c index 9485598..b54bad7 100644 --- a/src/suspend.c +++ b/src/suspend.c @@ -14,9 +14,9 @@ #include -#define SD_NAME "org.freedesktop.login1" -#define SD_PATH "/org/freedesktop/login1" -#define SD_INTERFACE "org.freedesktop.login1.Manager" +#define SD_NAME "org.freedesktop.login1" +#define SD_PATH "/org/freedesktop/login1" +#define SD_INTERFACE "org.freedesktop.login1.Manager" static void resume_ok(struct EG25Manager *manager) { @@ -50,8 +50,7 @@ static gboolean drop_inhibitor(struct EG25Manager *manager, gboolean block) manager->suspend_block_fd = -1; return TRUE; } - } - else { + } else { if (manager->suspend_delay_fd >= 0) { g_message("dropping systemd sleep delay inhibitor"); close(manager->suspend_delay_fd); @@ -62,18 +61,15 @@ static gboolean drop_inhibitor(struct EG25Manager *manager, gboolean block) return FALSE; } -static void inhibit_done_delay(GObject *source, - GAsyncResult *result, - gpointer user_data) +static void inhibit_done_delay(GObject *source, GAsyncResult *result, gpointer user_data) { - GDBusProxy *suspend_proxy = G_DBUS_PROXY(source); + GDBusProxy *suspend_proxy = G_DBUS_PROXY(source); struct EG25Manager *manager = user_data; - g_autoptr (GError) error = NULL; - GVariant *res; + g_autoptr(GError) error = NULL; + GVariant *res; GUnixFDList *fd_list; - res = g_dbus_proxy_call_with_unix_fd_list_finish(suspend_proxy, &fd_list, - result, &error); + res = g_dbus_proxy_call_with_unix_fd_list_finish(suspend_proxy, &fd_list, result, &error); if (!res) { g_warning("inhibit failed: %s", error->message); } else { @@ -88,18 +84,15 @@ static void inhibit_done_delay(GObject *source, } } -static void inhibit_done_block(GObject *source, - GAsyncResult *result, - gpointer user_data) +static void inhibit_done_block(GObject *source, GAsyncResult *result, gpointer user_data) { - GDBusProxy *suspend_proxy = G_DBUS_PROXY(source); + GDBusProxy *suspend_proxy = G_DBUS_PROXY(source); struct EG25Manager *manager = user_data; - g_autoptr (GError) error = NULL; - GVariant *res; + g_autoptr(GError) error = NULL; + GVariant *res; GUnixFDList *fd_list; - res = g_dbus_proxy_call_with_unix_fd_list_finish(suspend_proxy, &fd_list, - result, &error); + res = g_dbus_proxy_call_with_unix_fd_list_finish(suspend_proxy, &fd_list, result, &error); if (!res) { g_warning("inhibit failed: %s", error->message); } else { @@ -133,44 +126,59 @@ static void take_inhibitor(struct EG25Manager *manager, gboolean block) GVariant *variant_arg; if (block) { - if(manager->suspend_block_fd != -1) + if (manager->suspend_block_fd != -1) drop_inhibitor(manager, TRUE); - variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager", - "eg25manager needs to wait for modem to be fully booted", - "block"); + variant_arg = g_variant_new("(ssss)", + "sleep", + "eg25manager", + "eg25manager needs to wait for modem to be fully booted", + "block"); g_message("taking systemd sleep inhibitor (blocking)"); - g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit", - variant_arg, 0, G_MAXINT, NULL, NULL, - inhibit_done_block, manager); + g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, + "Inhibit", + variant_arg, + 0, + G_MAXINT, + NULL, + NULL, + inhibit_done_block, + manager); manager->modem_boot_timer = g_timeout_add_seconds(manager->modem_boot_timeout, G_SOURCE_FUNC(modem_fully_booted), manager); - } - else { - if(manager->suspend_delay_fd != -1) + } else { + if (manager->suspend_delay_fd != -1) drop_inhibitor(manager, FALSE); - variant_arg = g_variant_new ("(ssss)", "sleep", "eg25manager", - "eg25manager needs to prepare modem for sleep", - "delay"); + variant_arg = g_variant_new("(ssss)", + "sleep", + "eg25manager", + "eg25manager needs to prepare modem for sleep", + "delay"); g_message("taking systemd sleep inhibitor"); - g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, "Inhibit", - variant_arg, 0, G_MAXINT, NULL, NULL, - inhibit_done_delay, manager); + g_dbus_proxy_call_with_unix_fd_list(manager->suspend_proxy, + "Inhibit", + variant_arg, + 0, + G_MAXINT, + NULL, + NULL, + inhibit_done_delay, + manager); } } -static void signal_cb(GDBusProxy *proxy, +static void signal_cb(GDBusProxy *proxy, const gchar *sendername, const gchar *signalname, - GVariant *args, - gpointer user_data) + GVariant *args, + gpointer user_data) { struct EG25Manager *manager = user_data; - gboolean is_about_to_suspend; + gboolean is_about_to_suspend; if (strcmp(signalname, "PrepareForSleep") != 0) return; @@ -208,13 +216,11 @@ static void signal_cb(GDBusProxy *proxy, } } -static void name_owner_cb(GObject *object, - GParamSpec *pspec, - gpointer user_data) +static void name_owner_cb(GObject *object, GParamSpec *pspec, gpointer user_data) { - GDBusProxy *proxy = G_DBUS_PROXY(object); + GDBusProxy *proxy = G_DBUS_PROXY(object); struct EG25Manager *manager = user_data; - char *owner; + char *owner; g_assert(proxy == manager->suspend_proxy); @@ -227,11 +233,9 @@ static void name_owner_cb(GObject *object, } } -static void on_proxy_acquired(GObject *object, - GAsyncResult *res, - struct EG25Manager *manager) +static void on_proxy_acquired(GObject *object, GAsyncResult *res, struct EG25Manager *manager) { - g_autoptr (GError) error = NULL; + g_autoptr(GError) error = NULL; char *owner; manager->suspend_proxy = g_dbus_proxy_new_for_bus_finish(res, &error); @@ -240,10 +244,8 @@ static void on_proxy_acquired(GObject *object, return; } - g_signal_connect(manager->suspend_proxy, "notify::g-name-owner", - G_CALLBACK(name_owner_cb), manager); - g_signal_connect(manager->suspend_proxy, "g-signal", - G_CALLBACK(signal_cb), manager); + g_signal_connect(manager->suspend_proxy, "notify::g-name-owner", G_CALLBACK(name_owner_cb), manager); + g_signal_connect(manager->suspend_proxy, "g-signal", G_CALLBACK(signal_cb), manager); owner = g_dbus_proxy_get_name_owner(manager->suspend_proxy); if (owner) { @@ -259,7 +261,7 @@ void suspend_init(struct EG25Manager *manager, toml_table_t *config[]) for (int i = 0; i < EG25_CONFIG_COUNT; i++) suspend_config[i] = config[i] ? toml_table_in(config[i], "suspend") : NULL; - /* + /* * The `suspend` section is optional in both the user and system config files, * so let's make sure suspend_config[EG25_CONFIG_SYS] is valid if one of the * files has it. @@ -281,9 +283,14 @@ void suspend_init(struct EG25Manager *manager, toml_table_t *config[]) g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, SD_NAME, SD_PATH, SD_INTERFACE, NULL, - (GAsyncReadyCallback)on_proxy_acquired, manager); + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + SD_NAME, + SD_PATH, + SD_INTERFACE, + NULL, + (GAsyncReadyCallback)on_proxy_acquired, + manager); } void suspend_destroy(struct EG25Manager *manager) diff --git a/src/suspend.h b/src/suspend.h index fc8648a..17ba314 100644 --- a/src/suspend.h +++ b/src/suspend.h @@ -8,7 +8,7 @@ #include "manager.h" -void suspend_init (struct EG25Manager *data, toml_table_t *config[]); -void suspend_destroy (struct EG25Manager *data); +void suspend_init(struct EG25Manager *data, toml_table_t *config[]); +void suspend_destroy(struct EG25Manager *data); -void suspend_inhibit (struct EG25Manager *data, gboolean inhibit, gboolean block); +void suspend_inhibit(struct EG25Manager *data, gboolean inhibit, gboolean block); diff --git a/src/toml.c b/src/toml.c index 073974b..62a7de6 100644 --- a/src/toml.c +++ b/src/toml.c @@ -2,19 +2,19 @@ MIT License - Copyright (c) 2017 - 2019 CK Tan + Copyright (c) 2017 - 2019 CK Tan https://github.com/cktan/tomlc99 - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -25,2225 +25,2342 @@ */ #define _POSIX_C_SOURCE 200809L +#include "toml.h" +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -#include -#include "toml.h" +static void *(*ppmalloc)(size_t) = malloc; +static void (*ppfree)(void *) = free; -static void* (*ppmalloc)(size_t) = malloc; -static void (*ppfree)(void*) = free; - -void toml_set_memutil(void* (*xxmalloc)(size_t), - void (*xxfree)(void*)) +void toml_set_memutil(void *(*xxmalloc)(size_t), void (*xxfree)(void *)) { - if (xxmalloc) ppmalloc = xxmalloc; - if (xxfree) ppfree = xxfree; + if (xxmalloc) + ppmalloc = xxmalloc; + if (xxfree) + ppfree = xxfree; } +#define MALLOC(a) ppmalloc(a) +#define FREE(a) ppfree(a) -#define MALLOC(a) ppmalloc(a) -#define FREE(a) ppfree(a) - -static void* CALLOC(size_t nmemb, size_t sz) +static void *CALLOC(size_t nmemb, size_t sz) { - int nb = sz * nmemb; - void* p = MALLOC(nb); - if (p) { - memset(p, 0, nb); - } - return p; + int nb = sz * nmemb; + void *p = MALLOC(nb); + if (p) { + memset(p, 0, nb); + } + return p; } - -static char* STRDUP(const char* s) +static char *STRDUP(const char *s) { - int len = strlen(s); - char* p = MALLOC(len+1); - if (p) { - memcpy(p, s, len); - p[len] = 0; - } - return p; + int len = strlen(s); + char *p = MALLOC(len + 1); + if (p) { + memcpy(p, s, len); + p[len] = 0; + } + return p; } -static char* STRNDUP(const char* s, size_t n) +static char *STRNDUP(const char *s, size_t n) { - size_t len = strnlen(s, n); - char* p = MALLOC(len+1); - if (p) { - memcpy(p, s, len); - p[len] = 0; - } - return p; + size_t len = strnlen(s, n); + char *p = MALLOC(len + 1); + if (p) { + memcpy(p, s, len); + p[len] = 0; + } + return p; } - - /** * Convert a char in utf8 into UCS, and store it in *ret. * Return #bytes consumed or -1 on failure. */ -int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret) +int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret) { - const unsigned char* buf = (const unsigned char*) orig; - unsigned i = *buf++; - int64_t v; - - /* 0x00000000 - 0x0000007F: - 0xxxxxxx - */ - if (0 == (i >> 7)) { - if (len < 1) return -1; - v = i; - return *ret = v, 1; - } - /* 0x00000080 - 0x000007FF: - 110xxxxx 10xxxxxx - */ - if (0x6 == (i >> 5)) { - if (len < 2) return -1; - v = i & 0x1f; - for (int j = 0; j < 1; j++) { - i = *buf++; - if (0x2 != (i >> 6)) return -1; - v = (v << 6) | (i & 0x3f); - } - return *ret = v, (const char*) buf - orig; - } + const unsigned char *buf = (const unsigned char *)orig; + unsigned i = *buf++; + int64_t v; - /* 0x00000800 - 0x0000FFFF: - 1110xxxx 10xxxxxx 10xxxxxx - */ - if (0xE == (i >> 4)) { - if (len < 3) return -1; - v = i & 0x0F; - for (int j = 0; j < 2; j++) { - i = *buf++; - if (0x2 != (i >> 6)) return -1; - v = (v << 6) | (i & 0x3f); - } - return *ret = v, (const char*) buf - orig; - } + /* 0x00000000 - 0x0000007F: + 0xxxxxxx + */ + if (0 == (i >> 7)) { + if (len < 1) + return -1; + v = i; + return *ret = v, 1; + } + /* 0x00000080 - 0x000007FF: + 110xxxxx 10xxxxxx + */ + if (0x6 == (i >> 5)) { + if (len < 2) + return -1; + v = i & 0x1f; + for (int j = 0; j < 1; j++) { + i = *buf++; + if (0x2 != (i >> 6)) + return -1; + v = (v << 6) | (i & 0x3f); + } + return *ret = v, (const char *)buf - orig; + } - /* 0x00010000 - 0x001FFFFF: - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - if (0x1E == (i >> 3)) { - if (len < 4) return -1; - v = i & 0x07; - for (int j = 0; j < 3; j++) { - i = *buf++; - if (0x2 != (i >> 6)) return -1; - v = (v << 6) | (i & 0x3f); - } - return *ret = v, (const char*) buf - orig; - } - - /* 0x00200000 - 0x03FFFFFF: - 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - if (0x3E == (i >> 2)) { - if (len < 5) return -1; - v = i & 0x03; - for (int j = 0; j < 4; j++) { - i = *buf++; - if (0x2 != (i >> 6)) return -1; - v = (v << 6) | (i & 0x3f); - } - return *ret = v, (const char*) buf - orig; - } + /* 0x00000800 - 0x0000FFFF: + 1110xxxx 10xxxxxx 10xxxxxx + */ + if (0xE == (i >> 4)) { + if (len < 3) + return -1; + v = i & 0x0F; + for (int j = 0; j < 2; j++) { + i = *buf++; + if (0x2 != (i >> 6)) + return -1; + v = (v << 6) | (i & 0x3f); + } + return *ret = v, (const char *)buf - orig; + } - /* 0x04000000 - 0x7FFFFFFF: - 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - if (0x7e == (i >> 1)) { - if (len < 6) return -1; - v = i & 0x01; - for (int j = 0; j < 5; j++) { - i = *buf++; - if (0x2 != (i >> 6)) return -1; - v = (v << 6) | (i & 0x3f); - } - return *ret = v, (const char*) buf - orig; - } - return -1; + /* 0x00010000 - 0x001FFFFF: + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + if (0x1E == (i >> 3)) { + if (len < 4) + return -1; + v = i & 0x07; + for (int j = 0; j < 3; j++) { + i = *buf++; + if (0x2 != (i >> 6)) + return -1; + v = (v << 6) | (i & 0x3f); + } + return *ret = v, (const char *)buf - orig; + } + + /* 0x00200000 - 0x03FFFFFF: + 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + if (0x3E == (i >> 2)) { + if (len < 5) + return -1; + v = i & 0x03; + for (int j = 0; j < 4; j++) { + i = *buf++; + if (0x2 != (i >> 6)) + return -1; + v = (v << 6) | (i & 0x3f); + } + return *ret = v, (const char *)buf - orig; + } + + /* 0x04000000 - 0x7FFFFFFF: + 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + if (0x7e == (i >> 1)) { + if (len < 6) + return -1; + v = i & 0x01; + for (int j = 0; j < 5; j++) { + i = *buf++; + if (0x2 != (i >> 6)) + return -1; + v = (v << 6) | (i & 0x3f); + } + return *ret = v, (const char *)buf - orig; + } + return -1; } - /** * Convert a UCS char to utf8 code, and return it in buf. - * Return #bytes used in buf to encode the char, or + * Return #bytes used in buf to encode the char, or * -1 on error. */ int toml_ucs_to_utf8(int64_t code, char buf[6]) { - /* http://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16 */ - /* The UCS code values 0xd800–0xdfff (UTF-16 surrogates) as well - * as 0xfffe and 0xffff (UCS noncharacters) should not appear in - * conforming UTF-8 streams. - */ - if (0xd800 <= code && code <= 0xdfff) return -1; - if (0xfffe <= code && code <= 0xffff) return -1; + /* http://stackoverflow.com/questions/6240055/manually-converting-unicode-codepoints-into-utf-8-and-utf-16 + */ + /* The UCS code values 0xd800–0xdfff (UTF-16 surrogates) as well + * as 0xfffe and 0xffff (UCS noncharacters) should not appear in + * conforming UTF-8 streams. + */ + if (0xd800 <= code && code <= 0xdfff) + return -1; + if (0xfffe <= code && code <= 0xffff) + return -1; - /* 0x00000000 - 0x0000007F: - 0xxxxxxx - */ - if (code < 0) return -1; - if (code <= 0x7F) { - buf[0] = (unsigned char) code; - return 1; - } + /* 0x00000000 - 0x0000007F: + 0xxxxxxx + */ + if (code < 0) + return -1; + if (code <= 0x7F) { + buf[0] = (unsigned char)code; + return 1; + } - /* 0x00000080 - 0x000007FF: - 110xxxxx 10xxxxxx - */ - if (code <= 0x000007FF) { - buf[0] = 0xc0 | (code >> 6); - buf[1] = 0x80 | (code & 0x3f); - return 2; - } + /* 0x00000080 - 0x000007FF: + 110xxxxx 10xxxxxx + */ + if (code <= 0x000007FF) { + buf[0] = 0xc0 | (code >> 6); + buf[1] = 0x80 | (code & 0x3f); + return 2; + } - /* 0x00000800 - 0x0000FFFF: - 1110xxxx 10xxxxxx 10xxxxxx - */ - if (code <= 0x0000FFFF) { - buf[0] = 0xe0 | (code >> 12); - buf[1] = 0x80 | ((code >> 6) & 0x3f); - buf[2] = 0x80 | (code & 0x3f); - return 3; - } + /* 0x00000800 - 0x0000FFFF: + 1110xxxx 10xxxxxx 10xxxxxx + */ + if (code <= 0x0000FFFF) { + buf[0] = 0xe0 | (code >> 12); + buf[1] = 0x80 | ((code >> 6) & 0x3f); + buf[2] = 0x80 | (code & 0x3f); + return 3; + } - /* 0x00010000 - 0x001FFFFF: - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - if (code <= 0x001FFFFF) { - buf[0] = 0xf0 | (code >> 18); - buf[1] = 0x80 | ((code >> 12) & 0x3f); - buf[2] = 0x80 | ((code >> 6) & 0x3f); - buf[3] = 0x80 | (code & 0x3f); - return 4; - } + /* 0x00010000 - 0x001FFFFF: + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + if (code <= 0x001FFFFF) { + buf[0] = 0xf0 | (code >> 18); + buf[1] = 0x80 | ((code >> 12) & 0x3f); + buf[2] = 0x80 | ((code >> 6) & 0x3f); + buf[3] = 0x80 | (code & 0x3f); + return 4; + } - /* 0x00200000 - 0x03FFFFFF: - 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - if (code <= 0x03FFFFFF) { - buf[0] = 0xf8 | (code >> 24); - buf[1] = 0x80 | ((code >> 18) & 0x3f); - buf[2] = 0x80 | ((code >> 12) & 0x3f); - buf[3] = 0x80 | ((code >> 6) & 0x3f); - buf[4] = 0x80 | (code & 0x3f); - return 5; - } - - /* 0x04000000 - 0x7FFFFFFF: - 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - if (code <= 0x7FFFFFFF) { - buf[0] = 0xfc | (code >> 30); - buf[1] = 0x80 | ((code >> 24) & 0x3f); - buf[2] = 0x80 | ((code >> 18) & 0x3f); - buf[3] = 0x80 | ((code >> 12) & 0x3f); - buf[4] = 0x80 | ((code >> 6) & 0x3f); - buf[5] = 0x80 | (code & 0x3f); - return 6; - } + /* 0x00200000 - 0x03FFFFFF: + 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + if (code <= 0x03FFFFFF) { + buf[0] = 0xf8 | (code >> 24); + buf[1] = 0x80 | ((code >> 18) & 0x3f); + buf[2] = 0x80 | ((code >> 12) & 0x3f); + buf[3] = 0x80 | ((code >> 6) & 0x3f); + buf[4] = 0x80 | (code & 0x3f); + return 5; + } - return -1; + /* 0x04000000 - 0x7FFFFFFF: + 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + if (code <= 0x7FFFFFFF) { + buf[0] = 0xfc | (code >> 30); + buf[1] = 0x80 | ((code >> 24) & 0x3f); + buf[2] = 0x80 | ((code >> 18) & 0x3f); + buf[3] = 0x80 | ((code >> 12) & 0x3f); + buf[4] = 0x80 | ((code >> 6) & 0x3f); + buf[5] = 0x80 | (code & 0x3f); + return 6; + } + + return -1; } /* - * TOML has 3 data structures: value, array, table. + * TOML has 3 data structures: value, array, table. * Each of them can have identification key. */ typedef struct toml_keyval_t toml_keyval_t; struct toml_keyval_t { - const char* key; /* key to this value */ - const char* val; /* the raw value */ + const char *key; /* key to this value */ + const char *val; /* the raw value */ }; - struct toml_array_t { - const char* key; /* key to this array */ - int kind; /* element kind: 'v'alue, 'a'rray, or 't'able */ - int type; /* for value kind: 'i'nt, 'd'ouble, 'b'ool, 's'tring, 't'ime, 'D'ate, 'T'imestamp */ - - int nelem; /* number of elements */ - union { - char** val; - toml_array_t** arr; - toml_table_t** tab; - } u; + const char *key; /* key to this array */ + int kind; /* element kind: 'v'alue, 'a'rray, or 't'able */ + int type; /* for value kind: 'i'nt, 'd'ouble, 'b'ool, 's'tring, 't'ime, 'D'ate, 'T'imestamp */ + + int nelem; /* number of elements */ + union { + char **val; + toml_array_t **arr; + toml_table_t **tab; + } u; }; - struct toml_table_t { - const char* key; /* key to this table */ - bool implicit; /* table was created implicitly */ + const char *key; /* key to this table */ + bool implicit; /* table was created implicitly */ - /* key-values in the table */ - int nkval; - toml_keyval_t** kval; + /* key-values in the table */ + int nkval; + toml_keyval_t **kval; - /* arrays in the table */ - int narr; - toml_array_t** arr; + /* arrays in the table */ + int narr; + toml_array_t **arr; - /* tables in the table */ - int ntab; - toml_table_t** tab; + /* tables in the table */ + int ntab; + toml_table_t **tab; }; - -static inline void xfree(const void* x) { if (x) FREE((void*)(intptr_t)x); } - +static inline void xfree(const void *x) +{ + if (x) + FREE((void *)(intptr_t)x); +} enum tokentype_t { - INVALID, - DOT, - COMMA, - EQUAL, - LBRACE, - RBRACE, - NEWLINE, - LBRACKET, - RBRACKET, - STRING, + INVALID, + DOT, + COMMA, + EQUAL, + LBRACE, + RBRACE, + NEWLINE, + LBRACKET, + RBRACKET, + STRING, }; typedef enum tokentype_t tokentype_t; typedef struct token_t token_t; struct token_t { - tokentype_t tok; - int lineno; - char* ptr; /* points into context->start */ - int len; - int eof; + tokentype_t tok; + int lineno; + char *ptr; /* points into context->start */ + int len; + int eof; }; - typedef struct context_t context_t; struct context_t { - char* start; - char* stop; - char* errbuf; - int errbufsz; + char *start; + char *stop; + char *errbuf; + int errbufsz; - token_t tok; - toml_table_t* root; - toml_table_t* curtab; - - struct { - int top; - char* key[10]; - token_t tok[10]; - } tpath; + token_t tok; + toml_table_t *root; + toml_table_t *curtab; + struct { + int top; + char *key[10]; + token_t tok[10]; + } tpath; }; #define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) -#define FLINE __FILE__ ":" TOSTRING(__LINE__) +#define TOSTRING(x) STRINGIFY(x) +#define FLINE __FILE__ ":" TOSTRING(__LINE__) -static int next_token(context_t* ctx, int dotisspecial); +static int next_token(context_t *ctx, int dotisspecial); /* Error reporting. Call when an error is detected. Always return -1. */ -static int e_outofmemory(context_t* ctx, const char* fline) +static int e_outofmemory(context_t *ctx, const char *fline) { - snprintf(ctx->errbuf, ctx->errbufsz, "ERROR: out of memory (%s)", fline); - return -1; + snprintf(ctx->errbuf, ctx->errbufsz, "ERROR: out of memory (%s)", fline); + return -1; } - -static int e_internal(context_t* ctx, const char* fline) +static int e_internal(context_t *ctx, const char *fline) { - snprintf(ctx->errbuf, ctx->errbufsz, "internal error (%s)", fline); - return -1; + snprintf(ctx->errbuf, ctx->errbufsz, "internal error (%s)", fline); + return -1; } -static int e_syntax(context_t* ctx, int lineno, const char* msg) +static int e_syntax(context_t *ctx, int lineno, const char *msg) { - snprintf(ctx->errbuf, ctx->errbufsz, "line %d: %s", lineno, msg); - return -1; + snprintf(ctx->errbuf, ctx->errbufsz, "line %d: %s", lineno, msg); + return -1; } -static int e_badkey(context_t* ctx, int lineno) +static int e_badkey(context_t *ctx, int lineno) { - snprintf(ctx->errbuf, ctx->errbufsz, "line %d: bad key", lineno); - return -1; + snprintf(ctx->errbuf, ctx->errbufsz, "line %d: bad key", lineno); + return -1; } -static int e_keyexists(context_t* ctx, int lineno) +static int e_keyexists(context_t *ctx, int lineno) { - snprintf(ctx->errbuf, ctx->errbufsz, "line %d: key exists", lineno); - return -1; + snprintf(ctx->errbuf, ctx->errbufsz, "line %d: key exists", lineno); + return -1; } -static void* expand(void* p, int sz, int newsz) +static void *expand(void *p, int sz, int newsz) { - void* s = MALLOC(newsz); - if (!s) return 0; - - memcpy(s, p, sz); - FREE(p); - return s; + void *s = MALLOC(newsz); + if (!s) + return 0; + + memcpy(s, p, sz); + FREE(p); + return s; } -static void** expand_ptrarr(void** p, int n) +static void **expand_ptrarr(void **p, int n) { - void** s = MALLOC((n+1) * sizeof(void*)); - if (!s) return 0; + void **s = MALLOC((n + 1) * sizeof(void *)); + if (!s) + return 0; - s[n] = 0; - memcpy(s, p, n * sizeof(void*)); - FREE(p); - return s; + s[n] = 0; + memcpy(s, p, n * sizeof(void *)); + FREE(p); + return s; } - -static char* norm_lit_str(const char* src, int srclen, - int multiline, - char* errbuf, int errbufsz) +static char *norm_lit_str(const char *src, int srclen, int multiline, char *errbuf, int errbufsz) { - char* dst = 0; /* will write to dst[] and return it */ - int max = 0; /* max size of dst[] */ - int off = 0; /* cur offset in dst[] */ - const char* sp = src; - const char* sq = src + srclen; - int ch; + char *dst = 0; /* will write to dst[] and return it */ + int max = 0; /* max size of dst[] */ + int off = 0; /* cur offset in dst[] */ + const char *sp = src; + const char *sq = src + srclen; + int ch; - /* scan forward on src */ - for (;;) { - if (off >= max - 10) { /* have some slack for misc stuff */ - int newmax = max + 50; - char* x = expand(dst, max, newmax); - if (!x) { - xfree(dst); - snprintf(errbuf, errbufsz, "out of memory"); - return 0; - } - dst = x; - max = newmax; - } - - /* finished? */ - if (sp >= sq) break; - - ch = *sp++; - /* control characters other than tab is not allowed */ - if ((0 <= ch && ch <= 0x08) - || (0x0a <= ch && ch <= 0x1f) - || (ch == 0x7f)) { - if (! (multiline && (ch == '\r' || ch == '\n'))) { - xfree(dst); - snprintf(errbuf, errbufsz, "invalid char U+%04x", ch); - return 0; - } - } - - // a plain copy suffice - dst[off++] = ch; - } + /* scan forward on src */ + for (;;) { + if (off >= max - 10) { /* have some slack for misc stuff */ + int newmax = max + 50; + char *x = expand(dst, max, newmax); + if (!x) { + xfree(dst); + snprintf(errbuf, errbufsz, "out of memory"); + return 0; + } + dst = x; + max = newmax; + } - dst[off++] = 0; - return dst; + /* finished? */ + if (sp >= sq) + break; + + ch = *sp++; + /* control characters other than tab is not allowed */ + if ((0 <= ch && ch <= 0x08) || (0x0a <= ch && ch <= 0x1f) || (ch == 0x7f)) { + if (!(multiline && (ch == '\r' || ch == '\n'))) { + xfree(dst); + snprintf(errbuf, errbufsz, "invalid char U+%04x", ch); + return 0; + } + } + + // a plain copy suffice + dst[off++] = ch; + } + + dst[off++] = 0; + return dst; } - - - -/* +/* * Convert src to raw unescaped utf-8 string. * Returns NULL if error with errmsg in errbuf. */ -static char* norm_basic_str(const char* src, int srclen, - int multiline, - char* errbuf, int errbufsz) +static char *norm_basic_str(const char *src, int srclen, int multiline, char *errbuf, int errbufsz) { - char* dst = 0; /* will write to dst[] and return it */ - int max = 0; /* max size of dst[] */ - int off = 0; /* cur offset in dst[] */ - const char* sp = src; - const char* sq = src + srclen; - int ch; + char *dst = 0; /* will write to dst[] and return it */ + int max = 0; /* max size of dst[] */ + int off = 0; /* cur offset in dst[] */ + const char *sp = src; + const char *sq = src + srclen; + int ch; - /* scan forward on src */ - for (;;) { - if (off >= max - 10) { /* have some slack for misc stuff */ - int newmax = max + 50; - char* x = expand(dst, max, newmax); - if (!x) { - xfree(dst); - snprintf(errbuf, errbufsz, "out of memory"); - return 0; - } - dst = x; - max = newmax; - } - - /* finished? */ - if (sp >= sq) break; - - ch = *sp++; - if (ch != '\\') { - /* these chars must be escaped: U+0000 to U+0008, U+000A to U+001F, U+007F */ - if ((0 <= ch && ch <= 0x08) - || (0x0a <= ch && ch <= 0x1f) - || (ch == 0x7f)) { - if (! (multiline && (ch == '\r' || ch == '\n'))) { - xfree(dst); - snprintf(errbuf, errbufsz, "invalid char U+%04x", ch); - return 0; - } - } - - // a plain copy suffice - dst[off++] = ch; - continue; - } + /* scan forward on src */ + for (;;) { + if (off >= max - 10) { /* have some slack for misc stuff */ + int newmax = max + 50; + char *x = expand(dst, max, newmax); + if (!x) { + xfree(dst); + snprintf(errbuf, errbufsz, "out of memory"); + return 0; + } + dst = x; + max = newmax; + } - /* ch was backslash. we expect the escape char. */ - if (sp >= sq) { - snprintf(errbuf, errbufsz, "last backslash is invalid"); - xfree(dst); - return 0; - } + /* finished? */ + if (sp >= sq) + break; - /* for multi-line, we want to kill line-ending-backslash ... */ - if (multiline) { + ch = *sp++; + if (ch != '\\') { + /* these chars must be escaped: U+0000 to U+0008, U+000A to U+001F, U+007F */ + if ((0 <= ch && ch <= 0x08) || (0x0a <= ch && ch <= 0x1f) || (ch == 0x7f)) { + if (!(multiline && (ch == '\r' || ch == '\n'))) { + xfree(dst); + snprintf(errbuf, errbufsz, "invalid char U+%04x", ch); + return 0; + } + } - // if there is only whitespace after the backslash ... - if (sp[strspn(sp, " \t\r")] == '\n') { - /* skip all the following whitespaces */ - sp += strspn(sp, " \t\r\n"); - continue; - } - } + // a plain copy suffice + dst[off++] = ch; + continue; + } - /* get the escaped char */ - ch = *sp++; - switch (ch) { - case 'u': case 'U': - { - int64_t ucs = 0; - int nhex = (ch == 'u' ? 4 : 8); - for (int i = 0; i < nhex; i++) { - if (sp >= sq) { - snprintf(errbuf, errbufsz, "\\%c expects %d hex chars", ch, nhex); - xfree(dst); - return 0; - } - ch = *sp++; - int v = ('0' <= ch && ch <= '9') - ? ch - '0' - : (('A' <= ch && ch <= 'F') ? ch - 'A' + 10 : -1); - if (-1 == v) { - snprintf(errbuf, errbufsz, "invalid hex chars for \\u or \\U"); - xfree(dst); - return 0; - } - ucs = ucs * 16 + v; - } - int n = toml_ucs_to_utf8(ucs, &dst[off]); - if (-1 == n) { - snprintf(errbuf, errbufsz, "illegal ucs code in \\u or \\U"); - xfree(dst); - return 0; - } - off += n; - } - continue; + /* ch was backslash. we expect the escape char. */ + if (sp >= sq) { + snprintf(errbuf, errbufsz, "last backslash is invalid"); + xfree(dst); + return 0; + } - case 'b': ch = '\b'; break; - case 't': ch = '\t'; break; - case 'n': ch = '\n'; break; - case 'f': ch = '\f'; break; - case 'r': ch = '\r'; break; - case '"': ch = '"'; break; - case '\\': ch = '\\'; break; - default: - snprintf(errbuf, errbufsz, "illegal escape char \\%c", ch); - xfree(dst); - return 0; - } + /* for multi-line, we want to kill line-ending-backslash ... */ + if (multiline) { - dst[off++] = ch; - } + // if there is only whitespace after the backslash ... + if (sp[strspn(sp, " \t\r")] == '\n') { + /* skip all the following whitespaces */ + sp += strspn(sp, " \t\r\n"); + continue; + } + } - // Cap with NUL and return it. - dst[off++] = 0; - return dst; + /* get the escaped char */ + ch = *sp++; + switch (ch) { + case 'u': + case 'U': { + int64_t ucs = 0; + int nhex = (ch == 'u' ? 4 : 8); + for (int i = 0; i < nhex; i++) { + if (sp >= sq) { + snprintf(errbuf, errbufsz, "\\%c expects %d hex chars", ch, nhex); + xfree(dst); + return 0; + } + ch = *sp++; + int v = ('0' <= ch && ch <= '9') ? ch - '0' + : (('A' <= ch && ch <= 'F') ? ch - 'A' + 10 : -1); + if (-1 == v) { + snprintf(errbuf, errbufsz, "invalid hex chars for \\u or \\U"); + xfree(dst); + return 0; + } + ucs = ucs * 16 + v; + } + int n = toml_ucs_to_utf8(ucs, &dst[off]); + if (-1 == n) { + snprintf(errbuf, errbufsz, "illegal ucs code in \\u or \\U"); + xfree(dst); + return 0; + } + off += n; + } + continue; + + case 'b': + ch = '\b'; + break; + case 't': + ch = '\t'; + break; + case 'n': + ch = '\n'; + break; + case 'f': + ch = '\f'; + break; + case 'r': + ch = '\r'; + break; + case '"': + ch = '"'; + break; + case '\\': + ch = '\\'; + break; + default: + snprintf(errbuf, errbufsz, "illegal escape char \\%c", ch); + xfree(dst); + return 0; + } + + dst[off++] = ch; + } + + // Cap with NUL and return it. + dst[off++] = 0; + return dst; } - /* Normalize a key. Convert all special chars to raw unescaped utf-8 chars. */ -static char* normalize_key(context_t* ctx, token_t strtok) +static char *normalize_key(context_t *ctx, token_t strtok) { - const char* sp = strtok.ptr; - const char* sq = strtok.ptr + strtok.len; - int lineno = strtok.lineno; - char* ret; - int ch = *sp; - char ebuf[80]; + const char *sp = strtok.ptr; + const char *sq = strtok.ptr + strtok.len; + int lineno = strtok.lineno; + char *ret; + int ch = *sp; + char ebuf[80]; - /* handle quoted string */ - if (ch == '\'' || ch == '\"') { - /* if ''' or """, take 3 chars off front and back. Else, take 1 char off. */ - int multiline = 0; - if (sp[1] == ch && sp[2] == ch) { - sp += 3, sq -= 3; - multiline = 1; - } - else - sp++, sq--; + /* handle quoted string */ + if (ch == '\'' || ch == '\"') { + /* if ''' or """, take 3 chars off front and back. Else, take 1 char off. */ + int multiline = 0; + if (sp[1] == ch && sp[2] == ch) { + sp += 3, sq -= 3; + multiline = 1; + } else + sp++, sq--; - if (ch == '\'') { - /* for single quote, take it verbatim. */ - if (! (ret = STRNDUP(sp, sq - sp))) { - e_outofmemory(ctx, FLINE); - return 0; - } - } else { - /* for double quote, we need to normalize */ - ret = norm_basic_str(sp, sq - sp, multiline, ebuf, sizeof(ebuf)); - if (!ret) { - e_syntax(ctx, lineno, ebuf); - return 0; - } - } + if (ch == '\'') { + /* for single quote, take it verbatim. */ + if (!(ret = STRNDUP(sp, sq - sp))) { + e_outofmemory(ctx, FLINE); + return 0; + } + } else { + /* for double quote, we need to normalize */ + ret = norm_basic_str(sp, sq - sp, multiline, ebuf, sizeof(ebuf)); + if (!ret) { + e_syntax(ctx, lineno, ebuf); + return 0; + } + } - /* newlines are not allowed in keys */ - if (strchr(ret, '\n')) { - xfree(ret); - e_badkey(ctx, lineno); - return 0; - } - return ret; - } - - /* for bare-key allow only this regex: [A-Za-z0-9_-]+ */ - const char* xp; - for (xp = sp; xp != sq; xp++) { - int k = *xp; - if (isalnum(k)) continue; - if (k == '_' || k == '-') continue; - e_badkey(ctx, lineno); - return 0; - } + /* newlines are not allowed in keys */ + if (strchr(ret, '\n')) { + xfree(ret); + e_badkey(ctx, lineno); + return 0; + } + return ret; + } - /* dup and return it */ - if (! (ret = STRNDUP(sp, sq - sp))) { - e_outofmemory(ctx, FLINE); - return 0; - } - return ret; + /* for bare-key allow only this regex: [A-Za-z0-9_-]+ */ + const char *xp; + for (xp = sp; xp != sq; xp++) { + int k = *xp; + if (isalnum(k)) + continue; + if (k == '_' || k == '-') + continue; + e_badkey(ctx, lineno); + return 0; + } + + /* dup and return it */ + if (!(ret = STRNDUP(sp, sq - sp))) { + e_outofmemory(ctx, FLINE); + return 0; + } + return ret; } - -/* +/* * Look up key in tab. Return 0 if not found, or * 'v'alue, 'a'rray or 't'able depending on the element. */ -static int check_key(toml_table_t* tab, const char* key, - toml_keyval_t** ret_val, - toml_array_t** ret_arr, - toml_table_t** ret_tab) +static int check_key(toml_table_t *tab, + const char *key, + toml_keyval_t **ret_val, + toml_array_t **ret_arr, + toml_table_t **ret_tab) { - int i; - void* dummy; + int i; + void *dummy; - if (!ret_tab) ret_tab = (toml_table_t**) &dummy; - if (!ret_arr) ret_arr = (toml_array_t**) &dummy; - if (!ret_val) ret_val = (toml_keyval_t**) &dummy; + if (!ret_tab) + ret_tab = (toml_table_t **)&dummy; + if (!ret_arr) + ret_arr = (toml_array_t **)&dummy; + if (!ret_val) + ret_val = (toml_keyval_t **)&dummy; - *ret_tab = 0; *ret_arr = 0; *ret_val = 0; - - for (i = 0; i < tab->nkval; i++) { - if (0 == strcmp(key, tab->kval[i]->key)) { - *ret_val = tab->kval[i]; - return 'v'; - } - } - for (i = 0; i < tab->narr; i++) { - if (0 == strcmp(key, tab->arr[i]->key)) { - *ret_arr = tab->arr[i]; - return 'a'; - } - } - for (i = 0; i < tab->ntab; i++) { - if (0 == strcmp(key, tab->tab[i]->key)) { - *ret_tab = tab->tab[i]; - return 't'; - } - } - return 0; + *ret_tab = 0; + *ret_arr = 0; + *ret_val = 0; + + for (i = 0; i < tab->nkval; i++) { + if (0 == strcmp(key, tab->kval[i]->key)) { + *ret_val = tab->kval[i]; + return 'v'; + } + } + for (i = 0; i < tab->narr; i++) { + if (0 == strcmp(key, tab->arr[i]->key)) { + *ret_arr = tab->arr[i]; + return 'a'; + } + } + for (i = 0; i < tab->ntab; i++) { + if (0 == strcmp(key, tab->tab[i]->key)) { + *ret_tab = tab->tab[i]; + return 't'; + } + } + return 0; } - -static int key_kind(toml_table_t* tab, const char* key) +static int key_kind(toml_table_t *tab, const char *key) { - return check_key(tab, key, 0, 0, 0); + return check_key(tab, key, 0, 0, 0); } -/* Create a keyval in the table. +/* Create a keyval in the table. */ -static toml_keyval_t* create_keyval_in_table(context_t* ctx, toml_table_t* tab, token_t keytok) +static toml_keyval_t *create_keyval_in_table(context_t *ctx, toml_table_t *tab, token_t keytok) { - /* first, normalize the key to be used for lookup. - * remember to free it if we error out. - */ - char* newkey = normalize_key(ctx, keytok); - if (!newkey) return 0; + /* first, normalize the key to be used for lookup. + * remember to free it if we error out. + */ + char *newkey = normalize_key(ctx, keytok); + if (!newkey) + return 0; - /* if key exists: error out. */ - toml_keyval_t* dest = 0; - if (key_kind(tab, newkey)) { - xfree(newkey); - e_keyexists(ctx, keytok.lineno); - return 0; - } + /* if key exists: error out. */ + toml_keyval_t *dest = 0; + if (key_kind(tab, newkey)) { + xfree(newkey); + e_keyexists(ctx, keytok.lineno); + return 0; + } - /* make a new entry */ - int n = tab->nkval; - toml_keyval_t** base; - if (0 == (base = (toml_keyval_t**) expand_ptrarr((void**)tab->kval, n))) { - xfree(newkey); - e_outofmemory(ctx, FLINE); - return 0; - } - tab->kval = base; - - if (0 == (base[n] = (toml_keyval_t*) CALLOC(1, sizeof(*base[n])))) { - xfree(newkey); - e_outofmemory(ctx, FLINE); - return 0; - } - dest = tab->kval[tab->nkval++]; + /* make a new entry */ + int n = tab->nkval; + toml_keyval_t **base; + if (0 == (base = (toml_keyval_t **)expand_ptrarr((void **)tab->kval, n))) { + xfree(newkey); + e_outofmemory(ctx, FLINE); + return 0; + } + tab->kval = base; - /* save the key in the new value struct */ - dest->key = newkey; - return dest; + if (0 == (base[n] = (toml_keyval_t *)CALLOC(1, sizeof(*base[n])))) { + xfree(newkey); + e_outofmemory(ctx, FLINE); + return 0; + } + dest = tab->kval[tab->nkval++]; + + /* save the key in the new value struct */ + dest->key = newkey; + return dest; } - /* Create a table in the table. */ -static toml_table_t* create_keytable_in_table(context_t* ctx, toml_table_t* tab, token_t keytok) +static toml_table_t *create_keytable_in_table(context_t *ctx, toml_table_t *tab, token_t keytok) { - /* first, normalize the key to be used for lookup. - * remember to free it if we error out. - */ - char* newkey = normalize_key(ctx, keytok); - if (!newkey) return 0; + /* first, normalize the key to be used for lookup. + * remember to free it if we error out. + */ + char *newkey = normalize_key(ctx, keytok); + if (!newkey) + return 0; - /* if key exists: error out */ - toml_table_t* dest = 0; - if (check_key(tab, newkey, 0, 0, &dest)) { - xfree(newkey); /* don't need this anymore */ - - /* special case: if table exists, but was created implicitly ... */ - if (dest && dest->implicit) { - /* we make it explicit now, and simply return it. */ - dest->implicit = false; - return dest; - } - e_keyexists(ctx, keytok.lineno); - return 0; - } + /* if key exists: error out */ + toml_table_t *dest = 0; + if (check_key(tab, newkey, 0, 0, &dest)) { + xfree(newkey); /* don't need this anymore */ - /* create a new table entry */ - int n = tab->ntab; - toml_table_t** base; - if (0 == (base = (toml_table_t**) expand_ptrarr((void**)tab->tab, n))) { - xfree(newkey); - e_outofmemory(ctx, FLINE); - return 0; - } - tab->tab = base; - - if (0 == (base[n] = (toml_table_t*) CALLOC(1, sizeof(*base[n])))) { - xfree(newkey); - e_outofmemory(ctx, FLINE); - return 0; - } - dest = tab->tab[tab->ntab++]; - - /* save the key in the new table struct */ - dest->key = newkey; - return dest; + /* special case: if table exists, but was created implicitly ... */ + if (dest && dest->implicit) { + /* we make it explicit now, and simply return it. */ + dest->implicit = false; + return dest; + } + e_keyexists(ctx, keytok.lineno); + return 0; + } + + /* create a new table entry */ + int n = tab->ntab; + toml_table_t **base; + if (0 == (base = (toml_table_t **)expand_ptrarr((void **)tab->tab, n))) { + xfree(newkey); + e_outofmemory(ctx, FLINE); + return 0; + } + tab->tab = base; + + if (0 == (base[n] = (toml_table_t *)CALLOC(1, sizeof(*base[n])))) { + xfree(newkey); + e_outofmemory(ctx, FLINE); + return 0; + } + dest = tab->tab[tab->ntab++]; + + /* save the key in the new table struct */ + dest->key = newkey; + return dest; } - /* Create an array in the table. */ -static toml_array_t* create_keyarray_in_table(context_t* ctx, - toml_table_t* tab, - token_t keytok, - char kind) +static toml_array_t *create_keyarray_in_table(context_t *ctx, + toml_table_t *tab, + token_t keytok, + char kind) { - /* first, normalize the key to be used for lookup. - * remember to free it if we error out. - */ - char* newkey = normalize_key(ctx, keytok); - if (!newkey) return 0; - - /* if key exists: error out */ - if (key_kind(tab, newkey)) { - xfree(newkey); /* don't need this anymore */ - e_keyexists(ctx, keytok.lineno); - return 0; - } + /* first, normalize the key to be used for lookup. + * remember to free it if we error out. + */ + char *newkey = normalize_key(ctx, keytok); + if (!newkey) + return 0; - /* make a new array entry */ - int n = tab->narr; - toml_array_t** base; - if (0 == (base = (toml_array_t**) expand_ptrarr((void**)tab->arr, n))) { - xfree(newkey); - e_outofmemory(ctx, FLINE); - return 0; - } - tab->arr = base; - - if (0 == (base[n] = (toml_array_t*) CALLOC(1, sizeof(*base[n])))) { - xfree(newkey); - e_outofmemory(ctx, FLINE); - return 0; - } - toml_array_t* dest = tab->arr[tab->narr++]; + /* if key exists: error out */ + if (key_kind(tab, newkey)) { + xfree(newkey); /* don't need this anymore */ + e_keyexists(ctx, keytok.lineno); + return 0; + } - /* save the key in the new array struct */ - dest->key = newkey; - dest->kind = kind; - return dest; + /* make a new array entry */ + int n = tab->narr; + toml_array_t **base; + if (0 == (base = (toml_array_t **)expand_ptrarr((void **)tab->arr, n))) { + xfree(newkey); + e_outofmemory(ctx, FLINE); + return 0; + } + tab->arr = base; + + if (0 == (base[n] = (toml_array_t *)CALLOC(1, sizeof(*base[n])))) { + xfree(newkey); + e_outofmemory(ctx, FLINE); + return 0; + } + toml_array_t *dest = tab->arr[tab->narr++]; + + /* save the key in the new array struct */ + dest->key = newkey; + dest->kind = kind; + return dest; } -/* Create an array in an array +/* Create an array in an array */ -static toml_array_t* create_array_in_array(context_t* ctx, - toml_array_t* parent) +static toml_array_t *create_array_in_array(context_t *ctx, toml_array_t *parent) { - const int n = parent->nelem; - toml_array_t** base; - if (0 == (base = (toml_array_t**) expand_ptrarr((void**)parent->u.arr, n))) { - e_outofmemory(ctx, FLINE); - return 0; - } - parent->u.arr = base; - parent->nelem++; - - if (0 == (base[n] = (toml_array_t*) CALLOC(1, sizeof(*base[n])))) { - e_outofmemory(ctx, FLINE); - return 0; - } + const int n = parent->nelem; + toml_array_t **base; + if (0 == (base = (toml_array_t **)expand_ptrarr((void **)parent->u.arr, n))) { + e_outofmemory(ctx, FLINE); + return 0; + } + parent->u.arr = base; + parent->nelem++; - return parent->u.arr[n]; + if (0 == (base[n] = (toml_array_t *)CALLOC(1, sizeof(*base[n])))) { + e_outofmemory(ctx, FLINE); + return 0; + } + + return parent->u.arr[n]; } -/* Create a table in an array +/* Create a table in an array */ -static toml_table_t* create_table_in_array(context_t* ctx, - toml_array_t* parent) +static toml_table_t *create_table_in_array(context_t *ctx, toml_array_t *parent) { - int n = parent->nelem; - toml_table_t** base; - if (0 == (base = (toml_table_t**) expand_ptrarr((void**)parent->u.tab, n))) { - e_outofmemory(ctx, FLINE); - return 0; - } - parent->u.tab = base; - - if (0 == (base[n] = (toml_table_t*) CALLOC(1, sizeof(*base[n])))) { - e_outofmemory(ctx, FLINE); - return 0; - } + int n = parent->nelem; + toml_table_t **base; + if (0 == (base = (toml_table_t **)expand_ptrarr((void **)parent->u.tab, n))) { + e_outofmemory(ctx, FLINE); + return 0; + } + parent->u.tab = base; - return parent->u.tab[parent->nelem++]; + if (0 == (base[n] = (toml_table_t *)CALLOC(1, sizeof(*base[n])))) { + e_outofmemory(ctx, FLINE); + return 0; + } + + return parent->u.tab[parent->nelem++]; } - -static int skip_newlines(context_t* ctx, int isdotspecial) +static int skip_newlines(context_t *ctx, int isdotspecial) { - while (ctx->tok.tok == NEWLINE) { - if (next_token(ctx, isdotspecial)) return -1; - if (ctx->tok.eof) break; - } - return 0; + while (ctx->tok.tok == NEWLINE) { + if (next_token(ctx, isdotspecial)) + return -1; + if (ctx->tok.eof) + break; + } + return 0; } +static int parse_keyval(context_t *ctx, toml_table_t *tab); -static int parse_keyval(context_t* ctx, toml_table_t* tab); - -static inline int eat_token(context_t* ctx, tokentype_t typ, int isdotspecial, const char* fline) +static inline int eat_token(context_t *ctx, tokentype_t typ, int isdotspecial, const char *fline) { - if (ctx->tok.tok != typ) - return e_internal(ctx, fline); + if (ctx->tok.tok != typ) + return e_internal(ctx, fline); - if (next_token(ctx, isdotspecial)) - return -1; + if (next_token(ctx, isdotspecial)) + return -1; - return 0; + return 0; } - - /* We are at '{ ... }'. * Parse the table. */ -static int parse_table(context_t* ctx, toml_table_t* tab) +static int parse_table(context_t *ctx, toml_table_t *tab) { - if (eat_token(ctx, LBRACE, 1, FLINE)) - return -1; + if (eat_token(ctx, LBRACE, 1, FLINE)) + return -1; - for (;;) { - if (ctx->tok.tok == NEWLINE) - return e_syntax(ctx, ctx->tok.lineno, "newline not allowed in inline table"); + for (;;) { + if (ctx->tok.tok == NEWLINE) + return e_syntax(ctx, ctx->tok.lineno, "newline not allowed in inline table"); - /* until } */ - if (ctx->tok.tok == RBRACE) - break; + /* until } */ + if (ctx->tok.tok == RBRACE) + break; - if (ctx->tok.tok != STRING) - return e_syntax(ctx, ctx->tok.lineno, "expect a string"); + if (ctx->tok.tok != STRING) + return e_syntax(ctx, ctx->tok.lineno, "expect a string"); - if (parse_keyval(ctx, tab)) - return -1; - - if (ctx->tok.tok == NEWLINE) - return e_syntax(ctx, ctx->tok.lineno, "newline not allowed in inline table"); + if (parse_keyval(ctx, tab)) + return -1; - /* on comma, continue to scan for next keyval */ - if (ctx->tok.tok == COMMA) { - if (eat_token(ctx, COMMA, 1, FLINE)) - return -1; - continue; - } - break; - } + if (ctx->tok.tok == NEWLINE) + return e_syntax(ctx, ctx->tok.lineno, "newline not allowed in inline table"); - if (eat_token(ctx, RBRACE, 1, FLINE)) - return -1; - return 0; + /* on comma, continue to scan for next keyval */ + if (ctx->tok.tok == COMMA) { + if (eat_token(ctx, COMMA, 1, FLINE)) + return -1; + continue; + } + break; + } + + if (eat_token(ctx, RBRACE, 1, FLINE)) + return -1; + return 0; } -static int valtype(const char* val) +static int valtype(const char *val) { - toml_timestamp_t ts; - if (*val == '\'' || *val == '"') return 's'; - if (0 == toml_rtob(val, 0)) return 'b'; - if (0 == toml_rtoi(val, 0)) return 'i'; - if (0 == toml_rtod(val, 0)) return 'd'; - if (0 == toml_rtots(val, &ts)) { - if (ts.year && ts.hour) return 'T'; /* timestamp */ - if (ts.year) return 'D'; /* date */ - return 't'; /* time */ - } - return 'u'; /* unknown */ + toml_timestamp_t ts; + if (*val == '\'' || *val == '"') + return 's'; + if (0 == toml_rtob(val, 0)) + return 'b'; + if (0 == toml_rtoi(val, 0)) + return 'i'; + if (0 == toml_rtod(val, 0)) + return 'd'; + if (0 == toml_rtots(val, &ts)) { + if (ts.year && ts.hour) + return 'T'; /* timestamp */ + if (ts.year) + return 'D'; /* date */ + return 't'; /* time */ + } + return 'u'; /* unknown */ } - /* We are at '[...]' */ -static int parse_array(context_t* ctx, toml_array_t* arr) +static int parse_array(context_t *ctx, toml_array_t *arr) { - if (eat_token(ctx, LBRACKET, 0, FLINE)) return -1; - - for (;;) { - if (skip_newlines(ctx, 0)) return -1; - - /* until ] */ - if (ctx->tok.tok == RBRACKET) break; + if (eat_token(ctx, LBRACKET, 0, FLINE)) + return -1; - switch (ctx->tok.tok) { - case STRING: - { - char* val = ctx->tok.ptr; - int vlen = ctx->tok.len; + for (;;) { + if (skip_newlines(ctx, 0)) + return -1; - /* set array kind if this will be the first entry */ - if (arr->kind == 0) arr->kind = 'v'; - /* check array kind */ - if (arr->kind != 'v') - return e_syntax(ctx, ctx->tok.lineno, "a string array can only contain strings"); + /* until ] */ + if (ctx->tok.tok == RBRACKET) + break; - /* make a new value in array */ - char** tmp = (char**) expand_ptrarr((void**)arr->u.val, arr->nelem); - if (!tmp) - return e_outofmemory(ctx, FLINE); - - arr->u.val = tmp; - if (! (val = STRNDUP(val, vlen))) - return e_outofmemory(ctx, FLINE); + switch (ctx->tok.tok) { + case STRING: { + char *val = ctx->tok.ptr; + int vlen = ctx->tok.len; - arr->u.val[arr->nelem++] = val; + /* set array kind if this will be the first entry */ + if (arr->kind == 0) + arr->kind = 'v'; + /* check array kind */ + if (arr->kind != 'v') + return e_syntax(ctx, ctx->tok.lineno, "a string array can only contain strings"); - /* set array type if this is the first entry, or check that the types matched. */ - if (arr->nelem == 1) - arr->type = valtype(arr->u.val[0]); - else if (arr->type != valtype(val)) { - return e_syntax(ctx, ctx->tok.lineno, - "array type mismatch while processing array of values"); - } + /* make a new value in array */ + char **tmp = (char **)expand_ptrarr((void **)arr->u.val, arr->nelem); + if (!tmp) + return e_outofmemory(ctx, FLINE); - if (eat_token(ctx, STRING, 0, FLINE)) return -1; - break; - } + arr->u.val = tmp; + if (!(val = STRNDUP(val, vlen))) + return e_outofmemory(ctx, FLINE); - case LBRACKET: - { /* [ [array], [array] ... ] */ - /* set the array kind if this will be the first entry */ - if (arr->kind == 0) arr->kind = 'a'; - /* check array kind */ - if (arr->kind != 'a') { - return e_syntax(ctx, ctx->tok.lineno, - "array type mismatch while processing array of arrays"); - } - toml_array_t* subarr = create_array_in_array(ctx, arr); - if (!subarr) return -1; - if (parse_array(ctx, subarr)) return -1; - break; - } + arr->u.val[arr->nelem++] = val; - case LBRACE: - { /* [ {table}, {table} ... ] */ - /* set the array kind if this will be the first entry */ - if (arr->kind == 0) arr->kind = 't'; - /* check array kind */ - if (arr->kind != 't') { - return e_syntax(ctx, ctx->tok.lineno, - "array type mismatch while processing array of tables"); - } - toml_table_t* subtab = create_table_in_array(ctx, arr); - if (!subtab) return -1; - if (parse_table(ctx, subtab)) return -1; - break; - } - - default: - return e_syntax(ctx, ctx->tok.lineno, "syntax error"); - } + /* set array type if this is the first entry, or check that the types matched. */ + if (arr->nelem == 1) + arr->type = valtype(arr->u.val[0]); + else if (arr->type != valtype(val)) { + return e_syntax(ctx, + ctx->tok.lineno, + "array type mismatch while processing array of values"); + } - if (skip_newlines(ctx, 0)) return -1; + if (eat_token(ctx, STRING, 0, FLINE)) + return -1; + break; + } - /* on comma, continue to scan for next element */ - if (ctx->tok.tok == COMMA) { - if (eat_token(ctx, COMMA, 0, FLINE)) return -1; - continue; - } - break; - } + case LBRACKET: { /* [ [array], [array] ... ] */ + /* set the array kind if this will be the first entry */ + if (arr->kind == 0) + arr->kind = 'a'; + /* check array kind */ + if (arr->kind != 'a') { + return e_syntax(ctx, + ctx->tok.lineno, + "array type mismatch while processing array of arrays"); + } + toml_array_t *subarr = create_array_in_array(ctx, arr); + if (!subarr) + return -1; + if (parse_array(ctx, subarr)) + return -1; + break; + } - if (eat_token(ctx, RBRACKET, 1, FLINE)) return -1; - return 0; + case LBRACE: { /* [ {table}, {table} ... ] */ + /* set the array kind if this will be the first entry */ + if (arr->kind == 0) + arr->kind = 't'; + /* check array kind */ + if (arr->kind != 't') { + return e_syntax(ctx, + ctx->tok.lineno, + "array type mismatch while processing array of tables"); + } + toml_table_t *subtab = create_table_in_array(ctx, arr); + if (!subtab) + return -1; + if (parse_table(ctx, subtab)) + return -1; + break; + } + + default: + return e_syntax(ctx, ctx->tok.lineno, "syntax error"); + } + + if (skip_newlines(ctx, 0)) + return -1; + + /* on comma, continue to scan for next element */ + if (ctx->tok.tok == COMMA) { + if (eat_token(ctx, COMMA, 0, FLINE)) + return -1; + continue; + } + break; + } + + if (eat_token(ctx, RBRACKET, 1, FLINE)) + return -1; + return 0; } - /* handle lines like these: key = "value" key = [ array ] key = { table } */ -static int parse_keyval(context_t* ctx, toml_table_t* tab) +static int parse_keyval(context_t *ctx, toml_table_t *tab) { - token_t key = ctx->tok; - if (eat_token(ctx, STRING, 1, FLINE)) return -1; - - if (ctx->tok.tok == DOT) { - /* handle inline dotted key. - e.g. - physical.color = "orange" - physical.shape = "round" - */ - toml_table_t* subtab = 0; - { - char* subtabstr = normalize_key(ctx, key); - if (!subtabstr) return -1; + token_t key = ctx->tok; + if (eat_token(ctx, STRING, 1, FLINE)) + return -1; - subtab = toml_table_in(tab, subtabstr); - xfree(subtabstr); - } - if (!subtab) { - subtab = create_keytable_in_table(ctx, tab, key); - if (!subtab) return -1; - } - if (next_token(ctx, 1)) return -1; - if (parse_keyval(ctx, subtab)) return -1; - return 0; - } + if (ctx->tok.tok == DOT) { + /* handle inline dotted key. + e.g. + physical.color = "orange" + physical.shape = "round" + */ + toml_table_t *subtab = 0; + { + char *subtabstr = normalize_key(ctx, key); + if (!subtabstr) + return -1; - if (ctx->tok.tok != EQUAL) { - return e_syntax(ctx, ctx->tok.lineno, "missing ="); - } + subtab = toml_table_in(tab, subtabstr); + xfree(subtabstr); + } + if (!subtab) { + subtab = create_keytable_in_table(ctx, tab, key); + if (!subtab) + return -1; + } + if (next_token(ctx, 1)) + return -1; + if (parse_keyval(ctx, subtab)) + return -1; + return 0; + } - if (next_token(ctx, 0)) return -1; + if (ctx->tok.tok != EQUAL) { + return e_syntax(ctx, ctx->tok.lineno, "missing ="); + } - switch (ctx->tok.tok) { - case STRING: - { /* key = "value" */ - toml_keyval_t* keyval = create_keyval_in_table(ctx, tab, key); - if (!keyval) return -1; - token_t val = ctx->tok; - - assert(keyval->val == 0); - if (! (keyval->val = STRNDUP(val.ptr, val.len))) - return e_outofmemory(ctx, FLINE); + if (next_token(ctx, 0)) + return -1; - if (next_token(ctx, 1)) return -1; - - return 0; - } + switch (ctx->tok.tok) { + case STRING: { /* key = "value" */ + toml_keyval_t *keyval = create_keyval_in_table(ctx, tab, key); + if (!keyval) + return -1; + token_t val = ctx->tok; - case LBRACKET: - { /* key = [ array ] */ - toml_array_t* arr = create_keyarray_in_table(ctx, tab, key, 0); - if (!arr) return -1; - if (parse_array(ctx, arr)) return -1; - return 0; - } + assert(keyval->val == 0); + if (!(keyval->val = STRNDUP(val.ptr, val.len))) + return e_outofmemory(ctx, FLINE); - case LBRACE: - { /* key = { table } */ - toml_table_t* nxttab = create_keytable_in_table(ctx, tab, key); - if (!nxttab) return -1; - if (parse_table(ctx, nxttab)) return -1; - return 0; - } + if (next_token(ctx, 1)) + return -1; - default: - return e_syntax(ctx, ctx->tok.lineno, "syntax error"); - } - return 0; + return 0; + } + + case LBRACKET: { /* key = [ array ] */ + toml_array_t *arr = create_keyarray_in_table(ctx, tab, key, 0); + if (!arr) + return -1; + if (parse_array(ctx, arr)) + return -1; + return 0; + } + + case LBRACE: { /* key = { table } */ + toml_table_t *nxttab = create_keytable_in_table(ctx, tab, key); + if (!nxttab) + return -1; + if (parse_table(ctx, nxttab)) + return -1; + return 0; + } + + default: + return e_syntax(ctx, ctx->tok.lineno, "syntax error"); + } + return 0; } - typedef struct tabpath_t tabpath_t; struct tabpath_t { - int cnt; - token_t key[10]; + int cnt; + token_t key[10]; }; /* at [x.y.z] or [[x.y.z]] * Scan forward and fill tabpath until it enters ] or ]] * There will be at least one entry on return. */ -static int fill_tabpath(context_t* ctx) +static int fill_tabpath(context_t *ctx) { - int lineno = ctx->tok.lineno; - int i; - - /* clear tpath */ - for (i = 0; i < ctx->tpath.top; i++) { - char** p = &ctx->tpath.key[i]; - xfree(*p); - *p = 0; - } - ctx->tpath.top = 0; - - for (;;) { - if (ctx->tpath.top >= 10) - return e_syntax(ctx, lineno, "table path is too deep; max allowed is 10."); + int lineno = ctx->tok.lineno; + int i; - if (ctx->tok.tok != STRING) - return e_syntax(ctx, lineno, "invalid or missing key"); + /* clear tpath */ + for (i = 0; i < ctx->tpath.top; i++) { + char **p = &ctx->tpath.key[i]; + xfree(*p); + *p = 0; + } + ctx->tpath.top = 0; - char* key = normalize_key(ctx, ctx->tok); - if (!key) return -1; - ctx->tpath.tok[ctx->tpath.top] = ctx->tok; - ctx->tpath.key[ctx->tpath.top] = key; - ctx->tpath.top++; - - if (next_token(ctx, 1)) return -1; + for (;;) { + if (ctx->tpath.top >= 10) + return e_syntax(ctx, lineno, "table path is too deep; max allowed is 10."); - if (ctx->tok.tok == RBRACKET) break; + if (ctx->tok.tok != STRING) + return e_syntax(ctx, lineno, "invalid or missing key"); - if (ctx->tok.tok != DOT) - return e_syntax(ctx, lineno, "invalid key"); + char *key = normalize_key(ctx, ctx->tok); + if (!key) + return -1; + ctx->tpath.tok[ctx->tpath.top] = ctx->tok; + ctx->tpath.key[ctx->tpath.top] = key; + ctx->tpath.top++; - if (next_token(ctx, 1)) return -1; - } + if (next_token(ctx, 1)) + return -1; - if (ctx->tpath.top <= 0) - return e_syntax(ctx, lineno, "empty table selector"); + if (ctx->tok.tok == RBRACKET) + break; - return 0; + if (ctx->tok.tok != DOT) + return e_syntax(ctx, lineno, "invalid key"); + + if (next_token(ctx, 1)) + return -1; + } + + if (ctx->tpath.top <= 0) + return e_syntax(ctx, lineno, "empty table selector"); + + return 0; } - /* Walk tabpath from the root, and create new tables on the way. * Sets ctx->curtab to the final table. */ -static int walk_tabpath(context_t* ctx) +static int walk_tabpath(context_t *ctx) { - /* start from root */ - toml_table_t* curtab = ctx->root; - - for (int i = 0; i < ctx->tpath.top; i++) { - const char* key = ctx->tpath.key[i]; + /* start from root */ + toml_table_t *curtab = ctx->root; - toml_keyval_t* nextval = 0; - toml_array_t* nextarr = 0; - toml_table_t* nexttab = 0; - switch (check_key(curtab, key, &nextval, &nextarr, &nexttab)) { - case 't': - /* found a table. nexttab is where we will go next. */ - break; + for (int i = 0; i < ctx->tpath.top; i++) { + const char *key = ctx->tpath.key[i]; - case 'a': - /* found an array. nexttab is the last table in the array. */ - if (nextarr->kind != 't') - return e_internal(ctx, FLINE); + toml_keyval_t *nextval = 0; + toml_array_t *nextarr = 0; + toml_table_t *nexttab = 0; + switch (check_key(curtab, key, &nextval, &nextarr, &nexttab)) { + case 't': + /* found a table. nexttab is where we will go next. */ + break; - if (nextarr->nelem == 0) - return e_internal(ctx, FLINE); + case 'a': + /* found an array. nexttab is the last table in the array. */ + if (nextarr->kind != 't') + return e_internal(ctx, FLINE); - nexttab = nextarr->u.tab[nextarr->nelem-1]; - break; + if (nextarr->nelem == 0) + return e_internal(ctx, FLINE); - case 'v': - return e_keyexists(ctx, ctx->tpath.tok[i].lineno); + nexttab = nextarr->u.tab[nextarr->nelem - 1]; + break; - default: - { /* Not found. Let's create an implicit table. */ - int n = curtab->ntab; - toml_table_t** base = (toml_table_t**) expand_ptrarr((void**)curtab->tab, n); - if (0 == base) - return e_outofmemory(ctx, FLINE); + case 'v': + return e_keyexists(ctx, ctx->tpath.tok[i].lineno); - curtab->tab = base; - - if (0 == (base[n] = (toml_table_t*) CALLOC(1, sizeof(*base[n])))) - return e_outofmemory(ctx, FLINE); - - if (0 == (base[n]->key = STRDUP(key))) - return e_outofmemory(ctx, FLINE); - - nexttab = curtab->tab[curtab->ntab++]; - - /* tabs created by walk_tabpath are considered implicit */ - nexttab->implicit = true; - } - break; - } + default: { /* Not found. Let's create an implicit table. */ + int n = curtab->ntab; + toml_table_t **base = (toml_table_t **)expand_ptrarr((void **)curtab->tab, n); + if (0 == base) + return e_outofmemory(ctx, FLINE); - /* switch to next tab */ - curtab = nexttab; - } + curtab->tab = base; - /* save it */ - ctx->curtab = curtab; + if (0 == (base[n] = (toml_table_t *)CALLOC(1, sizeof(*base[n])))) + return e_outofmemory(ctx, FLINE); - return 0; + if (0 == (base[n]->key = STRDUP(key))) + return e_outofmemory(ctx, FLINE); + + nexttab = curtab->tab[curtab->ntab++]; + + /* tabs created by walk_tabpath are considered implicit */ + nexttab->implicit = true; + } break; + } + + /* switch to next tab */ + curtab = nexttab; + } + + /* save it */ + ctx->curtab = curtab; + + return 0; } - /* handle lines like [x.y.z] or [[x.y.z]] */ -static int parse_select(context_t* ctx) +static int parse_select(context_t *ctx) { - assert(ctx->tok.tok == LBRACKET); - - /* true if [[ */ - int llb = (ctx->tok.ptr + 1 < ctx->stop && ctx->tok.ptr[1] == '['); - /* need to detect '[[' on our own because next_token() will skip whitespace, - and '[ [' would be taken as '[[', which is wrong. */ + assert(ctx->tok.tok == LBRACKET); - /* eat [ or [[ */ - if (eat_token(ctx, LBRACKET, 1, FLINE)) return -1; - if (llb) { - assert(ctx->tok.tok == LBRACKET); - if (eat_token(ctx, LBRACKET, 1, FLINE)) return -1; - } + /* true if [[ */ + int llb = (ctx->tok.ptr + 1 < ctx->stop && ctx->tok.ptr[1] == '['); + /* need to detect '[[' on our own because next_token() will skip whitespace, + and '[ [' would be taken as '[[', which is wrong. */ - if (fill_tabpath(ctx)) return -1; + /* eat [ or [[ */ + if (eat_token(ctx, LBRACKET, 1, FLINE)) + return -1; + if (llb) { + assert(ctx->tok.tok == LBRACKET); + if (eat_token(ctx, LBRACKET, 1, FLINE)) + return -1; + } - /* For [x.y.z] or [[x.y.z]], remove z from tpath. - */ - token_t z = ctx->tpath.tok[ctx->tpath.top-1]; - xfree(ctx->tpath.key[ctx->tpath.top-1]); - ctx->tpath.top--; + if (fill_tabpath(ctx)) + return -1; - /* set up ctx->curtab */ - if (walk_tabpath(ctx)) return -1; + /* For [x.y.z] or [[x.y.z]], remove z from tpath. + */ + token_t z = ctx->tpath.tok[ctx->tpath.top - 1]; + xfree(ctx->tpath.key[ctx->tpath.top - 1]); + ctx->tpath.top--; - if (! llb) { - /* [x.y.z] -> create z = {} in x.y */ - toml_table_t* curtab = create_keytable_in_table(ctx, ctx->curtab, z); - if (!curtab) return -1; - ctx->curtab = curtab; - } else { - /* [[x.y.z]] -> create z = [] in x.y */ - toml_array_t* arr = 0; - { - char* zstr = normalize_key(ctx, z); - if (!zstr) return -1; - arr = toml_array_in(ctx->curtab, zstr); - xfree(zstr); - } - if (!arr) { - arr = create_keyarray_in_table(ctx, ctx->curtab, z, 't'); - if (!arr) return -1; - } - if (arr->kind != 't') - return e_syntax(ctx, z.lineno, "array mismatch"); + /* set up ctx->curtab */ + if (walk_tabpath(ctx)) + return -1; - /* add to z[] */ - toml_table_t* dest; - { - int n = arr->nelem; - toml_table_t** base = (toml_table_t**) expand_ptrarr((void**)arr->u.tab, n); - if (0 == base) - return e_outofmemory(ctx, FLINE); + if (!llb) { + /* [x.y.z] -> create z = {} in x.y */ + toml_table_t *curtab = create_keytable_in_table(ctx, ctx->curtab, z); + if (!curtab) + return -1; + ctx->curtab = curtab; + } else { + /* [[x.y.z]] -> create z = [] in x.y */ + toml_array_t *arr = 0; + { + char *zstr = normalize_key(ctx, z); + if (!zstr) + return -1; + arr = toml_array_in(ctx->curtab, zstr); + xfree(zstr); + } + if (!arr) { + arr = create_keyarray_in_table(ctx, ctx->curtab, z, 't'); + if (!arr) + return -1; + } + if (arr->kind != 't') + return e_syntax(ctx, z.lineno, "array mismatch"); - arr->u.tab = base; - - if (0 == (base[n] = CALLOC(1, sizeof(*base[n])))) - return e_outofmemory(ctx, FLINE); - - if (0 == (base[n]->key = STRDUP("__anon__"))) - return e_outofmemory(ctx, FLINE); - - dest = arr->u.tab[arr->nelem++]; - } + /* add to z[] */ + toml_table_t *dest; + { + int n = arr->nelem; + toml_table_t **base = (toml_table_t **)expand_ptrarr((void **)arr->u.tab, n); + if (0 == base) + return e_outofmemory(ctx, FLINE); - ctx->curtab = dest; - } + arr->u.tab = base; - if (ctx->tok.tok != RBRACKET) { - return e_syntax(ctx, ctx->tok.lineno, "expects ]"); - } - if (llb) { - if (! (ctx->tok.ptr + 1 < ctx->stop && ctx->tok.ptr[1] == ']')) { - return e_syntax(ctx, ctx->tok.lineno, "expects ]]"); - } - if (eat_token(ctx, RBRACKET, 1, FLINE)) return -1; - } - - if (eat_token(ctx, RBRACKET, 1, FLINE)) - return -1; - - if (ctx->tok.tok != NEWLINE) - return e_syntax(ctx, ctx->tok.lineno, "extra chars after ] or ]]"); + if (0 == (base[n] = CALLOC(1, sizeof(*base[n])))) + return e_outofmemory(ctx, FLINE); - return 0; + if (0 == (base[n]->key = STRDUP("__anon__"))) + return e_outofmemory(ctx, FLINE); + + dest = arr->u.tab[arr->nelem++]; + } + + ctx->curtab = dest; + } + + if (ctx->tok.tok != RBRACKET) { + return e_syntax(ctx, ctx->tok.lineno, "expects ]"); + } + if (llb) { + if (!(ctx->tok.ptr + 1 < ctx->stop && ctx->tok.ptr[1] == ']')) { + return e_syntax(ctx, ctx->tok.lineno, "expects ]]"); + } + if (eat_token(ctx, RBRACKET, 1, FLINE)) + return -1; + } + + if (eat_token(ctx, RBRACKET, 1, FLINE)) + return -1; + + if (ctx->tok.tok != NEWLINE) + return e_syntax(ctx, ctx->tok.lineno, "extra chars after ] or ]]"); + + return 0; } - - - -toml_table_t* toml_parse(char* conf, - char* errbuf, - int errbufsz) +toml_table_t *toml_parse(char *conf, char *errbuf, int errbufsz) { - context_t ctx; + context_t ctx; - // clear errbuf - if (errbufsz <= 0) errbufsz = 0; - if (errbufsz > 0) errbuf[0] = 0; + // clear errbuf + if (errbufsz <= 0) + errbufsz = 0; + if (errbufsz > 0) + errbuf[0] = 0; - // init context - memset(&ctx, 0, sizeof(ctx)); - ctx.start = conf; - ctx.stop = ctx.start + strlen(conf); - ctx.errbuf = errbuf; - ctx.errbufsz = errbufsz; + // init context + memset(&ctx, 0, sizeof(ctx)); + ctx.start = conf; + ctx.stop = ctx.start + strlen(conf); + ctx.errbuf = errbuf; + ctx.errbufsz = errbufsz; - // start with an artificial newline of length 0 - ctx.tok.tok = NEWLINE; - ctx.tok.lineno = 1; - ctx.tok.ptr = conf; - ctx.tok.len = 0; + // start with an artificial newline of length 0 + ctx.tok.tok = NEWLINE; + ctx.tok.lineno = 1; + ctx.tok.ptr = conf; + ctx.tok.len = 0; - // make a root table - if (0 == (ctx.root = CALLOC(1, sizeof(*ctx.root)))) { - e_outofmemory(&ctx, FLINE); - // Do not goto fail, root table not set up yet - return 0; - } + // make a root table + if (0 == (ctx.root = CALLOC(1, sizeof(*ctx.root)))) { + e_outofmemory(&ctx, FLINE); + // Do not goto fail, root table not set up yet + return 0; + } - // set root as default table - ctx.curtab = ctx.root; + // set root as default table + ctx.curtab = ctx.root; - /* Scan forward until EOF */ - for (token_t tok = ctx.tok; ! tok.eof ; tok = ctx.tok) { - switch (tok.tok) { - - case NEWLINE: - if (next_token(&ctx, 1)) goto fail; - break; - - case STRING: - if (parse_keyval(&ctx, ctx.curtab)) goto fail; - - if (ctx.tok.tok != NEWLINE) { - e_syntax(&ctx, ctx.tok.lineno, "extra chars after value"); - goto fail; - } + /* Scan forward until EOF */ + for (token_t tok = ctx.tok; !tok.eof; tok = ctx.tok) { + switch (tok.tok) { - if (eat_token(&ctx, NEWLINE, 1, FLINE)) goto fail; - break; - - case LBRACKET: /* [ x.y.z ] or [[ x.y.z ]] */ - if (parse_select(&ctx)) goto fail; - break; - - default: - e_syntax(&ctx, tok.lineno, "syntax error"); - goto fail; - } - } + case NEWLINE: + if (next_token(&ctx, 1)) + goto fail; + break; - /* success */ - for (int i = 0; i < ctx.tpath.top; i++) xfree(ctx.tpath.key[i]); - return ctx.root; + case STRING: + if (parse_keyval(&ctx, ctx.curtab)) + goto fail; + + if (ctx.tok.tok != NEWLINE) { + e_syntax(&ctx, ctx.tok.lineno, "extra chars after value"); + goto fail; + } + + if (eat_token(&ctx, NEWLINE, 1, FLINE)) + goto fail; + break; + + case LBRACKET: /* [ x.y.z ] or [[ x.y.z ]] */ + if (parse_select(&ctx)) + goto fail; + break; + + default: + e_syntax(&ctx, tok.lineno, "syntax error"); + goto fail; + } + } + + /* success */ + for (int i = 0; i < ctx.tpath.top; i++) + xfree(ctx.tpath.key[i]); + return ctx.root; fail: - // Something bad has happened. Free resources and return error. - for (int i = 0; i < ctx.tpath.top; i++) xfree(ctx.tpath.key[i]); - toml_free(ctx.root); - return 0; + // Something bad has happened. Free resources and return error. + for (int i = 0; i < ctx.tpath.top; i++) + xfree(ctx.tpath.key[i]); + toml_free(ctx.root); + return 0; } - -toml_table_t* toml_parse_file(FILE* fp, - char* errbuf, - int errbufsz) +toml_table_t *toml_parse_file(FILE *fp, char *errbuf, int errbufsz) { - int bufsz = 0; - char* buf = 0; - int off = 0; + int bufsz = 0; + char *buf = 0; + int off = 0; - /* read from fp into buf */ - while (! feof(fp)) { + /* read from fp into buf */ + while (!feof(fp)) { - if (off == bufsz) { - int xsz = bufsz + 1000; - char* x = expand(buf, bufsz, xsz); - if (!x) { - snprintf(errbuf, errbufsz, "out of memory"); - xfree(buf); - return 0; - } - buf = x; - bufsz = xsz; - } - - errno = 0; - int n = fread(buf + off, 1, bufsz - off, fp); - if (ferror(fp)) { - snprintf(errbuf, errbufsz, "%s", - errno ? strerror(errno) : "Error reading file"); - xfree(buf); - return 0; - } - off += n; - } + if (off == bufsz) { + int xsz = bufsz + 1000; + char *x = expand(buf, bufsz, xsz); + if (!x) { + snprintf(errbuf, errbufsz, "out of memory"); + xfree(buf); + return 0; + } + buf = x; + bufsz = xsz; + } - /* tag on a NUL to cap the string */ - if (off == bufsz) { - int xsz = bufsz + 1; - char* x = expand(buf, bufsz, xsz); - if (!x) { - snprintf(errbuf, errbufsz, "out of memory"); - xfree(buf); - return 0; - } - buf = x; - bufsz = xsz; - } - buf[off] = 0; + errno = 0; + int n = fread(buf + off, 1, bufsz - off, fp); + if (ferror(fp)) { + snprintf(errbuf, errbufsz, "%s", errno ? strerror(errno) : "Error reading file"); + xfree(buf); + return 0; + } + off += n; + } - /* parse it, cleanup and finish */ - toml_table_t* ret = toml_parse(buf, errbuf, errbufsz); - xfree(buf); - return ret; + /* tag on a NUL to cap the string */ + if (off == bufsz) { + int xsz = bufsz + 1; + char *x = expand(buf, bufsz, xsz); + if (!x) { + snprintf(errbuf, errbufsz, "out of memory"); + xfree(buf); + return 0; + } + buf = x; + bufsz = xsz; + } + buf[off] = 0; + + /* parse it, cleanup and finish */ + toml_table_t *ret = toml_parse(buf, errbuf, errbufsz); + xfree(buf); + return ret; } - -static void xfree_kval(toml_keyval_t* p) +static void xfree_kval(toml_keyval_t *p) { - if (!p) return; - xfree(p->key); - xfree(p->val); - xfree(p); + if (!p) + return; + xfree(p->key); + xfree(p->val); + xfree(p); } -static void xfree_tab(toml_table_t* p); +static void xfree_tab(toml_table_t *p); -static void xfree_arr(toml_array_t* p) +static void xfree_arr(toml_array_t *p) { - if (!p) return; + if (!p) + return; - xfree(p->key); - switch (p->kind) { - case 'v': - for (int i = 0; i < p->nelem; i++) xfree(p->u.val[i]); - xfree(p->u.val); - break; + xfree(p->key); + switch (p->kind) { + case 'v': + for (int i = 0; i < p->nelem; i++) + xfree(p->u.val[i]); + xfree(p->u.val); + break; - case 'a': - for (int i = 0; i < p->nelem; i++) xfree_arr(p->u.arr[i]); - xfree(p->u.arr); - break; + case 'a': + for (int i = 0; i < p->nelem; i++) + xfree_arr(p->u.arr[i]); + xfree(p->u.arr); + break; - case 't': - for (int i = 0; i < p->nelem; i++) xfree_tab(p->u.tab[i]); - xfree(p->u.tab); - break; - } + case 't': + for (int i = 0; i < p->nelem; i++) + xfree_tab(p->u.tab[i]); + xfree(p->u.tab); + break; + } - xfree(p); + xfree(p); } - -static void xfree_tab(toml_table_t* p) +static void xfree_tab(toml_table_t *p) { - int i; - - if (!p) return; - - xfree(p->key); - - for (i = 0; i < p->nkval; i++) xfree_kval(p->kval[i]); - xfree(p->kval); + int i; - for (i = 0; i < p->narr; i++) xfree_arr(p->arr[i]); - xfree(p->arr); + if (!p) + return; - for (i = 0; i < p->ntab; i++) xfree_tab(p->tab[i]); - xfree(p->tab); + xfree(p->key); - xfree(p); + for (i = 0; i < p->nkval; i++) + xfree_kval(p->kval[i]); + xfree(p->kval); + + for (i = 0; i < p->narr; i++) + xfree_arr(p->arr[i]); + xfree(p->arr); + + for (i = 0; i < p->ntab; i++) + xfree_tab(p->tab[i]); + xfree(p->tab); + + xfree(p); } - -void toml_free(toml_table_t* tab) +void toml_free(toml_table_t *tab) { - xfree_tab(tab); + xfree_tab(tab); } - -static void set_token(context_t* ctx, tokentype_t tok, int lineno, char* ptr, int len) +static void set_token(context_t *ctx, tokentype_t tok, int lineno, char *ptr, int len) { - token_t t; - t.tok = tok; - t.lineno = lineno; - t.ptr = ptr; - t.len = len; - t.eof = 0; - ctx->tok = t; + token_t t; + t.tok = tok; + t.lineno = lineno; + t.ptr = ptr; + t.len = len; + t.eof = 0; + ctx->tok = t; } -static void set_eof(context_t* ctx, int lineno) +static void set_eof(context_t *ctx, int lineno) { - set_token(ctx, NEWLINE, lineno, ctx->stop, 0); - ctx->tok.eof = 1; + set_token(ctx, NEWLINE, lineno, ctx->stop, 0); + ctx->tok.eof = 1; } - /* Scan p for n digits compositing entirely of [0-9] */ -static int scan_digits(const char* p, int n) +static int scan_digits(const char *p, int n) { - int ret = 0; - for ( ; n > 0 && isdigit(*p); n--, p++) { - ret = 10 * ret + (*p - '0'); - } - return n ? -1 : ret; + int ret = 0; + for (; n > 0 && isdigit(*p); n--, p++) { + ret = 10 * ret + (*p - '0'); + } + return n ? -1 : ret; } -static int scan_date(const char* p, int* YY, int* MM, int* DD) +static int scan_date(const char *p, int *YY, int *MM, int *DD) { - int year, month, day; - year = scan_digits(p, 4); - month = (year >= 0 && p[4] == '-') ? scan_digits(p+5, 2) : -1; - day = (month >= 0 && p[7] == '-') ? scan_digits(p+8, 2) : -1; - if (YY) *YY = year; - if (MM) *MM = month; - if (DD) *DD = day; - return (year >= 0 && month >= 0 && day >= 0) ? 0 : -1; + int year, month, day; + year = scan_digits(p, 4); + month = (year >= 0 && p[4] == '-') ? scan_digits(p + 5, 2) : -1; + day = (month >= 0 && p[7] == '-') ? scan_digits(p + 8, 2) : -1; + if (YY) + *YY = year; + if (MM) + *MM = month; + if (DD) + *DD = day; + return (year >= 0 && month >= 0 && day >= 0) ? 0 : -1; } -static int scan_time(const char* p, int* hh, int* mm, int* ss) +static int scan_time(const char *p, int *hh, int *mm, int *ss) { - int hour, minute, second; - hour = scan_digits(p, 2); - minute = (hour >= 0 && p[2] == ':') ? scan_digits(p+3, 2) : -1; - second = (minute >= 0 && p[5] == ':') ? scan_digits(p+6, 2) : -1; - if (hh) *hh = hour; - if (mm) *mm = minute; - if (ss) *ss = second; - return (hour >= 0 && minute >= 0 && second >= 0) ? 0 : -1; -} - - -static int scan_string(context_t* ctx, char* p, int lineno, int dotisspecial) -{ - char* orig = p; - if (0 == strncmp(p, "'''", 3)) { - p = strstr(p + 3, "'''"); - if (0 == p) { - return e_syntax(ctx, lineno, "unterminated triple-s-quote"); - } - - set_token(ctx, STRING, lineno, orig, p + 3 - orig); - return 0; - } - - if (0 == strncmp(p, "\"\"\"", 3)) { - int hexreq = 0; /* #hex required */ - int escape = 0; - int qcnt = 0; /* count quote */ - for (p += 3; *p && qcnt < 3; p++) { - if (escape) { - escape = 0; - if (strchr("btnfr\"\\", *p)) continue; - if (*p == 'u') { hexreq = 4; continue; } - if (*p == 'U') { hexreq = 8; continue; } - if (p[strspn(p, " \t\r")] == '\n') continue; /* allow for line ending backslash */ - return e_syntax(ctx, lineno, "bad escape char"); - } - if (hexreq) { - hexreq--; - if (strchr("0123456789ABCDEF", *p)) continue; - return e_syntax(ctx, lineno, "expect hex char"); - } - if (*p == '\\') { escape = 1; continue; } - qcnt = (*p == '"') ? qcnt + 1 : 0; - } - if (qcnt != 3) { - return e_syntax(ctx, lineno, "unterminated triple-quote"); - } - - set_token(ctx, STRING, lineno, orig, p - orig); - return 0; - } - - if ('\'' == *p) { - for (p++; *p && *p != '\n' && *p != '\''; p++); - if (*p != '\'') { - return e_syntax(ctx, lineno, "unterminated s-quote"); - } - - set_token(ctx, STRING, lineno, orig, p + 1 - orig); - return 0; - } - - if ('\"' == *p) { - int hexreq = 0; /* #hex required */ - int escape = 0; - for (p++; *p; p++) { - if (escape) { - escape = 0; - if (strchr("btnfr\"\\", *p)) continue; - if (*p == 'u') { hexreq = 4; continue; } - if (*p == 'U') { hexreq = 8; continue; } - return e_syntax(ctx, lineno, "bad escape char"); - } - if (hexreq) { - hexreq--; - if (strchr("0123456789ABCDEF", *p)) continue; - return e_syntax(ctx, lineno, "expect hex char"); - } - if (*p == '\\') { escape = 1; continue; } - if (*p == '\n') break; - if (*p == '"') break; - } - if (*p != '"') { - return e_syntax(ctx, lineno, "unterminated quote"); - } - - set_token(ctx, STRING, lineno, orig, p + 1 - orig); - return 0; - } - - /* check for timestamp without quotes */ - if (0 == scan_date(p, 0, 0, 0) || 0 == scan_time(p, 0, 0, 0)) { - // forward thru the timestamp - for ( ; strchr("0123456789.:+-T Z", toupper(*p)); p++); - // squeeze out any spaces at end of string - for ( ; p[-1] == ' '; p--); - // tokenize - set_token(ctx, STRING, lineno, orig, p - orig); - return 0; - } - - /* literals */ - for ( ; *p && *p != '\n'; p++) { - int ch = *p; - if (ch == '.' && dotisspecial) break; - if ('A' <= ch && ch <= 'Z') continue; - if ('a' <= ch && ch <= 'z') continue; - if (strchr("0123456789+-_.", ch)) continue; - break; - } - - set_token(ctx, STRING, lineno, orig, p - orig); - return 0; + int hour, minute, second; + hour = scan_digits(p, 2); + minute = (hour >= 0 && p[2] == ':') ? scan_digits(p + 3, 2) : -1; + second = (minute >= 0 && p[5] == ':') ? scan_digits(p + 6, 2) : -1; + if (hh) + *hh = hour; + if (mm) + *mm = minute; + if (ss) + *ss = second; + return (hour >= 0 && minute >= 0 && second >= 0) ? 0 : -1; } - -static int next_token(context_t* ctx, int dotisspecial) +static int scan_string(context_t *ctx, char *p, int lineno, int dotisspecial) { - int lineno = ctx->tok.lineno; - char* p = ctx->tok.ptr; - int i; + char *orig = p; + if (0 == strncmp(p, "'''", 3)) { + p = strstr(p + 3, "'''"); + if (0 == p) { + return e_syntax(ctx, lineno, "unterminated triple-s-quote"); + } - /* eat this tok */ - for (i = 0; i < ctx->tok.len; i++) { - if (*p++ == '\n') - lineno++; - } + set_token(ctx, STRING, lineno, orig, p + 3 - orig); + return 0; + } - /* make next tok */ - while (p < ctx->stop) { - /* skip comment. stop just before the \n. */ - if (*p == '#') { - for (p++; p < ctx->stop && *p != '\n'; p++); - continue; - } + if (0 == strncmp(p, "\"\"\"", 3)) { + int hexreq = 0; /* #hex required */ + int escape = 0; + int qcnt = 0; /* count quote */ + for (p += 3; *p && qcnt < 3; p++) { + if (escape) { + escape = 0; + if (strchr("btnfr\"\\", *p)) + continue; + if (*p == 'u') { + hexreq = 4; + continue; + } + if (*p == 'U') { + hexreq = 8; + continue; + } + if (p[strspn(p, " \t\r")] == '\n') + continue; /* allow for line ending backslash */ + return e_syntax(ctx, lineno, "bad escape char"); + } + if (hexreq) { + hexreq--; + if (strchr("0123456789ABCDEF", *p)) + continue; + return e_syntax(ctx, lineno, "expect hex char"); + } + if (*p == '\\') { + escape = 1; + continue; + } + qcnt = (*p == '"') ? qcnt + 1 : 0; + } + if (qcnt != 3) { + return e_syntax(ctx, lineno, "unterminated triple-quote"); + } - if (dotisspecial && *p == '.') { - set_token(ctx, DOT, lineno, p, 1); - return 0; - } - - switch (*p) { - case ',': set_token(ctx, COMMA, lineno, p, 1); return 0; - case '=': set_token(ctx, EQUAL, lineno, p, 1); return 0; - case '{': set_token(ctx, LBRACE, lineno, p, 1); return 0; - case '}': set_token(ctx, RBRACE, lineno, p, 1); return 0; - case '[': set_token(ctx, LBRACKET, lineno, p, 1); return 0; - case ']': set_token(ctx, RBRACKET, lineno, p, 1); return 0; - case '\n': set_token(ctx, NEWLINE, lineno, p, 1); return 0; - case '\r': case ' ': case '\t': - /* ignore white spaces */ - p++; - continue; - } + set_token(ctx, STRING, lineno, orig, p - orig); + return 0; + } - return scan_string(ctx, p, lineno, dotisspecial); - } + if ('\'' == *p) { + for (p++; *p && *p != '\n' && *p != '\''; p++) + ; + if (*p != '\'') { + return e_syntax(ctx, lineno, "unterminated s-quote"); + } - set_eof(ctx, lineno); - return 0; + set_token(ctx, STRING, lineno, orig, p + 1 - orig); + return 0; + } + + if ('\"' == *p) { + int hexreq = 0; /* #hex required */ + int escape = 0; + for (p++; *p; p++) { + if (escape) { + escape = 0; + if (strchr("btnfr\"\\", *p)) + continue; + if (*p == 'u') { + hexreq = 4; + continue; + } + if (*p == 'U') { + hexreq = 8; + continue; + } + return e_syntax(ctx, lineno, "bad escape char"); + } + if (hexreq) { + hexreq--; + if (strchr("0123456789ABCDEF", *p)) + continue; + return e_syntax(ctx, lineno, "expect hex char"); + } + if (*p == '\\') { + escape = 1; + continue; + } + if (*p == '\n') + break; + if (*p == '"') + break; + } + if (*p != '"') { + return e_syntax(ctx, lineno, "unterminated quote"); + } + + set_token(ctx, STRING, lineno, orig, p + 1 - orig); + return 0; + } + + /* check for timestamp without quotes */ + if (0 == scan_date(p, 0, 0, 0) || 0 == scan_time(p, 0, 0, 0)) { + // forward thru the timestamp + for (; strchr("0123456789.:+-T Z", toupper(*p)); p++) + ; + // squeeze out any spaces at end of string + for (; p[-1] == ' '; p--) + ; + // tokenize + set_token(ctx, STRING, lineno, orig, p - orig); + return 0; + } + + /* literals */ + for (; *p && *p != '\n'; p++) { + int ch = *p; + if (ch == '.' && dotisspecial) + break; + if ('A' <= ch && ch <= 'Z') + continue; + if ('a' <= ch && ch <= 'z') + continue; + if (strchr("0123456789+-_.", ch)) + continue; + break; + } + + set_token(ctx, STRING, lineno, orig, p - orig); + return 0; } - -const char* toml_key_in(const toml_table_t* tab, int keyidx) +static int next_token(context_t *ctx, int dotisspecial) { - if (keyidx < tab->nkval) return tab->kval[keyidx]->key; - - keyidx -= tab->nkval; - if (keyidx < tab->narr) return tab->arr[keyidx]->key; - - keyidx -= tab->narr; - if (keyidx < tab->ntab) return tab->tab[keyidx]->key; + int lineno = ctx->tok.lineno; + char *p = ctx->tok.ptr; + int i; - return 0; + /* eat this tok */ + for (i = 0; i < ctx->tok.len; i++) { + if (*p++ == '\n') + lineno++; + } + + /* make next tok */ + while (p < ctx->stop) { + /* skip comment. stop just before the \n. */ + if (*p == '#') { + for (p++; p < ctx->stop && *p != '\n'; p++) + ; + continue; + } + + if (dotisspecial && *p == '.') { + set_token(ctx, DOT, lineno, p, 1); + return 0; + } + + switch (*p) { + case ',': + set_token(ctx, COMMA, lineno, p, 1); + return 0; + case '=': + set_token(ctx, EQUAL, lineno, p, 1); + return 0; + case '{': + set_token(ctx, LBRACE, lineno, p, 1); + return 0; + case '}': + set_token(ctx, RBRACE, lineno, p, 1); + return 0; + case '[': + set_token(ctx, LBRACKET, lineno, p, 1); + return 0; + case ']': + set_token(ctx, RBRACKET, lineno, p, 1); + return 0; + case '\n': + set_token(ctx, NEWLINE, lineno, p, 1); + return 0; + case '\r': + case ' ': + case '\t': + /* ignore white spaces */ + p++; + continue; + } + + return scan_string(ctx, p, lineno, dotisspecial); + } + + set_eof(ctx, lineno); + return 0; } -toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key) +const char *toml_key_in(const toml_table_t *tab, int keyidx) { - int i; - for (i = 0; i < tab->nkval; i++) { - if (0 == strcmp(key, tab->kval[i]->key)) - return tab->kval[i]->val; - } - return 0; + if (keyidx < tab->nkval) + return tab->kval[keyidx]->key; + + keyidx -= tab->nkval; + if (keyidx < tab->narr) + return tab->arr[keyidx]->key; + + keyidx -= tab->narr; + if (keyidx < tab->ntab) + return tab->tab[keyidx]->key; + + return 0; } -toml_array_t* toml_array_in(const toml_table_t* tab, const char* key) +toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key) { - int i; - for (i = 0; i < tab->narr; i++) { - if (0 == strcmp(key, tab->arr[i]->key)) - return tab->arr[i]; - } - return 0; + int i; + for (i = 0; i < tab->nkval; i++) { + if (0 == strcmp(key, tab->kval[i]->key)) + return tab->kval[i]->val; + } + return 0; } - -toml_table_t* toml_table_in(const toml_table_t* tab, const char* key) +toml_array_t *toml_array_in(const toml_table_t *tab, const char *key) { - int i; - for (i = 0; i < tab->ntab; i++) { - if (0 == strcmp(key, tab->tab[i]->key)) - return tab->tab[i]; - } - return 0; + int i; + for (i = 0; i < tab->narr; i++) { + if (0 == strcmp(key, tab->arr[i]->key)) + return tab->arr[i]; + } + return 0; } -toml_raw_t toml_raw_at(const toml_array_t* arr, int idx) +toml_table_t *toml_table_in(const toml_table_t *tab, const char *key) { - if (arr->kind != 'v') - return 0; - if (! (0 <= idx && idx < arr->nelem)) - return 0; - return arr->u.val[idx]; + int i; + for (i = 0; i < tab->ntab; i++) { + if (0 == strcmp(key, tab->tab[i]->key)) + return tab->tab[i]; + } + return 0; } -char toml_array_kind(const toml_array_t* arr) +toml_raw_t toml_raw_at(const toml_array_t *arr, int idx) { - return arr->kind; + if (arr->kind != 'v') + return 0; + if (!(0 <= idx && idx < arr->nelem)) + return 0; + return arr->u.val[idx]; } -char toml_array_type(const toml_array_t* arr) +char toml_array_kind(const toml_array_t *arr) { - if (arr->kind != 'v') - return 0; - - if (arr->nelem == 0) - return 0; - - return arr->type; + return arr->kind; } - -int toml_array_nelem(const toml_array_t* arr) +char toml_array_type(const toml_array_t *arr) { - return arr->nelem; + if (arr->kind != 'v') + return 0; + + if (arr->nelem == 0) + return 0; + + return arr->type; } -const char* toml_array_key(const toml_array_t* arr) +int toml_array_nelem(const toml_array_t *arr) { - return arr ? arr->key : (const char*) NULL; + return arr->nelem; } -int toml_table_nkval(const toml_table_t* tab) +const char *toml_array_key(const toml_array_t *arr) { - return tab->nkval; + return arr ? arr->key : (const char *)NULL; } -int toml_table_narr(const toml_table_t* tab) +int toml_table_nkval(const toml_table_t *tab) { - return tab->narr; + return tab->nkval; } -int toml_table_ntab(const toml_table_t* tab) +int toml_table_narr(const toml_table_t *tab) { - return tab->ntab; + return tab->narr; } -const char* toml_table_key(const toml_table_t* tab) +int toml_table_ntab(const toml_table_t *tab) { - return tab ? tab->key : (const char*) NULL; + return tab->ntab; } -toml_array_t* toml_array_at(const toml_array_t* arr, int idx) +const char *toml_table_key(const toml_table_t *tab) { - if (arr->kind != 'a') - return 0; - if (! (0 <= idx && idx < arr->nelem)) - return 0; - return arr->u.arr[idx]; + return tab ? tab->key : (const char *)NULL; } -toml_table_t* toml_table_at(const toml_array_t* arr, int idx) +toml_array_t *toml_array_at(const toml_array_t *arr, int idx) { - if (arr->kind != 't') - return 0; - if (! (0 <= idx && idx < arr->nelem)) - return 0; - return arr->u.tab[idx]; + if (arr->kind != 'a') + return 0; + if (!(0 <= idx && idx < arr->nelem)) + return 0; + return arr->u.arr[idx]; } - -int toml_rtots(toml_raw_t src_, toml_timestamp_t* ret) +toml_table_t *toml_table_at(const toml_array_t *arr, int idx) { - if (! src_) return -1; - - const char* p = src_; - int must_parse_time = 0; - - memset(ret, 0, sizeof(*ret)); - - int* year = &ret->__buffer.year; - int* month = &ret->__buffer.month; - int* day = &ret->__buffer.day; - int* hour = &ret->__buffer.hour; - int* minute = &ret->__buffer.minute; - int* second = &ret->__buffer.second; - int* millisec = &ret->__buffer.millisec; - - /* parse date YYYY-MM-DD */ - if (0 == scan_date(p, year, month, day)) { - ret->year = year; - ret->month = month; - ret->day = day; - - p += 10; - if (*p) { - // parse the T or space separator - if (*p != 'T' && *p != ' ') return -1; - must_parse_time = 1; - p++; - } - } - - /* parse time HH:MM:SS */ - if (0 == scan_time(p, hour, minute, second)) { - ret->hour = hour; - ret->minute = minute; - ret->second = second; - - /* optionally, parse millisec */ - p += 8; - if (*p == '.') { - char* qq; - p++; - errno = 0; - *millisec = strtol(p, &qq, 0); - if (errno) { - return -1; - } - while (*millisec > 999) { - *millisec /= 10; - } - - ret->millisec = millisec; - p = qq; - } - - if (*p) { - /* parse and copy Z */ - char* z = ret->__buffer.z; - ret->z = z; - if (*p == 'Z' || *p == 'z') { - *z++ = 'Z'; p++; - *z = 0; - - } else if (*p == '+' || *p == '-') { - *z++ = *p++; - - if (! (isdigit(p[0]) && isdigit(p[1]))) return -1; - *z++ = *p++; - *z++ = *p++; - - if (*p == ':') { - *z++ = *p++; - - if (! (isdigit(p[0]) && isdigit(p[1]))) return -1; - *z++ = *p++; - *z++ = *p++; - } - - *z = 0; - } - } - } - if (*p != 0) - return -1; - - if (must_parse_time && !ret->hour) - return -1; - - return 0; + if (arr->kind != 't') + return 0; + if (!(0 <= idx && idx < arr->nelem)) + return 0; + return arr->u.tab[idx]; } +int toml_rtots(toml_raw_t src_, toml_timestamp_t *ret) +{ + if (!src_) + return -1; + + const char *p = src_; + int must_parse_time = 0; + + memset(ret, 0, sizeof(*ret)); + + int *year = &ret->__buffer.year; + int *month = &ret->__buffer.month; + int *day = &ret->__buffer.day; + int *hour = &ret->__buffer.hour; + int *minute = &ret->__buffer.minute; + int *second = &ret->__buffer.second; + int *millisec = &ret->__buffer.millisec; + + /* parse date YYYY-MM-DD */ + if (0 == scan_date(p, year, month, day)) { + ret->year = year; + ret->month = month; + ret->day = day; + + p += 10; + if (*p) { + // parse the T or space separator + if (*p != 'T' && *p != ' ') + return -1; + must_parse_time = 1; + p++; + } + } + + /* parse time HH:MM:SS */ + if (0 == scan_time(p, hour, minute, second)) { + ret->hour = hour; + ret->minute = minute; + ret->second = second; + + /* optionally, parse millisec */ + p += 8; + if (*p == '.') { + char *qq; + p++; + errno = 0; + *millisec = strtol(p, &qq, 0); + if (errno) { + return -1; + } + while (*millisec > 999) { + *millisec /= 10; + } + + ret->millisec = millisec; + p = qq; + } + + if (*p) { + /* parse and copy Z */ + char *z = ret->__buffer.z; + ret->z = z; + if (*p == 'Z' || *p == 'z') { + *z++ = 'Z'; + p++; + *z = 0; + + } else if (*p == '+' || *p == '-') { + *z++ = *p++; + + if (!(isdigit(p[0]) && isdigit(p[1]))) + return -1; + *z++ = *p++; + *z++ = *p++; + + if (*p == ':') { + *z++ = *p++; + + if (!(isdigit(p[0]) && isdigit(p[1]))) + return -1; + *z++ = *p++; + *z++ = *p++; + } + + *z = 0; + } + } + } + if (*p != 0) + return -1; + + if (must_parse_time && !ret->hour) + return -1; + + return 0; +} /* Raw to boolean */ -int toml_rtob(toml_raw_t src, int* ret_) +int toml_rtob(toml_raw_t src, int *ret_) { - if (!src) return -1; - int dummy; - int* ret = ret_ ? ret_ : &dummy; - - if (0 == strcmp(src, "true")) { - *ret = 1; - return 0; - } - if (0 == strcmp(src, "false")) { - *ret = 0; - return 0; - } - return -1; -} + if (!src) + return -1; + int dummy; + int *ret = ret_ ? ret_ : &dummy; + if (0 == strcmp(src, "true")) { + *ret = 1; + return 0; + } + if (0 == strcmp(src, "false")) { + *ret = 0; + return 0; + } + return -1; +} /* Raw to integer */ -int toml_rtoi(toml_raw_t src, int64_t* ret_) +int toml_rtoi(toml_raw_t src, int64_t *ret_) { - if (!src) return -1; - - char buf[100]; - char* p = buf; - char* q = p + sizeof(buf); - const char* s = src; - int base = 0; - int64_t dummy; - int64_t* ret = ret_ ? ret_ : &dummy; - + if (!src) + return -1; - /* allow +/- */ - if (s[0] == '+' || s[0] == '-') - *p++ = *s++; - - /* disallow +_100 */ - if (s[0] == '_') - return -1; + char buf[100]; + char *p = buf; + char *q = p + sizeof(buf); + const char *s = src; + int base = 0; + int64_t dummy; + int64_t *ret = ret_ ? ret_ : &dummy; - /* if 0 ... */ - if ('0' == s[0]) { - switch (s[1]) { - case 'x': base = 16; s += 2; break; - case 'o': base = 8; s += 2; break; - case 'b': base = 2; s += 2; break; - case '\0': return *ret = 0, 0; - default: - /* ensure no other digits after it */ - if (s[1]) return -1; - } - } + /* allow +/- */ + if (s[0] == '+' || s[0] == '-') + *p++ = *s++; - /* just strip underscores and pass to strtoll */ - while (*s && p < q) { - int ch = *s++; - switch (ch) { - case '_': - // disallow '__' - if (s[0] == '_') return -1; - continue; /* skip _ */ - default: - break; - } - *p++ = ch; - } - if (*s || p == q) return -1; + /* disallow +_100 */ + if (s[0] == '_') + return -1; - /* last char cannot be '_' */ - if (s[-1] == '_') return -1; - - /* cap with NUL */ - *p = 0; + /* if 0 ... */ + if ('0' == s[0]) { + switch (s[1]) { + case 'x': + base = 16; + s += 2; + break; + case 'o': + base = 8; + s += 2; + break; + case 'b': + base = 2; + s += 2; + break; + case '\0': + return *ret = 0, 0; + default: + /* ensure no other digits after it */ + if (s[1]) + return -1; + } + } - /* Run strtoll on buf to get the integer */ - char* endp; - errno = 0; - *ret = strtoll(buf, &endp, base); - return (errno || *endp) ? -1 : 0; + /* just strip underscores and pass to strtoll */ + while (*s && p < q) { + int ch = *s++; + switch (ch) { + case '_': + // disallow '__' + if (s[0] == '_') + return -1; + continue; /* skip _ */ + default: + break; + } + *p++ = ch; + } + if (*s || p == q) + return -1; + + /* last char cannot be '_' */ + if (s[-1] == '_') + return -1; + + /* cap with NUL */ + *p = 0; + + /* Run strtoll on buf to get the integer */ + char *endp; + errno = 0; + *ret = strtoll(buf, &endp, base); + return (errno || *endp) ? -1 : 0; } - -int toml_rtod_ex(toml_raw_t src, double* ret_, char* buf, int buflen) +int toml_rtod_ex(toml_raw_t src, double *ret_, char *buf, int buflen) { - if (!src) return -1; - - char* p = buf; - char* q = p + buflen; - const char* s = src; - double dummy; - double* ret = ret_ ? ret_ : &dummy; - + if (!src) + return -1; - /* allow +/- */ - if (s[0] == '+' || s[0] == '-') - *p++ = *s++; + char *p = buf; + char *q = p + buflen; + const char *s = src; + double dummy; + double *ret = ret_ ? ret_ : &dummy; - /* disallow +_1.00 */ - if (s[0] == '_') - return -1; + /* allow +/- */ + if (s[0] == '+' || s[0] == '-') + *p++ = *s++; - /* disallow +.99 */ - if (s[0] == '.') - return -1; - - /* zero must be followed by . or 'e', or NUL */ - if (s[0] == '0' && s[1] && !strchr("eE.", s[1])) - return -1; + /* disallow +_1.00 */ + if (s[0] == '_') + return -1; - /* just strip underscores and pass to strtod */ - while (*s && p < q) { - int ch = *s++; - switch (ch) { - case '.': - if (s[-2] == '_') return -1; - if (s[0] == '_') return -1; - break; - case '_': - // disallow '__' - if (s[0] == '_') return -1; - continue; /* skip _ */ - default: - break; - } - *p++ = ch; - } - if (*s || p == q) return -1; /* reached end of string or buffer is full? */ - - /* last char cannot be '_' */ - if (s[-1] == '_') return -1; + /* disallow +.99 */ + if (s[0] == '.') + return -1; - if (p != buf && p[-1] == '.') - return -1; /* no trailing zero */ + /* zero must be followed by . or 'e', or NUL */ + if (s[0] == '0' && s[1] && !strchr("eE.", s[1])) + return -1; - /* cap with NUL */ - *p = 0; + /* just strip underscores and pass to strtod */ + while (*s && p < q) { + int ch = *s++; + switch (ch) { + case '.': + if (s[-2] == '_') + return -1; + if (s[0] == '_') + return -1; + break; + case '_': + // disallow '__' + if (s[0] == '_') + return -1; + continue; /* skip _ */ + default: + break; + } + *p++ = ch; + } + if (*s || p == q) + return -1; /* reached end of string or buffer is full? */ - /* Run strtod on buf to get the value */ - char* endp; - errno = 0; - *ret = strtod(buf, &endp); - return (errno || *endp) ? -1 : 0; + /* last char cannot be '_' */ + if (s[-1] == '_') + return -1; + + if (p != buf && p[-1] == '.') + return -1; /* no trailing zero */ + + /* cap with NUL */ + *p = 0; + + /* Run strtod on buf to get the value */ + char *endp; + errno = 0; + *ret = strtod(buf, &endp); + return (errno || *endp) ? -1 : 0; } -int toml_rtod(toml_raw_t src, double* ret_) +int toml_rtod(toml_raw_t src, double *ret_) { - char buf[100]; - return toml_rtod_ex(src, ret_, buf, sizeof(buf)); + char buf[100]; + return toml_rtod_ex(src, ret_, buf, sizeof(buf)); } - - - -int toml_rtos(toml_raw_t src, char** ret) +int toml_rtos(toml_raw_t src, char **ret) { - int multiline = 0; - const char* sp; - const char* sq; - - *ret = 0; - if (!src) return -1; + int multiline = 0; + const char *sp; + const char *sq; - int qchar = src[0]; - int srclen = strlen(src); - if (! (qchar == '\'' || qchar == '"')) { - return -1; - } - - // triple quotes? - if (qchar == src[1] && qchar == src[2]) { - multiline = 1; - sp = src + 3; - sq = src + srclen - 3; - /* last 3 chars in src must be qchar */ - if (! (sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar)) - return -1; - - /* skip new line immediate after qchar */ - if (sp[0] == '\n') - sp++; - else if (sp[0] == '\r' && sp[1] == '\n') - sp += 2; - - } else { - sp = src + 1; - sq = src + srclen - 1; - /* last char in src must be qchar */ - if (! (sp <= sq && *sq == qchar)) - return -1; - } - - if (qchar == '\'') { - *ret = norm_lit_str(sp, sq - sp, - multiline, - 0, 0); - } else { - *ret = norm_basic_str(sp, sq - sp, - multiline, - 0, 0); - } - - return *ret ? 0 : -1; + *ret = 0; + if (!src) + return -1; + + int qchar = src[0]; + int srclen = strlen(src); + if (!(qchar == '\'' || qchar == '"')) { + return -1; + } + + // triple quotes? + if (qchar == src[1] && qchar == src[2]) { + multiline = 1; + sp = src + 3; + sq = src + srclen - 3; + /* last 3 chars in src must be qchar */ + if (!(sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar)) + return -1; + + /* skip new line immediate after qchar */ + if (sp[0] == '\n') + sp++; + else if (sp[0] == '\r' && sp[1] == '\n') + sp += 2; + + } else { + sp = src + 1; + sq = src + srclen - 1; + /* last char in src must be qchar */ + if (!(sp <= sq && *sq == qchar)) + return -1; + } + + if (qchar == '\'') { + *ret = norm_lit_str(sp, sq - sp, multiline, 0, 0); + } else { + *ret = norm_basic_str(sp, sq - sp, multiline, 0, 0); + } + + return *ret ? 0 : -1; } - -toml_datum_t toml_string_at(const toml_array_t* arr, int idx) +toml_datum_t toml_string_at(const toml_array_t *arr, int idx) { - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtos(toml_raw_at(arr, idx), &ret.u.s)); - return ret; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtos(toml_raw_at(arr, idx), &ret.u.s)); + return ret; } -toml_datum_t toml_bool_at(const toml_array_t* arr, int idx) +toml_datum_t toml_bool_at(const toml_array_t *arr, int idx) { - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtob(toml_raw_at(arr, idx), &ret.u.b)); - return ret; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtob(toml_raw_at(arr, idx), &ret.u.b)); + return ret; } -toml_datum_t toml_int_at(const toml_array_t* arr, int idx) +toml_datum_t toml_int_at(const toml_array_t *arr, int idx) { - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtoi(toml_raw_at(arr, idx), &ret.u.i)); - return ret; -} - -toml_datum_t toml_double_at(const toml_array_t* arr, int idx) -{ - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtod(toml_raw_at(arr, idx), &ret.u.d)); - return ret; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtoi(toml_raw_at(arr, idx), &ret.u.i)); + return ret; } -toml_datum_t toml_timestamp_at(const toml_array_t* arr, int idx) +toml_datum_t toml_double_at(const toml_array_t *arr, int idx) { - toml_timestamp_t ts; - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtots(toml_raw_at(arr, idx), &ts)); - if (ret.ok) { - ret.ok = !!(ret.u.ts = malloc(sizeof(*ret.u.ts))); - if (ret.ok) { - *ret.u.ts = ts; - } - } - return ret; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtod(toml_raw_at(arr, idx), &ret.u.d)); + return ret; } -toml_datum_t toml_string_in(const toml_table_t* arr, const char* key) +toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx) { - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - toml_raw_t raw = toml_raw_in(arr, key); - if (raw) { - ret.ok = (0 == toml_rtos(raw, &ret.u.s)); - } - return ret; + toml_timestamp_t ts; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtots(toml_raw_at(arr, idx), &ts)); + if (ret.ok) { + ret.ok = !!(ret.u.ts = malloc(sizeof(*ret.u.ts))); + if (ret.ok) { + *ret.u.ts = ts; + } + } + return ret; } -toml_datum_t toml_bool_in(const toml_table_t* arr, const char* key) +toml_datum_t toml_string_in(const toml_table_t *arr, const char *key) { - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtob(toml_raw_in(arr, key), &ret.u.b)); - return ret; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_in(arr, key); + if (raw) { + ret.ok = (0 == toml_rtos(raw, &ret.u.s)); + } + return ret; } -toml_datum_t toml_int_in(const toml_table_t* arr, const char* key) +toml_datum_t toml_bool_in(const toml_table_t *arr, const char *key) { - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtoi(toml_raw_in(arr, key), &ret.u.i)); - return ret; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtob(toml_raw_in(arr, key), &ret.u.b)); + return ret; } -toml_datum_t toml_double_in(const toml_table_t* arr, const char* key) +toml_datum_t toml_int_in(const toml_table_t *arr, const char *key) { - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtod(toml_raw_in(arr, key), &ret.u.d)); - return ret; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtoi(toml_raw_in(arr, key), &ret.u.i)); + return ret; } -toml_datum_t toml_timestamp_in(const toml_table_t* arr, const char* key) +toml_datum_t toml_double_in(const toml_table_t *arr, const char *key) { - toml_timestamp_t ts; - toml_datum_t ret; - memset(&ret, 0, sizeof(ret)); - ret.ok = (0 == toml_rtots(toml_raw_in(arr, key), &ts)); - if (ret.ok) { - ret.ok = !!(ret.u.ts = malloc(sizeof(*ret.u.ts))); - if (ret.ok) { - *ret.u.ts = ts; - } - } - return ret; -} + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtod(toml_raw_in(arr, key), &ret.u.d)); + return ret; +} + +toml_datum_t toml_timestamp_in(const toml_table_t *arr, const char *key) +{ + toml_timestamp_t ts; + toml_datum_t ret; + memset(&ret, 0, sizeof(ret)); + ret.ok = (0 == toml_rtots(toml_raw_in(arr, key), &ts)); + if (ret.ok) { + ret.ok = !!(ret.u.ts = malloc(sizeof(*ret.u.ts))); + if (ret.ok) { + *ret.u.ts = ts; + } + } + return ret; +} diff --git a/src/toml.h b/src/toml.h index 19f6f64..89ddecc 100644 --- a/src/toml.h +++ b/src/toml.h @@ -1,19 +1,19 @@ /* MIT License - + Copyright (c) 2017 - 2019 CK Tan https://github.com/cktan/tomlc99 - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -25,10 +25,8 @@ #ifndef TOML_H #define TOML_H - -#include #include - +#include #ifdef __cplusplus #define TOML_EXTERN extern "C" @@ -37,139 +35,130 @@ #endif typedef struct toml_timestamp_t toml_timestamp_t; -typedef struct toml_table_t toml_table_t; -typedef struct toml_array_t toml_array_t; -typedef struct toml_datum_t toml_datum_t; +typedef struct toml_table_t toml_table_t; +typedef struct toml_array_t toml_array_t; +typedef struct toml_datum_t toml_datum_t; -/* Parse a file. Return a table on success, or 0 otherwise. +/* Parse a file. Return a table on success, or 0 otherwise. * Caller must toml_free(the-return-value) after use. */ -TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp, - char* errbuf, - int errbufsz); +TOML_EXTERN toml_table_t *toml_parse_file(FILE *fp, char *errbuf, int errbufsz); -/* Parse a string containing the full config. +/* Parse a string containing the full config. * Return a table on success, or 0 otherwise. * Caller must toml_free(the-return-value) after use. */ -TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */ - char* errbuf, - int errbufsz); +TOML_EXTERN toml_table_t *toml_parse(char *conf, /* NUL terminated, please. */ + char *errbuf, + int errbufsz); -/* Free the table returned by toml_parse() or toml_parse_file(). Once - * this function is called, any handles accessed through this tab +/* Free the table returned by toml_parse() or toml_parse_file(). Once + * this function is called, any handles accessed through this tab * directly or indirectly are no longer valid. */ -TOML_EXTERN void toml_free(toml_table_t* tab); +TOML_EXTERN void toml_free(toml_table_t *tab); - -/* Timestamp types. The year, month, day, hour, minute, second, z +/* Timestamp types. The year, month, day, hour, minute, second, z * fields may be NULL if they are not relevant. e.g. In a DATE * type, the hour, minute, second and z fields will be NULLs. */ struct toml_timestamp_t { - struct { /* internal. do not use. */ - int year, month, day; - int hour, minute, second, millisec; - char z[10]; - } __buffer; - int *year, *month, *day; - int *hour, *minute, *second, *millisec; - char* z; + struct { /* internal. do not use. */ + int year, month, day; + int hour, minute, second, millisec; + char z[10]; + } __buffer; + int *year, *month, *day; + int *hour, *minute, *second, *millisec; + char *z; }; - /*----------------------------------------------------------------- - * Enhanced access methods + * Enhanced access methods */ struct toml_datum_t { - int ok; - union { - toml_timestamp_t* ts; /* ts must be freed after use */ - char* s; /* string value. s must be freed after use */ - int b; /* bool value */ - int64_t i; /* int value */ - double d; /* double value */ - } u; + int ok; + union { + toml_timestamp_t *ts; /* ts must be freed after use */ + char *s; /* string value. s must be freed after use */ + int b; /* bool value */ + int64_t i; /* int value */ + double d; /* double value */ + } u; }; /* on arrays: */ /* ... retrieve size of array. */ -TOML_EXTERN int toml_array_nelem(const toml_array_t* arr); +TOML_EXTERN int toml_array_nelem(const toml_array_t *arr); /* ... retrieve values using index. */ -TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t* arr, int idx); -TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t* arr, int idx); -TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t* arr, int idx); -TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t* arr, int idx); -TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t* arr, int idx); +TOML_EXTERN toml_datum_t toml_string_at(const toml_array_t *arr, int idx); +TOML_EXTERN toml_datum_t toml_bool_at(const toml_array_t *arr, int idx); +TOML_EXTERN toml_datum_t toml_int_at(const toml_array_t *arr, int idx); +TOML_EXTERN toml_datum_t toml_double_at(const toml_array_t *arr, int idx); +TOML_EXTERN toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx); /* ... retrieve array or table using index. */ -TOML_EXTERN toml_array_t* toml_array_at(const toml_array_t* arr, int idx); -TOML_EXTERN toml_table_t* toml_table_at(const toml_array_t* arr, int idx); +TOML_EXTERN toml_array_t *toml_array_at(const toml_array_t *arr, int idx); +TOML_EXTERN toml_table_t *toml_table_at(const toml_array_t *arr, int idx); /* on tables: */ /* ... retrieve the key in table at keyidx. Return 0 if out of range. */ -TOML_EXTERN const char* toml_key_in(const toml_table_t* tab, int keyidx); +TOML_EXTERN const char *toml_key_in(const toml_table_t *tab, int keyidx); /* ... retrieve values using key. */ -TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t* arr, const char* key); -TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t* arr, const char* key); -TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t* arr, const char* key); -TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t* arr, const char* key); -TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t* arr, const char* key); +TOML_EXTERN toml_datum_t toml_string_in(const toml_table_t *arr, const char *key); +TOML_EXTERN toml_datum_t toml_bool_in(const toml_table_t *arr, const char *key); +TOML_EXTERN toml_datum_t toml_int_in(const toml_table_t *arr, const char *key); +TOML_EXTERN toml_datum_t toml_double_in(const toml_table_t *arr, const char *key); +TOML_EXTERN toml_datum_t toml_timestamp_in(const toml_table_t *arr, const char *key); /* .. retrieve array or table using key. */ -TOML_EXTERN toml_array_t* toml_array_in(const toml_table_t* tab, - const char* key); -TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab, - const char* key); +TOML_EXTERN toml_array_t *toml_array_in(const toml_table_t *tab, const char *key); +TOML_EXTERN toml_table_t *toml_table_in(const toml_table_t *tab, const char *key); /*----------------------------------------------------------------- - * lesser used + * lesser used */ /* Return the array kind: 't'able, 'a'rray, 'v'alue */ -TOML_EXTERN char toml_array_kind(const toml_array_t* arr); +TOML_EXTERN char toml_array_kind(const toml_array_t *arr); -/* For array kind 'v'alue, return the type of values +/* For array kind 'v'alue, return the type of values i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp 0 if unknown */ -TOML_EXTERN char toml_array_type(const toml_array_t* arr); +TOML_EXTERN char toml_array_type(const toml_array_t *arr); /* Return the key of an array */ -TOML_EXTERN const char* toml_array_key(const toml_array_t* arr); +TOML_EXTERN const char *toml_array_key(const toml_array_t *arr); /* Return the number of key-values in a table */ -TOML_EXTERN int toml_table_nkval(const toml_table_t* tab); +TOML_EXTERN int toml_table_nkval(const toml_table_t *tab); /* Return the number of arrays in a table */ -TOML_EXTERN int toml_table_narr(const toml_table_t* tab); +TOML_EXTERN int toml_table_narr(const toml_table_t *tab); /* Return the number of sub-tables in a table */ -TOML_EXTERN int toml_table_ntab(const toml_table_t* tab); +TOML_EXTERN int toml_table_ntab(const toml_table_t *tab); /* Return the key of a table*/ -TOML_EXTERN const char* toml_table_key(const toml_table_t* tab); +TOML_EXTERN const char *toml_table_key(const toml_table_t *tab); /*-------------------------------------------------------------- - * misc + * misc */ -TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret); -TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]); -TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t), - void (*xxfree)(void*)); - +TOML_EXTERN int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret); +TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]); +TOML_EXTERN void toml_set_memutil(void *(*xxmalloc)(size_t), void (*xxfree)(void *)); /*-------------------------------------------------------------- - * deprecated + * deprecated */ /* A raw value, must be processed by toml_rto* before using. */ -typedef const char* toml_raw_t; -TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key); -TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t* arr, int idx); -TOML_EXTERN int toml_rtos(toml_raw_t s, char** ret); -TOML_EXTERN int toml_rtob(toml_raw_t s, int* ret); -TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t* ret); -TOML_EXTERN int toml_rtod(toml_raw_t s, double* ret); -TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double* ret, char* buf, int buflen); -TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t* ret); - +typedef const char *toml_raw_t; +TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key); +TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t *arr, int idx); +TOML_EXTERN int toml_rtos(toml_raw_t s, char **ret); +TOML_EXTERN int toml_rtob(toml_raw_t s, int *ret); +TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t *ret); +TOML_EXTERN int toml_rtod(toml_raw_t s, double *ret); +TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double *ret, char *buf, int buflen); +TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t *ret); #endif /* TOML_H */ diff --git a/src/udev.c b/src/udev.c index cc452b1..da70b71 100644 --- a/src/udev.c +++ b/src/udev.c @@ -11,14 +11,13 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer data) { struct EG25Manager *manager = data; - const gchar *prop; - long vid = 0, pid = 0; + const gchar *prop; + long vid = 0, pid = 0; /* * Act only if the device is the one identified as a modem by MM/ofono */ - if (!manager->modem_usb_id || - strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) { + if (!manager->modem_usb_id || strcmp(g_udev_device_get_name(device), manager->modem_usb_id) != 0) { return; } @@ -42,10 +41,8 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic manager->modem_state = EG25_STATE_UPDATING; } - if (strcmp(action, "unbind") != 0 || - manager->modem_state == EG25_STATE_UPDATING || - manager->modem_state == EG25_STATE_RESETTING || - manager->complete_reset_timer != 0 || + if (strcmp(action, "unbind") != 0 || manager->modem_state == EG25_STATE_UPDATING || + manager->modem_state == EG25_STATE_RESETTING || manager->complete_reset_timer != 0 || manager->schedule_reset_timer != 0) { return; } @@ -54,9 +51,9 @@ static void udev_event_cb(GUdevClient *client, gchar *action, GUdevDevice *devic manager->schedule_reset_timer = g_timeout_add_seconds(3, G_SOURCE_FUNC(modem_reset), manager); } -void udev_init (struct EG25Manager *manager, toml_table_t *config[]) +void udev_init(struct EG25Manager *manager, toml_table_t *config[]) { - const char * const subsystems[] = { "usb", NULL }; + const char *const subsystems[] = {"usb", NULL}; manager->udev = g_udev_client_new(subsystems); g_signal_connect(manager->udev, "uevent", G_CALLBACK(udev_event_cb), manager); @@ -64,7 +61,7 @@ void udev_init (struct EG25Manager *manager, toml_table_t *config[]) return; } -void udev_destroy (struct EG25Manager *manager) +void udev_destroy(struct EG25Manager *manager) { if (manager->udev) { g_object_unref(manager->udev); diff --git a/src/udev.h b/src/udev.h index 1d399d7..58bebd3 100644 --- a/src/udev.h +++ b/src/udev.h @@ -8,5 +8,5 @@ #include "manager.h" -void udev_init (struct EG25Manager *data, toml_table_t *config[]); -void udev_destroy (struct EG25Manager *data); +void udev_init(struct EG25Manager *data, toml_table_t *config[]); +void udev_destroy(struct EG25Manager *data);