mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-25 19:30:50 +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)
|
||||
|
||||
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})
|
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