mirror of
https://github.com/86Box/86Box.git
synced 2025-01-23 09:42:47 -05:00
config: Refactor the INI parser out
This commit is contained in:
parent
d2dc53fbfb
commit
7dd8c96ffc
9 changed files with 1446 additions and 1282 deletions
|
@ -20,7 +20,7 @@ endif()
|
|||
|
||||
add_executable(86Box 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
|
||||
dma.c ddma.c discord.c nmi.c pic.c pit.c pit_fast.c port_6x.c port_92.c ppi.c pci.c
|
||||
mca.c usb.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c machine_status.c)
|
||||
mca.c usb.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c machine_status.c ini.c)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1)
|
||||
|
|
1802
src/config.c
1802
src/config.c
File diff suppressed because it is too large
Load diff
|
@ -45,6 +45,7 @@
|
|||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/ini.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
|
|
|
@ -136,27 +136,33 @@ typedef struct {
|
|||
|
||||
extern void config_load(void);
|
||||
extern void config_save(void);
|
||||
extern void config_write(char *fn);
|
||||
extern void config_dump(void);
|
||||
|
||||
extern void config_delete_var(char *head, char *name);
|
||||
extern int config_get_int(char *head, char *name, int def);
|
||||
extern double config_get_double(char *head, char *name, double def);
|
||||
extern int config_get_hex16(char *head, char *name, int def);
|
||||
extern int config_get_hex20(char *head, char *name, int def);
|
||||
extern int config_get_mac(char *head, char *name, int def);
|
||||
extern char *config_get_string(char *head, char *name, char *def);
|
||||
extern wchar_t *config_get_wstring(char *head, char *name, wchar_t *def);
|
||||
extern void config_set_int(char *head, char *name, int val);
|
||||
extern void config_set_double(char *head, char *name, double val);
|
||||
extern void config_set_hex16(char *head, char *name, int val);
|
||||
extern void config_set_hex20(char *head, char *name, int val);
|
||||
extern void config_set_mac(char *head, char *name, int val);
|
||||
extern void config_set_string(char *head, char *name, char *val);
|
||||
extern void config_set_wstring(char *head, char *name, wchar_t *val);
|
||||
#ifdef EMU_INI_H
|
||||
extern ini_t config_get_ini(void);
|
||||
#else
|
||||
extern void *config_get_ini(void);
|
||||
#endif
|
||||
|
||||
extern void *config_find_section(char *name);
|
||||
extern void config_rename_section(void *priv, char *name);
|
||||
#define config_delete_var(head, name) ini_delete_var(config_get_ini(), head, name)
|
||||
|
||||
#define config_get_int(head, name, def) ini_get_int(config_get_ini(), head, name, def)
|
||||
#define config_get_double(head, name, def) ini_get_double(config_get_ini(), head, name, def)
|
||||
#define config_get_hex16(head, name, def) ini_get_hex16(config_get_ini(), head, name, def)
|
||||
#define config_get_hex20(head, name, def) ini_get_hex20(config_get_ini(), head, name, def)
|
||||
#define config_get_mac(head, name, def) ini_get_mac(config_get_ini(), head, name, def)
|
||||
#define config_get_string(head, name, def) ini_get_string(config_get_ini(), head, name, def)
|
||||
#define config_get_wstring(head, name, def) ini_get_wstring(config_get_ini(), head, name, def)
|
||||
|
||||
#define config_set_int(head, name, val) ini_set_int(config_get_ini(), head, name, val)
|
||||
#define config_set_double(head, name, val) ini_set_double(config_get_ini(), head, name, val)
|
||||
#define config_set_hex16(head, name, val) ini_set_hex16(config_get_ini(), head, name, val)
|
||||
#define config_set_hex20(head, name, val) ini_set_hex20(config_get_ini(), head, name, val)
|
||||
#define config_set_mac(head, name, val) ini_set_mac(config_get_ini(), head, name, val)
|
||||
#define config_set_string(head, name, val) ini_set_string(config_get_ini(), head, name, val)
|
||||
#define config_set_wstring(head, name, val) ini_set_wstring(config_get_ini(), head, name, val)
|
||||
|
||||
#define config_find_section(name) ini_find_section(config_get_ini(), name)
|
||||
#define config_rename_section ini_rename_section
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
81
src/include/86box/ini.h
Normal file
81
src/include/86box/ini.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Configuration file handler header.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Overdoze,
|
||||
*
|
||||
* Copyright 2008-2017 Sarah Walker.
|
||||
* Copyright 2016,2017 Miran Grca.
|
||||
*
|
||||
*/
|
||||
#ifndef EMU_INI_H
|
||||
#define EMU_INI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void *ini_t;
|
||||
typedef void *ini_section_t;
|
||||
|
||||
extern ini_t ini_new(void);
|
||||
extern ini_t ini_read(char *fn);
|
||||
extern void ini_write(ini_t ini, char *fn);
|
||||
extern void ini_dump(ini_t ini);
|
||||
extern void ini_close(ini_t ini);
|
||||
|
||||
extern void ini_section_delete_var(ini_section_t section, char *name);
|
||||
extern int ini_section_get_int(ini_section_t section, char *name, int def);
|
||||
extern double ini_section_get_double(ini_section_t section, char *name, double def);
|
||||
extern int ini_section_get_hex16(ini_section_t section, char *name, int def);
|
||||
extern int ini_section_get_hex20(ini_section_t section, char *name, int def);
|
||||
extern int ini_section_get_mac(ini_section_t section, char *name, int def);
|
||||
extern char *ini_section_get_string(ini_section_t section, char *name, char *def);
|
||||
extern wchar_t *ini_section_get_wstring(ini_section_t section, char *name, wchar_t *def);
|
||||
extern void ini_section_set_int(ini_section_t section, char *name, int val);
|
||||
extern void ini_section_set_double(ini_section_t section, char *name, double val);
|
||||
extern void ini_section_set_hex16(ini_section_t section, char *name, int val);
|
||||
extern void ini_section_set_hex20(ini_section_t section, char *name, int val);
|
||||
extern void ini_section_set_mac(ini_section_t section, char *name, int val);
|
||||
extern void ini_section_set_string(ini_section_t section, char *name, char *val);
|
||||
extern void ini_section_set_wstring(ini_section_t section, char *name, wchar_t *val);
|
||||
|
||||
#define ini_delete_var(ini, head, name) ini_section_delete_var(ini_find_section(ini, head), name)
|
||||
|
||||
#define ini_get_int(ini, head, name, def) ini_section_get_int(ini_find_section(ini, head), name, def)
|
||||
#define ini_get_double(ini, head, name, def) ini_section_get_double(ini_find_section(ini, head), name, def)
|
||||
#define ini_get_hex16(ini, head, name, def) ini_section_get_hex16(ini_find_section(ini, head), name, def)
|
||||
#define ini_get_hex20(ini, head, name, def) ini_section_get_hex20(ini_find_section(ini, head), name, def)
|
||||
#define ini_get_mac(ini, head, name, def) ini_section_get_mac(ini_find_section(ini, head), name, def)
|
||||
#define ini_get_string(ini, head, name, def) ini_section_get_string(ini_find_section(ini, head), name, def)
|
||||
#define ini_get_wstring(ini, head, name, def) ini_section_get_wstring(ini_find_section(ini, head), name, def)
|
||||
|
||||
#define ini_set_int(ini, head, name, val) ini_section_set_int(ini_find_or_create_section(ini, head), name, val)
|
||||
#define ini_set_double(ini, head, name, val) ini_section_set_double(ini_find_or_create_section(ini, head), name, val)
|
||||
#define ini_set_hex16(ini, head, name, val) ini_section_set_hex16(ini_find_or_create_section(ini, head), name, val)
|
||||
#define ini_set_hex20(ini, head, name, val) ini_section_set_hex20(ini_find_or_create_section(ini, head), name, val)
|
||||
#define ini_set_mac(ini, head, name, val) ini_section_set_mac(ini_find_or_create_section(ini, head), name, val)
|
||||
#define ini_set_string(ini, head, name, val) ini_section_set_string(ini_find_or_create_section(ini, head), name, val)
|
||||
#define ini_set_wstring(ini, head, name, val) ini_section_set_wstring(ini_find_or_create_section(ini, head), name, val)
|
||||
|
||||
extern ini_section_t ini_find_section(ini_t ini, char *name);
|
||||
extern ini_section_t ini_find_or_create_section(ini_t ini, char *name);
|
||||
extern void ini_rename_section(ini_section_t section, char *name);
|
||||
extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
795
src/ini.c
Normal file
795
src/ini.c
Normal file
|
@ -0,0 +1,795 @@
|
|||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Configuration file handler.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Overdoze,
|
||||
* David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
*
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2018,2019 David Hrdlička.
|
||||
*
|
||||
* NOTE: Forcing config files to be in Unicode encoding breaks
|
||||
* it on Windows XP, and possibly also Vista. Use the
|
||||
* -DANSI_CFG for use on these systems.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/ini.h>
|
||||
#include <86box/plat.h>
|
||||
|
||||
typedef struct _list_ {
|
||||
struct _list_ *next;
|
||||
} list_t;
|
||||
|
||||
typedef struct {
|
||||
list_t list;
|
||||
|
||||
char name[128];
|
||||
|
||||
list_t entry_head;
|
||||
} section_t;
|
||||
|
||||
typedef struct {
|
||||
list_t list;
|
||||
|
||||
char name[128];
|
||||
char data[512];
|
||||
wchar_t wdata[512];
|
||||
} entry_t;
|
||||
|
||||
#define list_add(new, head) \
|
||||
{ \
|
||||
list_t *next = head; \
|
||||
\
|
||||
while (next->next != NULL) \
|
||||
next = next->next; \
|
||||
\
|
||||
(next)->next = new; \
|
||||
(new)->next = NULL; \
|
||||
}
|
||||
|
||||
#define list_delete(old, head) \
|
||||
{ \
|
||||
list_t *next = head; \
|
||||
\
|
||||
while ((next)->next != old) { \
|
||||
next = (next)->next; \
|
||||
} \
|
||||
\
|
||||
(next)->next = (old)->next; \
|
||||
if ((next) == (head)) \
|
||||
(head)->next = (old)->next; \
|
||||
}
|
||||
|
||||
#ifdef ENABLE_INI_LOG
|
||||
int ini_do_log = ENABLE_INI_LOG;
|
||||
|
||||
static void
|
||||
ini_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (ini_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define ini_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static section_t *
|
||||
find_section(list_t *head, char *name)
|
||||
{
|
||||
section_t *sec = (section_t *) head->next;
|
||||
char blank[] = "";
|
||||
|
||||
if (name == NULL)
|
||||
name = blank;
|
||||
|
||||
while (sec != NULL) {
|
||||
if (!strncmp(sec->name, name, sizeof(sec->name)))
|
||||
return (sec);
|
||||
|
||||
sec = (section_t *) sec->list.next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ini_section_t
|
||||
ini_find_section(ini_t ini, char *name)
|
||||
{
|
||||
if (ini == NULL)
|
||||
return NULL;
|
||||
|
||||
return (ini_section_t) find_section((list_t *) ini, name);
|
||||
}
|
||||
|
||||
void
|
||||
ini_rename_section(ini_section_t section, char *name)
|
||||
{
|
||||
section_t *sec = (section_t *) section;
|
||||
|
||||
if (sec == NULL)
|
||||
return;
|
||||
|
||||
memset(sec->name, 0x00, sizeof(sec->name));
|
||||
memcpy(sec->name, name, MIN(128, strlen(name) + 1));
|
||||
}
|
||||
|
||||
static entry_t *
|
||||
find_entry(section_t *section, char *name)
|
||||
{
|
||||
entry_t *ent;
|
||||
|
||||
ent = (entry_t *) section->entry_head.next;
|
||||
|
||||
while (ent != NULL) {
|
||||
if (!strncmp(ent->name, name, sizeof(ent->name)))
|
||||
return (ent);
|
||||
|
||||
ent = (entry_t *) ent->list.next;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
entries_num(section_t *section)
|
||||
{
|
||||
entry_t *ent;
|
||||
int i = 0;
|
||||
|
||||
ent = (entry_t *) section->entry_head.next;
|
||||
|
||||
while (ent != NULL) {
|
||||
if (strlen(ent->name) > 0)
|
||||
i++;
|
||||
|
||||
ent = (entry_t *) ent->list.next;
|
||||
}
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_section_if_empty(list_t *head, section_t *section)
|
||||
{
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
if (entries_num(section) == 0) {
|
||||
list_delete(§ion->list, head);
|
||||
free(section);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ini_delete_section_if_empty(ini_t ini, ini_section_t section)
|
||||
{
|
||||
if (ini == NULL || section == NULL)
|
||||
return;
|
||||
|
||||
delete_section_if_empty((list_t *) ini, (section_t *) section);
|
||||
}
|
||||
|
||||
static section_t *
|
||||
create_section(list_t *head, char *name)
|
||||
{
|
||||
section_t *ns = malloc(sizeof(section_t));
|
||||
|
||||
memset(ns, 0x00, sizeof(section_t));
|
||||
memcpy(ns->name, name, strlen(name) + 1);
|
||||
list_add(&ns->list, head);
|
||||
|
||||
return (ns);
|
||||
}
|
||||
|
||||
ini_section_t
|
||||
ini_find_or_create_section(ini_t ini, char *name)
|
||||
{
|
||||
if (ini == NULL)
|
||||
return NULL;
|
||||
|
||||
section_t *section = find_section((list_t *) ini, name);
|
||||
if (section == NULL)
|
||||
section = create_section((list_t *) ini, name);
|
||||
|
||||
return (ini_section_t) section;
|
||||
}
|
||||
|
||||
static entry_t *
|
||||
create_entry(section_t *section, char *name)
|
||||
{
|
||||
entry_t *ne = malloc(sizeof(entry_t));
|
||||
|
||||
memset(ne, 0x00, sizeof(entry_t));
|
||||
memcpy(ne->name, name, strlen(name) + 1);
|
||||
list_add(&ne->list, §ion->entry_head);
|
||||
|
||||
return (ne);
|
||||
}
|
||||
|
||||
static void
|
||||
ini_close(ini_t ini)
|
||||
{
|
||||
section_t *sec, *ns;
|
||||
entry_t *ent;
|
||||
list_t *list = (list_t *) ini;
|
||||
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
sec = (section_t *) list->next;
|
||||
while (sec != NULL) {
|
||||
ns = (section_t *) sec->list.next;
|
||||
ent = (entry_t *) sec->entry_head.next;
|
||||
|
||||
while (ent != NULL) {
|
||||
entry_t *nent = (entry_t *) ent->list.next;
|
||||
|
||||
free(ent);
|
||||
ent = nent;
|
||||
}
|
||||
|
||||
free(sec);
|
||||
sec = ns;
|
||||
}
|
||||
|
||||
free(list);
|
||||
}
|
||||
|
||||
static int
|
||||
ini_detect_bom(char *fn)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned char bom[4] = { 0, 0, 0, 0 };
|
||||
|
||||
#if defined(ANSI_CFG) || !defined(_WIN32)
|
||||
f = plat_fopen(fn, "rt");
|
||||
#else
|
||||
f = plat_fopen(fn, "rt, ccs=UTF-8");
|
||||
#endif
|
||||
if (f == NULL)
|
||||
return (0);
|
||||
fread(bom, 1, 3, f);
|
||||
if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __HAIKU__
|
||||
/* Local version of fgetws to avoid a crash */
|
||||
static wchar_t *
|
||||
ini_fgetws(wchar_t *str, int count, FILE *stream)
|
||||
{
|
||||
int i = 0;
|
||||
if (feof(stream))
|
||||
return NULL;
|
||||
for (i = 0; i < count; i++) {
|
||||
wint_t curChar = fgetwc(stream);
|
||||
if (curChar == WEOF) {
|
||||
if (i + 1 < count)
|
||||
str[i + 1] = 0;
|
||||
return feof(stream) ? str : NULL;
|
||||
}
|
||||
str[i] = curChar;
|
||||
if (curChar == '\n')
|
||||
break;
|
||||
}
|
||||
if (i + 1 < count)
|
||||
str[i + 1] = 0;
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read and parse the configuration file into memory. */
|
||||
ini_t
|
||||
ini_read(char *fn)
|
||||
{
|
||||
char sname[128], ename[128];
|
||||
wchar_t buff[1024];
|
||||
section_t *sec, *ns;
|
||||
entry_t *ne;
|
||||
int c, d, bom;
|
||||
FILE *f;
|
||||
list_t *head;
|
||||
|
||||
bom = ini_detect_bom(fn);
|
||||
#if defined(ANSI_CFG) || !defined(_WIN32)
|
||||
f = plat_fopen(fn, "rt");
|
||||
#else
|
||||
f = plat_fopen(fn, "rt, ccs=UTF-8");
|
||||
#endif
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
||||
head = malloc(sizeof(list_t));
|
||||
memset(head, 0x00, sizeof(list_t));
|
||||
|
||||
sec = malloc(sizeof(section_t));
|
||||
memset(sec, 0x00, sizeof(section_t));
|
||||
|
||||
list_add(&sec->list, head);
|
||||
if (bom)
|
||||
fseek(f, 3, SEEK_SET);
|
||||
|
||||
while (1) {
|
||||
memset(buff, 0x00, sizeof(buff));
|
||||
#ifdef __HAIKU__
|
||||
ini_fgetws(buff, sizeof_w(buff), f);
|
||||
#else
|
||||
(void) !fgetws(buff, sizeof_w(buff), f);
|
||||
#endif
|
||||
if (feof(f))
|
||||
break;
|
||||
|
||||
/* Make sure there are no stray newlines or hard-returns in there. */
|
||||
if (wcslen(buff) > 0)
|
||||
if (buff[wcslen(buff) - 1] == L'\n')
|
||||
buff[wcslen(buff) - 1] = L'\0';
|
||||
if (wcslen(buff) > 0)
|
||||
if (buff[wcslen(buff) - 1] == L'\r')
|
||||
buff[wcslen(buff) - 1] = L'\0';
|
||||
|
||||
/* Skip any leading whitespace. */
|
||||
c = 0;
|
||||
while ((buff[c] == L' ') || (buff[c] == L'\t'))
|
||||
c++;
|
||||
|
||||
/* Skip empty lines. */
|
||||
if (buff[c] == L'\0')
|
||||
continue;
|
||||
|
||||
/* Skip lines that (only) have a comment. */
|
||||
if ((buff[c] == L'#') || (buff[c] == L';'))
|
||||
continue;
|
||||
|
||||
if (buff[c] == L'[') { /*Section*/
|
||||
c++;
|
||||
d = 0;
|
||||
while (buff[c] != L']' && buff[c])
|
||||
(void) !wctomb(&(sname[d++]), buff[c++]);
|
||||
sname[d] = L'\0';
|
||||
|
||||
/* Is the section name properly terminated? */
|
||||
if (buff[c] != L']')
|
||||
continue;
|
||||
|
||||
/* Create a new section and insert it. */
|
||||
ns = malloc(sizeof(section_t));
|
||||
memset(ns, 0x00, sizeof(section_t));
|
||||
memcpy(ns->name, sname, 128);
|
||||
list_add(&ns->list, head);
|
||||
|
||||
/* New section is now the current one. */
|
||||
sec = ns;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the variable name. */
|
||||
d = 0;
|
||||
while ((buff[c] != L'=') && (buff[c] != L' ') && buff[c])
|
||||
(void) !wctomb(&(ename[d++]), buff[c++]);
|
||||
ename[d] = L'\0';
|
||||
|
||||
/* Skip incomplete lines. */
|
||||
if (buff[c] == L'\0')
|
||||
continue;
|
||||
|
||||
/* Look for =, skip whitespace. */
|
||||
while ((buff[c] == L'=' || buff[c] == L' ') && buff[c])
|
||||
c++;
|
||||
|
||||
/* Skip incomplete lines. */
|
||||
if (buff[c] == L'\0')
|
||||
continue;
|
||||
|
||||
/* This is where the value part starts. */
|
||||
d = c;
|
||||
|
||||
/* Allocate a new variable entry.. */
|
||||
ne = malloc(sizeof(entry_t));
|
||||
memset(ne, 0x00, sizeof(entry_t));
|
||||
memcpy(ne->name, ename, 128);
|
||||
wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata) - 1);
|
||||
ne->wdata[sizeof_w(ne->wdata) - 1] = L'\0';
|
||||
#ifdef _WIN32 /* Make sure the string is converted to UTF-8 rather than a legacy codepage */
|
||||
c16stombs(ne->data, ne->wdata, sizeof(ne->data));
|
||||
#else
|
||||
wcstombs(ne->data, ne->wdata, sizeof(ne->data));
|
||||
#endif
|
||||
ne->data[sizeof(ne->data) - 1] = '\0';
|
||||
|
||||
/* .. and insert it. */
|
||||
list_add(&ne->list, &sec->entry_head);
|
||||
}
|
||||
|
||||
(void) fclose(f);
|
||||
|
||||
return (ini_t) head;
|
||||
}
|
||||
|
||||
/* Write the in-memory configuration to disk. */
|
||||
void
|
||||
ini_write(ini_t ini, char *fn)
|
||||
{
|
||||
wchar_t wtemp[512];
|
||||
list_t *list = (list_t *) ini;
|
||||
section_t *sec;
|
||||
FILE *f;
|
||||
int fl = 0;
|
||||
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
sec = (section_t *) list->next;
|
||||
|
||||
#if defined(ANSI_CFG) || !defined(_WIN32)
|
||||
f = plat_fopen(fn, "wt");
|
||||
#else
|
||||
f = plat_fopen(fn, "wt, ccs=UTF-8");
|
||||
#endif
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
while (sec != NULL) {
|
||||
entry_t *ent;
|
||||
|
||||
if (sec->name[0]) {
|
||||
mbstowcs(wtemp, sec->name, strlen(sec->name) + 1);
|
||||
if (fl)
|
||||
fwprintf(f, L"\n[%ls]\n", wtemp);
|
||||
else
|
||||
fwprintf(f, L"[%ls]\n", wtemp);
|
||||
fl++;
|
||||
}
|
||||
|
||||
ent = (entry_t *) sec->entry_head.next;
|
||||
while (ent != NULL) {
|
||||
if (ent->name[0] != '\0') {
|
||||
mbstowcs(wtemp, ent->name, 128);
|
||||
if (ent->wdata[0] == L'\0')
|
||||
fwprintf(f, L"%ls = \n", wtemp);
|
||||
else
|
||||
fwprintf(f, L"%ls = %ls\n", wtemp, ent->wdata);
|
||||
fl++;
|
||||
}
|
||||
|
||||
ent = (entry_t *) ent->list.next;
|
||||
}
|
||||
|
||||
sec = (section_t *) sec->list.next;
|
||||
}
|
||||
|
||||
(void) fclose(f);
|
||||
}
|
||||
|
||||
ini_t
|
||||
ini_new()
|
||||
{
|
||||
ini_t ini = malloc(sizeof(list_t));
|
||||
memset(ini, 0, sizeof(list_t));
|
||||
return ini;
|
||||
}
|
||||
|
||||
void
|
||||
ini_dump(ini_t ini)
|
||||
{
|
||||
section_t *sec = (section_t *) ini;
|
||||
while (sec != NULL) {
|
||||
entry_t *ent;
|
||||
|
||||
if (sec->name[0])
|
||||
ini_log("[%s]\n", sec->name);
|
||||
|
||||
ent = (entry_t *) sec->entry_head.next;
|
||||
while (ent != NULL) {
|
||||
ini_log("%s = %s\n", ent->name, ent->data);
|
||||
|
||||
ent = (entry_t *) ent->list.next;
|
||||
}
|
||||
|
||||
sec = (section_t *) sec->list.next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_delete_var(ini_section_t self, char *name)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry != NULL) {
|
||||
list_delete(&entry->list, §ion->entry_head);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ini_section_get_int(ini_section_t self, char *name, int def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
int value;
|
||||
|
||||
if (section == NULL)
|
||||
return (def);
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry == NULL)
|
||||
return (def);
|
||||
|
||||
sscanf(entry->data, "%i", &value);
|
||||
|
||||
return (value);
|
||||
}
|
||||
|
||||
double
|
||||
ini_section_get_double(ini_section_t self, char *name, double def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
double value;
|
||||
|
||||
if (section == NULL)
|
||||
return (def);
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry == NULL)
|
||||
return (def);
|
||||
|
||||
sscanf(entry->data, "%lg", &value);
|
||||
|
||||
return (value);
|
||||
}
|
||||
|
||||
int
|
||||
ini_section_get_hex16(ini_section_t self, char *name, int def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
unsigned int value;
|
||||
|
||||
if (section == NULL)
|
||||
return (def);
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry == NULL)
|
||||
return (def);
|
||||
|
||||
sscanf(entry->data, "%04X", &value);
|
||||
|
||||
return (value);
|
||||
}
|
||||
|
||||
int
|
||||
ini_section_get_hex20(ini_section_t self, char *name, int def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
unsigned int value;
|
||||
|
||||
if (section == NULL)
|
||||
return (def);
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry == NULL)
|
||||
return (def);
|
||||
|
||||
sscanf(entry->data, "%05X", &value);
|
||||
|
||||
return (value);
|
||||
}
|
||||
|
||||
int
|
||||
ini_section_get_mac(ini_section_t self, char *name, int def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
unsigned int val0 = 0, val1 = 0, val2 = 0;
|
||||
|
||||
if (section == NULL)
|
||||
return (def);
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry == NULL)
|
||||
return (def);
|
||||
|
||||
sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2);
|
||||
|
||||
return ((val0 << 16) + (val1 << 8) + val2);
|
||||
}
|
||||
|
||||
char *
|
||||
ini_section_get_string(ini_section_t self, char *name, char *def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
|
||||
if (section == NULL)
|
||||
return (def);
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry == NULL)
|
||||
return (def);
|
||||
|
||||
return (entry->data);
|
||||
}
|
||||
|
||||
wchar_t *
|
||||
ini_section_get_wstring(ini_section_t self, char *name, wchar_t *def)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *entry;
|
||||
|
||||
if (section == NULL)
|
||||
return (def);
|
||||
|
||||
entry = find_entry(section, name);
|
||||
if (entry == NULL)
|
||||
return (def);
|
||||
|
||||
return (entry->wdata);
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_set_int(ini_section_t self, char *name, int val)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *ent;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
ent = find_entry(section, name);
|
||||
if (ent == NULL)
|
||||
ent = create_entry(section, name);
|
||||
|
||||
sprintf(ent->data, "%i", val);
|
||||
mbstowcs(ent->wdata, ent->data, 512);
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_set_double(ini_section_t self, char *name, double val)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *ent;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
ent = find_entry(section, name);
|
||||
if (ent == NULL)
|
||||
ent = create_entry(section, name);
|
||||
|
||||
sprintf(ent->data, "%lg", val);
|
||||
mbstowcs(ent->wdata, ent->data, 512);
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_set_hex16(ini_section_t self, char *name, int val)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *ent;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
ent = find_entry(section, name);
|
||||
if (ent == NULL)
|
||||
ent = create_entry(section, name);
|
||||
|
||||
sprintf(ent->data, "%04X", val);
|
||||
mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata));
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_set_hex20(ini_section_t self, char *name, int val)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *ent;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
ent = find_entry(section, name);
|
||||
if (ent == NULL)
|
||||
ent = create_entry(section, name);
|
||||
|
||||
sprintf(ent->data, "%05X", val);
|
||||
mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata));
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_set_mac(ini_section_t self, char *name, int val)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *ent;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
ent = find_entry(section, name);
|
||||
if (ent == NULL)
|
||||
ent = create_entry(section, name);
|
||||
|
||||
sprintf(ent->data, "%02x:%02x:%02x",
|
||||
(val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
|
||||
mbstowcs(ent->wdata, ent->data, 512);
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_set_string(ini_section_t self, char *name, char *val)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *ent;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
ent = find_entry(section, name);
|
||||
if (ent == NULL)
|
||||
ent = create_entry(section, name);
|
||||
|
||||
if ((strlen(val) + 1) <= sizeof(ent->data))
|
||||
memcpy(ent->data, val, strlen(val) + 1);
|
||||
else
|
||||
memcpy(ent->data, val, sizeof(ent->data));
|
||||
#ifdef _WIN32 /* Make sure the string is converted from UTF-8 rather than a legacy codepage */
|
||||
mbstoc16s(ent->wdata, ent->data, sizeof_w(ent->wdata));
|
||||
#else
|
||||
mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata));
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ini_section_set_wstring(ini_section_t self, char *name, wchar_t *val)
|
||||
{
|
||||
section_t *section = (section_t *) self;
|
||||
entry_t *ent;
|
||||
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
ent = find_entry(section, name);
|
||||
if (ent == NULL)
|
||||
ent = create_entry(section, name);
|
||||
|
||||
memcpy(ent->wdata, val, sizeof_w(ent->wdata));
|
||||
#ifdef _WIN32 /* Make sure the string is converted to UTF-8 rather than a legacy codepage */
|
||||
c16stombs(ent->data, ent->wdata, sizeof(ent->data));
|
||||
#else
|
||||
wcstombs(ent->data, ent->wdata, sizeof(ent->data));
|
||||
#endif
|
||||
}
|
|
@ -35,6 +35,7 @@
|
|||
#include <86box/timer.h>
|
||||
#include <86box/network.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/ini.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/video.h>
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/ini.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/midi_rtmidi.h>
|
||||
|
|
|
@ -34,6 +34,7 @@ extern "C"
|
|||
#include <86box/device.h>
|
||||
#include <86box/midi.h>
|
||||
#include <86box/midi_rtmidi.h>
|
||||
#include <86box/ini.h>
|
||||
#include <86box/config.h>
|
||||
|
||||
// Disable c99-designator to avoid the warnings in rtmidi_*_device
|
||||
|
|
Loading…
Add table
Reference in a new issue