290 lines
6.1 KiB
C
290 lines
6.1 KiB
C
#define RENDER() extern "C" void render()
|
|
|
|
string process_html_literal(SharedUnit* su, string content)
|
|
{
|
|
string pc;
|
|
string HT_START = "context->print(R\"(";
|
|
string HT_END = ")\");";
|
|
|
|
u8 mode = 0;
|
|
bool inside_quote = false;
|
|
string code_buffer = "";
|
|
bool is_field = false;
|
|
|
|
for(u32 i = 0; i < content.length(); i++)
|
|
{
|
|
char c = content[i];
|
|
if(mode == 1)
|
|
{
|
|
if(c == '\"')
|
|
{
|
|
inside_quote = !inside_quote;
|
|
code_buffer.append(1, c);
|
|
}
|
|
else if(c == '?' && content[i+1] == '>')
|
|
{
|
|
mode = 0;
|
|
i += 1;
|
|
if(is_field)
|
|
{
|
|
pc.append(
|
|
HT_END +
|
|
"echo(html_escape( " +
|
|
code_buffer +
|
|
" )); " +
|
|
HT_START
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pc.append(HT_END + code_buffer + HT_START);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
code_buffer.append(1, c);
|
|
}
|
|
}
|
|
else if(!inside_quote && c == '<' && content[i+1] == '?')
|
|
{
|
|
code_buffer = "";
|
|
if(content[i+2] == '=')
|
|
{
|
|
is_field = true;
|
|
i += 2;
|
|
}
|
|
else
|
|
{
|
|
is_field = false;
|
|
i += 1;
|
|
}
|
|
mode = 1;
|
|
}
|
|
/*else if(c == '\"')
|
|
{
|
|
inside_quote = !inside_quote;
|
|
pc.append(1, c);
|
|
}*/
|
|
else
|
|
{
|
|
pc.append(1, c);
|
|
}
|
|
}
|
|
|
|
return(HT_START + pc + HT_END);
|
|
}
|
|
|
|
string preprocess_shared_unit(SharedUnit* su)
|
|
{
|
|
string content = file_get_contents(su->file_name);
|
|
printf("(c) compiling with root dir %s\n", context->server->config.COMPILER_SYS_PATH.c_str());
|
|
string pc = ("#include \"")+context->server->config.COMPILER_SYS_PATH +"/src/lib/uce_gen.h\" \n";
|
|
string token = "";
|
|
string html_buffer = "";
|
|
u8 mode = 0;
|
|
bool inside_quote = false;
|
|
for(u32 i = 0; i < content.length(); i++)
|
|
{
|
|
char c = content[i];
|
|
if(mode == 2)
|
|
{
|
|
auto end_pos = content.find(string("</")+token+">", i);
|
|
if(end_pos != string::npos)
|
|
{
|
|
u32 len = token.length() + 3 + end_pos - i;
|
|
html_buffer.append(content.substr(i, len - (token.length() == 0 ? 3 : 0)));
|
|
i += len - 1;
|
|
pc.append(process_html_literal(su, html_buffer));
|
|
}
|
|
else
|
|
{
|
|
printf("(!) unterminated HTML literal <%s> in %s", token.c_str(), su->file_name.c_str());
|
|
}
|
|
mode = 0;
|
|
}
|
|
else if(mode == 1)
|
|
{
|
|
if(isspace(c) || c == '>')
|
|
{
|
|
mode = 2;
|
|
if(token.length() > 0)
|
|
html_buffer.append(1, c);
|
|
}
|
|
else
|
|
{
|
|
token.append(1, c);
|
|
html_buffer.append(1, c);
|
|
}
|
|
}
|
|
else if(!inside_quote && c == '<' && (content[i+1] == '>' || isalpha(content[i+1])))
|
|
{
|
|
mode = 1;
|
|
token = "";
|
|
html_buffer = "";
|
|
if(content[i+1] != '>')
|
|
html_buffer.append(1, c);
|
|
}
|
|
else if(c == '\"')
|
|
{
|
|
inside_quote = !inside_quote;
|
|
pc.append(1, c);
|
|
}
|
|
else
|
|
{
|
|
pc.append(1, c);
|
|
}
|
|
}
|
|
return(pc);
|
|
}
|
|
|
|
void setup_unit_paths(SharedUnit* su, string file_name)
|
|
{
|
|
su->file_name = file_name;
|
|
|
|
if(su->src_path.length() > 0) // we did this already
|
|
return;
|
|
|
|
su->src_path = dirname(file_name);
|
|
su->bin_path = context->server->config.BIN_DIRECTORY + su->src_path;
|
|
su->pre_path = context->server->config.BIN_DIRECTORY + su->src_path;
|
|
|
|
su->src_file_name = basename(file_name);
|
|
su->bin_file_name = su->src_file_name + ".so";
|
|
su->pre_file_name = su->src_file_name + ".cpp";
|
|
|
|
su->so_name = su->bin_path + "/" + su->bin_file_name;
|
|
}
|
|
|
|
void load_shared_unit(SharedUnit* su, string file_name)
|
|
{
|
|
setup_unit_paths(su, file_name);
|
|
|
|
su->on_render = 0;
|
|
su->on_setup = 0;
|
|
su->compiler_messages = "";
|
|
|
|
if(!file_exists(su->so_name))
|
|
{
|
|
printf("(i) unit file not found: %s\n", su->so_name.c_str());
|
|
su->compiler_messages = "unit file not found";
|
|
return;
|
|
}
|
|
|
|
su->so_handle = dlopen(su->so_name.c_str(), RTLD_NOW);
|
|
if(su->so_handle)
|
|
{
|
|
su->last_compiled = file_mtime(su->so_name);
|
|
char *error;
|
|
su->on_setup = (request_handler)dlsym(su->so_handle, "set_current_request");
|
|
su->on_render = (call_handler)dlsym(su->so_handle, "render");
|
|
if ((error = dlerror()) != NULL)
|
|
printf("Error - %s in %s\n", error, su->file_name.c_str());
|
|
else
|
|
printf("(i) loaded unit %s\n", su->file_name.c_str());
|
|
}
|
|
else
|
|
{
|
|
printf("Error loading unit %s, could not open %s\n", su->file_name.c_str(), su->so_name.c_str());
|
|
}
|
|
}
|
|
|
|
void compile_shared_unit(SharedUnit* su, string file_name)
|
|
{
|
|
setup_unit_paths(su, file_name);
|
|
|
|
if(!file_exists(su->file_name))
|
|
{
|
|
su->compiler_messages = "source file not found";
|
|
return;
|
|
}
|
|
|
|
shell_exec("mkdir -p " + shell_escape(su->pre_path));
|
|
file_put_contents(su->pre_path + "/" + su->pre_file_name, preprocess_shared_unit(su));
|
|
|
|
printf("Config.COMPILE_SCRIPT %s\n", string(su->pre_path + "/" + su->pre_file_name).c_str());
|
|
|
|
su->compiler_messages = trim(shell_exec(context->server->config.COMPILE_SCRIPT+" "+
|
|
shell_escape(su->src_path)+" "+
|
|
shell_escape(su->bin_path)+" "+
|
|
shell_escape(su->file_name)+" "+
|
|
shell_escape(su->pre_file_name)+" "+
|
|
shell_escape(su->bin_file_name)
|
|
));
|
|
|
|
if(su->compiler_messages.length() > 0)
|
|
{
|
|
printf("%s \n", su->compiler_messages.c_str());
|
|
}
|
|
else
|
|
{
|
|
load_shared_unit(su, file_name);
|
|
printf("(i) compiled unit %s\n", file_name.c_str());
|
|
}
|
|
}
|
|
|
|
SharedUnit* get_shared_unit(string file_name)
|
|
{
|
|
SharedUnit* su = context->server->units[file_name];
|
|
auto mod_time = file_mtime(file_name);
|
|
bool do_recompile = false;
|
|
if(su && (su->last_compiled < mod_time || mod_time == 0))
|
|
{
|
|
delete su;
|
|
su = 0;
|
|
do_recompile = true;
|
|
}
|
|
if(!su)
|
|
{
|
|
su = new SharedUnit();
|
|
|
|
if(do_recompile)
|
|
{
|
|
compile_shared_unit(su, file_name);
|
|
}
|
|
else
|
|
{
|
|
load_shared_unit(su, file_name);
|
|
if(!su->so_handle)
|
|
compile_shared_unit(su, file_name);
|
|
}
|
|
|
|
context->server->units[file_name] = su;
|
|
}
|
|
return(su);
|
|
}
|
|
|
|
void compiler_invoke(string file_name)
|
|
{
|
|
printf("(i) invoke %s\n", file_name.c_str());
|
|
if(file_name[0] != '/')
|
|
{
|
|
file_name = expand_path(file_name);
|
|
}
|
|
//printf("(i) invoke(%s)\n", file_name.c_str());
|
|
auto su = get_shared_unit(file_name);
|
|
if(!su)
|
|
{
|
|
printf("Error loading unit %s\n", file_name.c_str());
|
|
context->print("Error loading unit: "+file_name);
|
|
}
|
|
else if(!su->on_render)
|
|
{
|
|
context->print("Compiler error: "+su->compiler_messages);
|
|
}
|
|
else
|
|
{
|
|
if(su->compiler_messages.length() > 0)
|
|
context->print(su->compiler_messages);
|
|
else
|
|
{
|
|
string prev_wd = get_cwd();
|
|
set_cwd(su->src_path);
|
|
su->on_setup(context);
|
|
su->on_render();
|
|
set_cwd(prev_wd);
|
|
}
|
|
}
|
|
}
|
|
|
|
invoke_handler invoke;
|