From 1a9aefdd006b660093283b039bfa8931319f8ae3 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sat, 30 Apr 2016 17:38:30 -0700 Subject: Split out config string parser --- machine/configstring.c | 160 +---------------------------------------------- machine/configstring.h | 166 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 159 deletions(-) create mode 100644 machine/configstring.h diff --git a/machine/configstring.c b/machine/configstring.c index 3d0eda3..d2f2a84 100644 --- a/machine/configstring.c +++ b/machine/configstring.c @@ -1,166 +1,8 @@ +#include "configstring.h" #include "encoding.h" #include "mtrap.h" #include -static const char* skip_whitespace(const char* str) -{ - while (*str && *str <= ' ') - str++; - return str; -} - -static const char* skip_string(const char* str) -{ - while (*str && *str++ != '"') - ; - return str; -} - -static int is_hex(char ch) -{ - return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); -} - -static int parse_hex(char ch) -{ - return (ch >= '0' && ch <= '9') ? ch - '0' : - (ch >= 'a' && ch <= 'f') ? ch - 'a' + 10 : - ch - 'A' + 10; -} - -static const char* skip_key(const char* str) -{ - while (*str >= 35 && *str <= 122 && *str != ';') - str++; - return str; -} - -typedef struct { - const char* start; - const char* end; -} query_result; - -static query_result query_config_string(const char* str, const char* k) -{ - size_t ksize = 0; - while (k[ksize] && k[ksize] != '{') - ksize++; - int last = !k[ksize]; - - query_result res = {0, 0}; - while (1) { - const char* key_start = str = skip_whitespace(str); - const char* key_end = str = skip_key(str); - int match = (key_end - key_start) == ksize; - if (match) - for (size_t i = 0; i < ksize; i++) - if (key_start[i] != k[i]) - match = 0; - const char* value_start = str = skip_whitespace(str); - while (*str != ';') { - if (!*str) { - return res; - } else if (*str == '"') { - str = skip_string(str+1); - } else if (*str == '{') { - const char* search_key = match && !last ? k + ksize + 1 : ""; - query_result inner_res = query_config_string(str + 1, search_key); - if (inner_res.start) - return inner_res; - str = inner_res.end + 1; - } else { - str = skip_key(str); - } - str = skip_whitespace(str); - } - res.end = str; - if (match && last) { - res.start = value_start; - return res; - } - str = skip_whitespace(str+1); - if (*str == '}') { - res.end = str; - return res; - } - } -} - -static void parse_string(query_result r, char* buf) -{ - if (r.start < r.end) { - if (*r.start == '"') { - for (const char* p = r.start + 1; p < r.end && *p != '"'; p++) { - char ch = p[0]; - if (ch == '\\' && p[1] == 'x' && is_hex(p[2])) { - ch = parse_hex(p[2]); - if (is_hex(p[3])) { - ch = (ch << 4) + parse_hex(p[3]); - p++; - } - p += 2; - } - *buf++ = ch; - } - } else { - for (const char* p = r.start; p < r.end && *p > ' '; p++) - *buf++ = *p; - } - } - *buf = 0; -} - -#define get_string(name, search_res) \ - char name[(search_res).end - (search_res).start + 1]; \ - parse_string(search_res, name) - -static unsigned long __get_uint_hex(const char* s) -{ - unsigned long res = 0; - while (*s) { - if (is_hex(*s)) - res = (res << 4) + parse_hex(*s); - else if (*s != '_') - break; - s++; - } - return res; -} - -static unsigned long __get_uint_dec(const char* s) -{ - unsigned long res = 0; - while (*s) { - if (*s >= '0' && *s <= '9') - res = res * 10 + (*s - '0'); - else - break; - s++; - } - return res; -} - -static unsigned long __get_uint(const char* s) -{ - if (s[0] == '0' && s[1] == 'x') - return __get_uint_hex(s+2); - return __get_uint_dec(s); -} - -static unsigned long get_uint(query_result res) -{ - get_string(s, res); - return __get_uint(s); -} - -static long get_sint(query_result res) -{ - get_string(s, res); - if (s[0] == '-') - return -__get_uint(s+1); - return __get_uint(s); -} - static void query_mem(const char* config_string) { query_result res = query_config_string(config_string, "ram{0{addr"); diff --git a/machine/configstring.h b/machine/configstring.h new file mode 100644 index 0000000..39538c9 --- /dev/null +++ b/machine/configstring.h @@ -0,0 +1,166 @@ +#ifndef RISCV_CONFIG_STRING_H +#define RISCV_CONFIG_STRING_H + +#include +#include + +static const char* skip_whitespace(const char* str) +{ + while (*str && *str <= ' ') + str++; + return str; +} + +static const char* skip_string(const char* str) +{ + while (*str && *str++ != '"') + ; + return str; +} + +static int is_hex(char ch) +{ + return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); +} + +static int parse_hex(char ch) +{ + return (ch >= '0' && ch <= '9') ? ch - '0' : + (ch >= 'a' && ch <= 'f') ? ch - 'a' + 10 : + ch - 'A' + 10; +} + +static const char* skip_key(const char* str) +{ + while (*str >= 35 && *str <= 122 && *str != ';') + str++; + return str; +} + +typedef struct { + const char* start; + const char* end; +} query_result; + +static query_result query_config_string(const char* str, const char* k) +{ + size_t ksize = 0; + while (k[ksize] && k[ksize] != '{') + ksize++; + int last = !k[ksize]; + + query_result res = {0, 0}; + while (1) { + const char* key_start = str = skip_whitespace(str); + const char* key_end = str = skip_key(str); + int match = (size_t)(key_end - key_start) == ksize; + if (match) + for (size_t i = 0; i < ksize; i++) + if (key_start[i] != k[i]) + match = 0; + const char* value_start = str = skip_whitespace(str); + while (*str != ';') { + if (!*str) { + return res; + } else if (*str == '"') { + str = skip_string(str+1); + } else if (*str == '{') { + const char* search_key = match && !last ? k + ksize + 1 : ""; + query_result inner_res = query_config_string(str + 1, search_key); + if (inner_res.start) + return inner_res; + str = inner_res.end + 1; + } else { + str = skip_key(str); + } + str = skip_whitespace(str); + } + res.end = str; + if (match && last) { + res.start = value_start; + return res; + } + str = skip_whitespace(str+1); + if (*str == '}') { + res.end = str; + return res; + } + } +} + +static void parse_string(query_result r, char* buf) +{ + if (r.start < r.end) { + if (*r.start == '"') { + for (const char* p = r.start + 1; p < r.end && *p != '"'; p++) { + char ch = p[0]; + if (ch == '\\' && p[1] == 'x' && is_hex(p[2])) { + ch = parse_hex(p[2]); + if (is_hex(p[3])) { + ch = (ch << 4) + parse_hex(p[3]); + p++; + } + p += 2; + } + *buf++ = ch; + } + } else { + for (const char* p = r.start; p < r.end && *p > ' '; p++) + *buf++ = *p; + } + } + *buf = 0; +} + +#define get_string(name, search_res) \ + char name[(search_res).end - (search_res).start + 1]; \ + parse_string(search_res, name) + +static uint64_t __get_uint_hex(const char* s) +{ + uint64_t res = 0; + while (*s) { + if (is_hex(*s)) + res = (res << 4) + parse_hex(*s); + else if (*s != '_') + break; + s++; + } + return res; +} + +static uint64_t __get_uint_dec(const char* s) +{ + uint64_t res = 0; + while (*s) { + if (*s >= '0' && *s <= '9') + res = res * 10 + (*s - '0'); + else + break; + s++; + } + return res; +} + +static uint64_t __get_uint(const char* s) +{ + if (s[0] == '0' && s[1] == 'x') + return __get_uint_hex(s+2); + return __get_uint_dec(s); +} + +static inline uint64_t get_uint(query_result res) +{ + get_string(s, res); + return __get_uint(s); +} + +static inline int64_t get_sint(query_result res) +{ + get_string(s, res); + if (s[0] == '-') + return -__get_uint(s+1); + return __get_uint(s); +} + +#endif -- cgit v1.1