mirror of
https://github.com/ksherlock/mpw.git
synced 2025-01-09 13:30:34 +00:00
New environment code
-D command line now supported.
This commit is contained in:
parent
6b383a0e35
commit
e83477c9b2
@ -538,6 +538,8 @@ bool file_exists(const std::string & name)
|
||||
|
||||
std::string find_exe(const std::string &name)
|
||||
{
|
||||
// TODO -- use the environment variable for directories.
|
||||
|
||||
if (file_exists(name)) return name;
|
||||
|
||||
// if name is a path, then it doesn't exist.
|
||||
@ -652,8 +654,10 @@ int main(int argc, char **argv)
|
||||
|
||||
//auto start_time = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::vector<std::string> defines;
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "+hVm:r:s:", LongOpts, NULL)) != -1)
|
||||
while ((c = getopt_long(argc, argv, "+hVm:r:s:D:", LongOpts, NULL)) != -1)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
@ -700,6 +704,10 @@ int main(int argc, char **argv)
|
||||
exit(EX_CONFIG);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
defines.push_back(optarg);
|
||||
break;
|
||||
|
||||
case ':':
|
||||
case '?':
|
||||
help();
|
||||
@ -768,7 +776,7 @@ int main(int argc, char **argv)
|
||||
|
||||
MM::Init(Memory, MemorySize, kGlobalSize);
|
||||
OS::Init();
|
||||
MPW::Init(argc, argv);
|
||||
MPW::Init(argc, argv, defines);
|
||||
|
||||
|
||||
cpuStartup();
|
||||
|
@ -5,33 +5,39 @@ set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall -g")
|
||||
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 epv.cpp ep.cpp)
|
||||
environment.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_custom_command(
|
||||
OUTPUT environ.cpp
|
||||
COMMAND ragel -p -G2 -o environ.cpp "${CMAKE_CURRENT_SOURCE_DIR}/environ.rl"
|
||||
MAIN_DEPENDENCY environ.rl
|
||||
OUTPUT environment.cpp
|
||||
COMMAND ragel -p -G2 -o environment.cpp "${CMAKE_CURRENT_SOURCE_DIR}/environment.rl"
|
||||
MAIN_DEPENDENCY environment.rl
|
||||
)
|
||||
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT epv.cpp
|
||||
COMMAND ragel -p -G2 -o epv.cpp "${CMAKE_CURRENT_SOURCE_DIR}/epv.rl"
|
||||
MAIN_DEPENDENCY epv.rl
|
||||
)
|
||||
# add_custom_command(
|
||||
# OUTPUT epv.cpp
|
||||
# COMMAND ragel -p -G2 -o epv.cpp "${CMAKE_CURRENT_SOURCE_DIR}/epv.rl"
|
||||
# MAIN_DEPENDENCY epv.rl
|
||||
# )
|
||||
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ep.cpp
|
||||
COMMAND ragel -p -G2 -o ep.cpp "${CMAKE_CURRENT_SOURCE_DIR}/ep.rl"
|
||||
MAIN_DEPENDENCY ep.rl
|
||||
)
|
||||
# add_custom_command(
|
||||
# OUTPUT ep.cpp
|
||||
# COMMAND ragel -p -G2 -o ep.cpp "${CMAKE_CURRENT_SOURCE_DIR}/ep.rl"
|
||||
# MAIN_DEPENDENCY ep.rl
|
||||
# )
|
||||
|
||||
|
||||
|
||||
|
||||
set_source_files_properties(
|
||||
environ.cpp ep.cpp epv.cpp
|
||||
environment.cpp # environ.cpp ep.cpp epv.cpp
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -Wno-unused-variable"
|
||||
|
326
mpw/environment.rl
Normal file
326
mpw/environment.rl
Normal file
@ -0,0 +1,326 @@
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace MPW
|
||||
{
|
||||
extern std::unordered_map<std::string, std::string> Environment;
|
||||
|
||||
std::string ExpandVariables(const std::string &s);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
%%{
|
||||
machine name;
|
||||
|
||||
main :=
|
||||
|
||||
[A-Za-z0-9_]+ @{
|
||||
name.push_back(fc);
|
||||
}
|
||||
;
|
||||
|
||||
write data;
|
||||
}%%
|
||||
|
||||
%%{
|
||||
machine assign;
|
||||
|
||||
ws = [ \t\r\n];
|
||||
main :=
|
||||
|
||||
ws*
|
||||
(
|
||||
'=' @{
|
||||
op = 1;
|
||||
}
|
||||
|
|
||||
'+=' @{
|
||||
op = 2;
|
||||
}
|
||||
|
|
||||
'?=' @{
|
||||
op = 3;
|
||||
}
|
||||
)
|
||||
ws*
|
||||
;
|
||||
|
||||
write data;
|
||||
}%%
|
||||
|
||||
%%{
|
||||
machine variables;
|
||||
|
||||
main := |*
|
||||
|
||||
'{' [A-Za-z0-9_]+ '}' {
|
||||
|
||||
std::string name(ts + 1, te - 1);
|
||||
auto iter = Environment.find(name);
|
||||
if (iter != Environment.end())
|
||||
rv.append(iter->second);
|
||||
};
|
||||
|
||||
# backwards compatibility.
|
||||
'${' [A-Za-z0-9_]+ '}' {
|
||||
|
||||
std::string name(ts + 2, te - 1);
|
||||
auto iter = Environment.find(name);
|
||||
if (iter != Environment.end())
|
||||
rv.append(iter->second);
|
||||
};
|
||||
|
||||
# backwards compatibility.
|
||||
'$' [A-Za-z0-9_]+ {
|
||||
std::string name(ts + 1, te);
|
||||
auto iter = Environment.find(name);
|
||||
if (iter != Environment.end())
|
||||
rv.append(iter->second);
|
||||
};
|
||||
|
||||
any {
|
||||
rv.push_back(*ts);
|
||||
};
|
||||
*|;
|
||||
|
||||
write data;
|
||||
}%%
|
||||
|
||||
// split out since goto names conflict.
|
||||
const char* GetName(const char *p, const char *pe, std::string &name)
|
||||
{
|
||||
const char *eof = pe;
|
||||
int cs;
|
||||
|
||||
%%{
|
||||
machine name;
|
||||
write init;
|
||||
write exec;
|
||||
}%%
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
const char *GetAssignment(const char *p, const char *pe, unsigned &op)
|
||||
{
|
||||
const char *eof = pe;
|
||||
int cs;
|
||||
|
||||
%%{
|
||||
machine assign;
|
||||
write init;
|
||||
write exec;
|
||||
}%%
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
bool ParseLine(const char *p, const char *pe)
|
||||
{
|
||||
/*
|
||||
* name = value
|
||||
* name += value
|
||||
* name ?= value
|
||||
*/
|
||||
|
||||
std::string name;
|
||||
unsigned op = 0;
|
||||
|
||||
const char *begin = p;
|
||||
|
||||
// 1. get the name
|
||||
p = GetName(p, pe, name);
|
||||
if (!name.length())
|
||||
{
|
||||
#ifdef TESTING
|
||||
fprintf(stderr, "No Name\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. get the op
|
||||
p = GetAssignment(p, pe, op);
|
||||
if (!op)
|
||||
{
|
||||
fprintf(stderr, "No assignment\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string value(p, pe);
|
||||
value = MPW::ExpandVariables(value);
|
||||
|
||||
auto iter = MPW::Environment.find(name);
|
||||
if (iter == MPW::Environment.end())
|
||||
{
|
||||
MPW::Environment.emplace(std::move(name), std::move(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
case 1: // =
|
||||
iter->second = std::move(value);
|
||||
break;
|
||||
case 2: // +=
|
||||
iter->second += value;
|
||||
break;
|
||||
case 3: // ?=
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace MPW {
|
||||
|
||||
|
||||
std::string GetEnv(const std::string &key)
|
||||
{
|
||||
auto iter = Environment.find(key);
|
||||
if (iter == Environment.end()) return "";
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
std::string ExpandVariables(const std::string &s)
|
||||
{
|
||||
if (s.find_first_of("{$") == s.npos) return s;
|
||||
|
||||
std::string rv;
|
||||
const char *p = s.c_str();
|
||||
const char *pe = p + s.length();
|
||||
const char *eof = pe;
|
||||
const char *te;
|
||||
const char *ts;
|
||||
|
||||
int cs;
|
||||
int act;
|
||||
|
||||
%%{
|
||||
machine variables;
|
||||
|
||||
write init;
|
||||
write exec;
|
||||
}%%
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void EnvLoadArray(const std::vector<std::string> &data)
|
||||
{
|
||||
for (const auto &s : data)
|
||||
{
|
||||
const char *begin = s.c_str();
|
||||
const char *end = begin + s.length();
|
||||
if (!s.length()) continue;
|
||||
if (!ParseLine(begin, end))
|
||||
{
|
||||
fprintf(stderr, "Error in variable: %s\n", s.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EnvLoadFile(const std::string &envfile)
|
||||
{
|
||||
|
||||
FILE *fp;
|
||||
|
||||
|
||||
fp = fopen(envfile.c_str(), "r");
|
||||
|
||||
if (!fp) return;
|
||||
|
||||
|
||||
/*
|
||||
* getline(3) is 2008 posix. it allocates (and resizes as appropriate)
|
||||
* the buffer.
|
||||
*
|
||||
*/
|
||||
char *lineBuffer = NULL;
|
||||
size_t lineSize = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
char *line;
|
||||
ssize_t length;
|
||||
|
||||
length = getline(&lineBuffer, &lineSize, fp);
|
||||
if (!length) continue; //?
|
||||
if (length < 0) break; // eof or error.
|
||||
|
||||
line = lineBuffer;
|
||||
|
||||
// skip any leading space.
|
||||
while (length && isspace(*line))
|
||||
{
|
||||
++line;
|
||||
--length;
|
||||
}
|
||||
if (!length) continue;
|
||||
|
||||
// comments
|
||||
if (*line == '#') continue;
|
||||
|
||||
|
||||
// strip any trailing space.
|
||||
// (will be \n terminated unless there was no \n)
|
||||
while (length && isspace(line[length - 1]))
|
||||
{
|
||||
line[--length] = 0;
|
||||
}
|
||||
if (!length) continue;
|
||||
|
||||
if (!ParseLine(line, line + length))
|
||||
{
|
||||
fprintf(stderr, "Error in variable: %s\n", line);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef TESTING
|
||||
|
||||
namespace MPW
|
||||
{
|
||||
std::unordered_map<std::string, std::string> Environment;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
char *cp = argv[i];
|
||||
int len = strlen(cp);
|
||||
|
||||
if (!ParseLine(cp, cp + len))
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", cp);
|
||||
}
|
||||
}
|
||||
|
||||
MPW::EnvLoadFile("/Users/kelvin/mpw/Environment.text");
|
||||
|
||||
for (auto kv : MPW::Environment)
|
||||
{
|
||||
printf("%s --> %s\n", kv.first.c_str(), kv.second.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
31
mpw/mpw.cpp
31
mpw/mpw.cpp
@ -56,7 +56,7 @@
|
||||
extern char **environ;
|
||||
|
||||
|
||||
namespace MPW { namespace Internal {
|
||||
namespace MPW {
|
||||
|
||||
// for dup counts, etc.
|
||||
//std::vector<int> FDTable;
|
||||
@ -65,12 +65,11 @@ namespace MPW { namespace Internal {
|
||||
|
||||
std::unordered_map<std::string, std::string> Environment;
|
||||
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
namespace MPW
|
||||
{
|
||||
using namespace Internal;
|
||||
|
||||
bool Trace = false;
|
||||
|
||||
@ -222,19 +221,7 @@ namespace MPW
|
||||
return path; // unknown.
|
||||
}
|
||||
|
||||
|
||||
std::string GetEnv(const std::string &name)
|
||||
{
|
||||
static std::string empty;
|
||||
|
||||
auto iter = Environment.find(name);
|
||||
if (iter == Environment.end()) return empty;
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t Init(int argc, char **argv)
|
||||
uint16_t Init(int argc, char **argv, const std::vector<std::string> &defines)
|
||||
{
|
||||
/*
|
||||
FDTable.resize(16);
|
||||
@ -335,6 +322,8 @@ namespace MPW
|
||||
// environment,
|
||||
// just use $MPW and synthesize the other ones.
|
||||
{
|
||||
void EnvLoadFile(const std::string &envfile);
|
||||
void EnvLoadArray(const std::vector<std::string> &data);
|
||||
|
||||
std::string m(RootDir());
|
||||
if (!m.empty())
|
||||
@ -346,13 +335,15 @@ namespace MPW
|
||||
}
|
||||
Environment.emplace(std::string("Command"), command);
|
||||
|
||||
|
||||
if (defines.size())
|
||||
EnvLoadArray(defines);
|
||||
|
||||
if (!m.empty())
|
||||
{
|
||||
|
||||
void LoadEnvironment(std::string &envfile, std::unordered_map<std::string, std::string> &env);
|
||||
|
||||
std::string path(RootDirPathForFile("Environment.text"));
|
||||
LoadEnvironment(path, Environment);
|
||||
EnvLoadFile(path);
|
||||
}
|
||||
|
||||
std::deque<std::string> e;
|
||||
@ -368,7 +359,7 @@ namespace MPW
|
||||
|
||||
|
||||
uint32_t size = 0;
|
||||
for(const std::string &s : e)
|
||||
for (const std::string &s : e)
|
||||
{
|
||||
int l = s.length() + 1;
|
||||
if (l & 0x01) l++;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace MPW {
|
||||
|
||||
@ -99,7 +100,7 @@ namespace MPW {
|
||||
|
||||
|
||||
// should add argc/argv/envp...
|
||||
uint16_t Init(int argc, char **argv);
|
||||
uint16_t Init(int argc, char **argv, const std::vector<std::string> &defines);
|
||||
|
||||
uint32_t ExitStatus();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user