mirror of
https://github.com/ksherlock/mpw.git
synced 2024-12-01 13:52:22 +00:00
ragel environment parser.
This commit is contained in:
parent
9312383433
commit
75ad0ab38c
@ -6,6 +6,11 @@ add_definitions(-I ${CMAKE_SOURCE_DIR}/)
|
|||||||
|
|
||||||
set(MPW_SRC mpw.cpp mpw_io.cpp mpw_close.cpp mpw_access.cpp mpw_ioctl.cpp environ.cpp)
|
set(MPW_SRC mpw.cpp mpw_io.cpp mpw_close.cpp mpw_access.cpp mpw_ioctl.cpp environ.cpp)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT environ.cpp
|
||||||
|
COMMAND ragel -p -G2 -o environ.cpp "${CMAKE_CURRENT_SOURCE_DIR}/environ.rl"
|
||||||
|
MAIN_DEPENDENCY environ.rl
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
add_library(MPW_LIB ${MPW_SRC})
|
add_library(MPW_LIB ${MPW_SRC})
|
356
mpw/environ.cpp
356
mpw/environ.cpp
@ -1,356 +0,0 @@
|
|||||||
/* Generated by re2c 0.13.5 on Sat May 18 16:26:02 2013 */
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* #...comment
|
|
||||||
* var=value
|
|
||||||
* where value may contain $var and ${var} interpolations.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace MPW {
|
|
||||||
std::string EvalString(std::string &s, std::unordered_map<std::string, std::string> &env)
|
|
||||||
{
|
|
||||||
|
|
||||||
std::string rv;
|
|
||||||
const char *cp = s.c_str();
|
|
||||||
const char *marker = NULL;
|
|
||||||
|
|
||||||
while (*cp)
|
|
||||||
{
|
|
||||||
const char *begin = cp;
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
char yych;
|
|
||||||
|
|
||||||
yych = (char)*cp;
|
|
||||||
switch (yych) {
|
|
||||||
case '\n': goto yy5;
|
|
||||||
case '$': goto yy2;
|
|
||||||
default: goto yy4;
|
|
||||||
}
|
|
||||||
yy2:
|
|
||||||
yych = (char)*(marker = ++cp);
|
|
||||||
switch (yych) {
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
case 'A':
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
case 'D':
|
|
||||||
case 'E':
|
|
||||||
case 'F':
|
|
||||||
case 'G':
|
|
||||||
case 'H':
|
|
||||||
case 'I':
|
|
||||||
case 'J':
|
|
||||||
case 'K':
|
|
||||||
case 'L':
|
|
||||||
case 'M':
|
|
||||||
case 'N':
|
|
||||||
case 'O':
|
|
||||||
case 'P':
|
|
||||||
case 'Q':
|
|
||||||
case 'R':
|
|
||||||
case 'S':
|
|
||||||
case 'T':
|
|
||||||
case 'U':
|
|
||||||
case 'V':
|
|
||||||
case 'W':
|
|
||||||
case 'X':
|
|
||||||
case 'Y':
|
|
||||||
case 'Z':
|
|
||||||
case '_':
|
|
||||||
case 'a':
|
|
||||||
case 'b':
|
|
||||||
case 'c':
|
|
||||||
case 'd':
|
|
||||||
case 'e':
|
|
||||||
case 'f':
|
|
||||||
case 'g':
|
|
||||||
case 'h':
|
|
||||||
case 'i':
|
|
||||||
case 'j':
|
|
||||||
case 'k':
|
|
||||||
case 'l':
|
|
||||||
case 'm':
|
|
||||||
case 'n':
|
|
||||||
case 'o':
|
|
||||||
case 'p':
|
|
||||||
case 'q':
|
|
||||||
case 'r':
|
|
||||||
case 's':
|
|
||||||
case 't':
|
|
||||||
case 'u':
|
|
||||||
case 'v':
|
|
||||||
case 'w':
|
|
||||||
case 'x':
|
|
||||||
case 'y':
|
|
||||||
case 'z': goto yy9;
|
|
||||||
case '{': goto yy7;
|
|
||||||
default: goto yy3;
|
|
||||||
}
|
|
||||||
yy3:
|
|
||||||
{
|
|
||||||
rv.push_back(*begin);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
yy4:
|
|
||||||
yych = (char)*++cp;
|
|
||||||
goto yy3;
|
|
||||||
yy5:
|
|
||||||
++cp;
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
yy7:
|
|
||||||
yych = (char)*++cp;
|
|
||||||
switch (yych) {
|
|
||||||
case '}': goto yy8;
|
|
||||||
default: goto yy13;
|
|
||||||
}
|
|
||||||
yy8:
|
|
||||||
cp = marker;
|
|
||||||
goto yy3;
|
|
||||||
yy9:
|
|
||||||
++cp;
|
|
||||||
yych = (char)*cp;
|
|
||||||
switch (yych) {
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
case 'A':
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
case 'D':
|
|
||||||
case 'E':
|
|
||||||
case 'F':
|
|
||||||
case 'G':
|
|
||||||
case 'H':
|
|
||||||
case 'I':
|
|
||||||
case 'J':
|
|
||||||
case 'K':
|
|
||||||
case 'L':
|
|
||||||
case 'M':
|
|
||||||
case 'N':
|
|
||||||
case 'O':
|
|
||||||
case 'P':
|
|
||||||
case 'Q':
|
|
||||||
case 'R':
|
|
||||||
case 'S':
|
|
||||||
case 'T':
|
|
||||||
case 'U':
|
|
||||||
case 'V':
|
|
||||||
case 'W':
|
|
||||||
case 'X':
|
|
||||||
case 'Y':
|
|
||||||
case 'Z':
|
|
||||||
case '_':
|
|
||||||
case 'a':
|
|
||||||
case 'b':
|
|
||||||
case 'c':
|
|
||||||
case 'd':
|
|
||||||
case 'e':
|
|
||||||
case 'f':
|
|
||||||
case 'g':
|
|
||||||
case 'h':
|
|
||||||
case 'i':
|
|
||||||
case 'j':
|
|
||||||
case 'k':
|
|
||||||
case 'l':
|
|
||||||
case 'm':
|
|
||||||
case 'n':
|
|
||||||
case 'o':
|
|
||||||
case 'p':
|
|
||||||
case 'q':
|
|
||||||
case 'r':
|
|
||||||
case 's':
|
|
||||||
case 't':
|
|
||||||
case 'u':
|
|
||||||
case 'v':
|
|
||||||
case 'w':
|
|
||||||
case 'x':
|
|
||||||
case 'y':
|
|
||||||
case 'z': goto yy9;
|
|
||||||
default: goto yy11;
|
|
||||||
}
|
|
||||||
yy11:
|
|
||||||
{
|
|
||||||
std::string tmp(begin + 1, cp);
|
|
||||||
|
|
||||||
// lookup value...
|
|
||||||
// append to rv.
|
|
||||||
auto iter = env.find(tmp);
|
|
||||||
if (iter != env.end())
|
|
||||||
{
|
|
||||||
rv.append(iter->second);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
yy12:
|
|
||||||
++cp;
|
|
||||||
yych = (char)*cp;
|
|
||||||
yy13:
|
|
||||||
switch (yych) {
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
case 'A':
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
case 'D':
|
|
||||||
case 'E':
|
|
||||||
case 'F':
|
|
||||||
case 'G':
|
|
||||||
case 'H':
|
|
||||||
case 'I':
|
|
||||||
case 'J':
|
|
||||||
case 'K':
|
|
||||||
case 'L':
|
|
||||||
case 'M':
|
|
||||||
case 'N':
|
|
||||||
case 'O':
|
|
||||||
case 'P':
|
|
||||||
case 'Q':
|
|
||||||
case 'R':
|
|
||||||
case 'S':
|
|
||||||
case 'T':
|
|
||||||
case 'U':
|
|
||||||
case 'V':
|
|
||||||
case 'W':
|
|
||||||
case 'X':
|
|
||||||
case 'Y':
|
|
||||||
case 'Z':
|
|
||||||
case '_':
|
|
||||||
case 'a':
|
|
||||||
case 'b':
|
|
||||||
case 'c':
|
|
||||||
case 'd':
|
|
||||||
case 'e':
|
|
||||||
case 'f':
|
|
||||||
case 'g':
|
|
||||||
case 'h':
|
|
||||||
case 'i':
|
|
||||||
case 'j':
|
|
||||||
case 'k':
|
|
||||||
case 'l':
|
|
||||||
case 'm':
|
|
||||||
case 'n':
|
|
||||||
case 'o':
|
|
||||||
case 'p':
|
|
||||||
case 'q':
|
|
||||||
case 'r':
|
|
||||||
case 's':
|
|
||||||
case 't':
|
|
||||||
case 'u':
|
|
||||||
case 'v':
|
|
||||||
case 'w':
|
|
||||||
case 'x':
|
|
||||||
case 'y':
|
|
||||||
case 'z': goto yy12;
|
|
||||||
case '}': goto yy14;
|
|
||||||
default: goto yy8;
|
|
||||||
}
|
|
||||||
yy14:
|
|
||||||
++cp;
|
|
||||||
{
|
|
||||||
|
|
||||||
std::string tmp(begin + 2, cp - 1);
|
|
||||||
|
|
||||||
auto iter = env.find(tmp);
|
|
||||||
if (iter != env.end())
|
|
||||||
{
|
|
||||||
rv.append(iter->second);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadEnvironment(std::string &envfile, std::unordered_map<std::string, std::string> &env)
|
|
||||||
{
|
|
||||||
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
|
|
||||||
fp = fopen(envfile.c_str(), "r");
|
|
||||||
|
|
||||||
if (!fp) return;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
char *begin;
|
|
||||||
char *end;
|
|
||||||
char *iter;
|
|
||||||
|
|
||||||
size_t length;
|
|
||||||
|
|
||||||
begin = fgetln(fp, &length);
|
|
||||||
if (!begin) break; // eof or error.
|
|
||||||
|
|
||||||
if (!length) continue;
|
|
||||||
if (begin[0] == '#') continue;
|
|
||||||
|
|
||||||
while (length && isspace(begin[length - 1])) --length;
|
|
||||||
if (!length) continue;
|
|
||||||
|
|
||||||
// key=value
|
|
||||||
|
|
||||||
// ehh, this could really check for [A-Za-z0-9_]+ '='
|
|
||||||
|
|
||||||
end = begin + length;
|
|
||||||
iter = std::find(begin, end, '=');
|
|
||||||
|
|
||||||
if (iter == end || iter == begin)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Invalid Environment entry: %.*s\n", (int)length, begin);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string key(begin, iter);
|
|
||||||
std::string value(iter + 1, end);
|
|
||||||
|
|
||||||
value = EvalString(value, env);
|
|
||||||
|
|
||||||
//fprintf(stdout, "%s = %s\n", key.c_str(), value.c_str());
|
|
||||||
|
|
||||||
// todo -- does this replace an existing value?
|
|
||||||
env.emplace(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
145
mpw/environ.rl
Normal file
145
mpw/environ.rl
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
|
||||||
|
%%{
|
||||||
|
|
||||||
|
machine lexer;
|
||||||
|
|
||||||
|
|
||||||
|
ws = [ \t\r\n];
|
||||||
|
|
||||||
|
word = [A-Za-z0-9_];
|
||||||
|
|
||||||
|
action emplace {
|
||||||
|
//printf("emplacing %s\n", name.c_str());
|
||||||
|
// trim any whitespace.
|
||||||
|
while (value.length() && isspace(value.back()))
|
||||||
|
value.pop_back();
|
||||||
|
env[std::move(name)] = std::move(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
action error {
|
||||||
|
fprintf(stderr, "Bad environment: %.*s\n", (int)length, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
value := |*
|
||||||
|
|
||||||
|
'$' word+ => {
|
||||||
|
std::string name(ts + 1, te);
|
||||||
|
auto iter = env.find(name);
|
||||||
|
if (iter != env.end())
|
||||||
|
value.append(iter->second);
|
||||||
|
};
|
||||||
|
|
||||||
|
'${' word+ '}' => {
|
||||||
|
std::string name(ts + 2, te - 1);
|
||||||
|
auto iter = env.find(name);
|
||||||
|
if (iter != env.end())
|
||||||
|
value.append(iter->second);
|
||||||
|
};
|
||||||
|
|
||||||
|
'$$' => {
|
||||||
|
value.push_back('$');
|
||||||
|
};
|
||||||
|
|
||||||
|
any $eof(emplace) => {
|
||||||
|
value.push_back(fc);
|
||||||
|
} ;
|
||||||
|
|
||||||
|
*|;
|
||||||
|
|
||||||
|
|
||||||
|
# exit w/ cs = lexer_en_comment.
|
||||||
|
|
||||||
|
comment := any* ${ fbreak; };
|
||||||
|
|
||||||
|
assignment =
|
||||||
|
word+ ${ name.push_back(fc); }
|
||||||
|
ws* %eof(error)
|
||||||
|
'='
|
||||||
|
ws*
|
||||||
|
(any - ws)? ${ fhold; fgoto value; }
|
||||||
|
%eof(emplace)
|
||||||
|
;
|
||||||
|
|
||||||
|
main := ws* ( '#' ${ fgoto comment; } | assignment);
|
||||||
|
|
||||||
|
}%%
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
namespace MPW {
|
||||||
|
|
||||||
|
void LoadEnvironment(std::string &envfile, std::unordered_map<std::string, std::string> &env)
|
||||||
|
{
|
||||||
|
%% write data;
|
||||||
|
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
|
||||||
|
fp = fopen(envfile.c_str(), "r");
|
||||||
|
|
||||||
|
if (!fp) return;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
const char *line;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
line = fgetln(fp, &length);
|
||||||
|
if (!line) break; // eof or error.
|
||||||
|
|
||||||
|
// strip any trailign space.
|
||||||
|
while (length && isspace(line[length - 1]))
|
||||||
|
length--;
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string value;
|
||||||
|
|
||||||
|
const char *p = line;
|
||||||
|
const char *pe = line + length;
|
||||||
|
const char *eof = line + length;
|
||||||
|
const char *te;
|
||||||
|
const char *ts;
|
||||||
|
|
||||||
|
int cs, act;
|
||||||
|
|
||||||
|
%%write init;
|
||||||
|
%%write exec;
|
||||||
|
|
||||||
|
if (cs == lexer_error)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Bad environment: %.*s\n", (int)length, line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, std::string> env;
|
||||||
|
std::string f(argv[i]);
|
||||||
|
|
||||||
|
MPW::LoadEnvironment(f, env);
|
||||||
|
|
||||||
|
for (const auto &kv : env)
|
||||||
|
{
|
||||||
|
printf("%s -> %s\n", kv.first.c_str(), kv.second.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user