You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
2.4 KiB
147 lines
2.4 KiB
/* |
|
* keyd - A key remapping daemon. |
|
* |
|
* © 2019 Raheman Vaiya (see also: LICENSE). |
|
*/ |
|
#include <ctype.h> |
|
#include <string.h> |
|
#include <assert.h> |
|
#include <unistd.h> |
|
#include <fcntl.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <sys/stat.h> |
|
#include <assert.h> |
|
|
|
#include "ini.h" |
|
#define MAX_INI_SIZE 65536 |
|
|
|
/* |
|
* Parse a value of the form 'key = value'. The value may contain = |
|
* and the key may itself be = as a special case. value may be NULL |
|
* if '=' is not present in the original string. |
|
*/ |
|
|
|
void parse_kvp(char *s, char **key, char **value) |
|
{ |
|
char *last_space = NULL; |
|
char *c = s; |
|
|
|
/* Allow the first character to be = as a special case. */ |
|
if (*c == '=') |
|
c++; |
|
|
|
*key = s; |
|
*value = NULL; |
|
while (*c) { |
|
switch (*c) { |
|
case '=': |
|
if (last_space) |
|
*last_space = 0; |
|
else |
|
*c = 0; |
|
|
|
while (*++c == ' '); |
|
|
|
*value = c; |
|
return; |
|
case ' ': |
|
if (!last_space) |
|
last_space = c; |
|
break; |
|
default: |
|
last_space = NULL; |
|
break; |
|
} |
|
|
|
c++; |
|
} |
|
} |
|
|
|
/* |
|
* The result is statically allocated and should not be freed by the caller. |
|
* The returned struct is only valid until the next invocation. The |
|
* input string may be modified and should only be freed after the |
|
* returned ini struct is no longer required. |
|
*/ |
|
|
|
struct ini *ini_parse_string(char *s, const char *default_section_name) |
|
{ |
|
static struct ini ini; |
|
|
|
int ln = 0; |
|
size_t n = 0; |
|
|
|
struct ini_section *section = NULL; |
|
|
|
while (s) { |
|
size_t len; |
|
struct ini_entry *ent; |
|
char *line; |
|
|
|
ln++; |
|
|
|
line = s; |
|
s = strchr(s, '\n'); |
|
|
|
if (s) { |
|
*s = 0; |
|
s++; |
|
} |
|
|
|
|
|
while (isspace(line[0])) |
|
line++; |
|
|
|
len = strlen(line); |
|
|
|
while(len > 0 && isspace(line[len-1])) |
|
len--; |
|
|
|
if (line[0] == 0) |
|
continue; |
|
|
|
line[len] = 0; |
|
|
|
switch (line[0]) { |
|
case '[': |
|
if (line[len-1] == ']') { |
|
assert(n < MAX_SECTIONS); |
|
|
|
section = &ini.sections[n++]; |
|
|
|
line[len-1] = 0; |
|
|
|
strncpy(section->name, line+1, sizeof(section->name)); |
|
section->nr_entries = 0; |
|
section->lnum = ln; |
|
|
|
continue; |
|
} |
|
|
|
break; |
|
case '#': |
|
continue; |
|
} |
|
|
|
if (!section) { |
|
if(default_section_name) { |
|
section = &ini.sections[n++]; |
|
strcpy(section->name, default_section_name); |
|
|
|
section->nr_entries = 0; |
|
section->lnum = 0; |
|
} else |
|
return NULL; |
|
} |
|
|
|
assert(section->nr_entries < MAX_SECTION_ENTRIES); |
|
|
|
ent = §ion->entries[section->nr_entries++]; |
|
parse_kvp(line, &ent->key, &ent->val); |
|
ent->lnum = ln; |
|
} |
|
|
|
ini.nr_sections = n; |
|
return &ini; |
|
}
|
|
|