New config parser
Basically a subset of Bourne shell.
This commit is contained in:
parent
e80c56e249
commit
3624636c2f
59
sdn.cpp
59
sdn.cpp
@ -130,6 +130,51 @@ fun shell_escape (const string &v) -> string {
|
||||
return "'" + result + "'";
|
||||
}
|
||||
|
||||
fun parse_line (istream &is, vector<string> &out) -> bool {
|
||||
enum {STA, DEF, COM, ESC, WOR, QUO, STATES};
|
||||
enum {TAKE = 1 << 3, PUSH = 1 << 4, STOP = 1 << 5, ERROR = 1 << 6};
|
||||
enum {TWOR = TAKE | WOR};
|
||||
|
||||
// We never transition back to the start state, so it can stay as a noop
|
||||
static char table[STATES][7] = {
|
||||
// state EOF SP, TAB ' # \ LF default
|
||||
/* STA */ {ERROR, DEF, QUO, COM, ESC, STOP, TWOR},
|
||||
/* DEF */ {STOP, 0, QUO, COM, ESC, STOP, TWOR},
|
||||
/* COM */ {STOP, 0, 0, 0, 0, STOP, 0},
|
||||
/* ESC */ {ERROR, TWOR, TWOR, TWOR, TWOR, TWOR, TWOR},
|
||||
/* WOR */ {STOP | PUSH, DEF | PUSH, QUO, TAKE, ESC, STOP | PUSH, TAKE},
|
||||
/* QUO */ {ERROR, TAKE, WOR, TAKE, TAKE, TAKE, TAKE},
|
||||
};
|
||||
|
||||
out.clear (); string token; int state = STA;
|
||||
constexpr auto eof = istream::traits_type::eof ();
|
||||
while (1) {
|
||||
int ch = is.get (), edge = 0;
|
||||
switch (ch) {
|
||||
case eof: edge = table[state][0]; break;
|
||||
case '\t':
|
||||
case ' ': edge = table[state][1]; break;
|
||||
case '\'': edge = table[state][2]; break;
|
||||
case '#': edge = table[state][3]; break;
|
||||
case '\\': edge = table[state][4]; break;
|
||||
case '\n': edge = table[state][5]; break;
|
||||
default: edge = table[state][6]; break;
|
||||
}
|
||||
if (edge & TAKE)
|
||||
token += ch;
|
||||
if (edge & PUSH) {
|
||||
out.push_back (token);
|
||||
token.clear ();
|
||||
}
|
||||
if (edge & STOP)
|
||||
return true;
|
||||
if (edge & ERROR)
|
||||
return false;
|
||||
if (edge &= 7)
|
||||
state = edge;
|
||||
}
|
||||
}
|
||||
|
||||
fun decode_type (mode_t m) -> wchar_t {
|
||||
if (S_ISDIR (m)) return L'd'; if (S_ISBLK (m)) return L'b';
|
||||
if (S_ISCHR (m)) return L'c'; if (S_ISLNK (m)) return L'l';
|
||||
@ -1006,10 +1051,9 @@ fun load_colors () {
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
string line;
|
||||
while (getline (*config, line)) {
|
||||
auto tokens = split (line, " ");
|
||||
if (tokens.empty () || line.front () == '#')
|
||||
vector<string> tokens;
|
||||
while (parse_line (*config, tokens)) {
|
||||
if (tokens.empty ())
|
||||
continue;
|
||||
auto name = shift (tokens);
|
||||
for (int i = 0; i < g.AT_COUNT; i++)
|
||||
@ -1105,10 +1149,9 @@ fun load_bindings () {
|
||||
actions[name] = action (a++);
|
||||
}
|
||||
|
||||
string line;
|
||||
while (getline (*config, line)) {
|
||||
auto tokens = split (line, " ");
|
||||
if (tokens.empty () || line.front () == '#')
|
||||
vector<string> tokens;
|
||||
while (parse_line (*config, tokens)) {
|
||||
if (tokens.empty ())
|
||||
continue;
|
||||
if (tokens.size () < 3) {
|
||||
cerr << "bindings: expected: context binding action";
|
||||
|
Loading…
Reference in New Issue
Block a user