mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-11 03:31:08 +00:00
[Quests] Cleanup Quest Parser Logic (#4025)
* [Quests] Cleanup Quest Parser Logic # Notes - Consolidate duplicated code into loops to make it easier to read and easier to add on to. # Images * Update quest_parser_collection.cpp * Push * Push * Update embperl.cpp * Push * Additional cleanup, use File::Exists utility * Range based loops * Update embparser.cpp * Cleanup * Update embparser.cpp --------- Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
+88
-97
@@ -27,16 +27,18 @@ Eglin
|
||||
XS(XS_EQEmuIO_PRINT);
|
||||
#endif //EMBPERL_IO_CAPTURE
|
||||
|
||||
const char *argv_eqemu[] = { "",
|
||||
const char* argv_eqemu[] = {
|
||||
"",
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
"-w", "-W",
|
||||
"-w", "-W",
|
||||
#endif
|
||||
"-e", "0;", nullptr };
|
||||
"-e", "0;", nullptr
|
||||
};
|
||||
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
int argc = 5;
|
||||
int argc = 5;
|
||||
#else
|
||||
int argc = 3;
|
||||
int argc = 3;
|
||||
#endif
|
||||
//so embedded scripts can use xs extensions (ala 'use socket;')
|
||||
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
|
||||
@@ -46,7 +48,7 @@ EXTERN_C void xs_init(pTHX)
|
||||
strncpy(file, __FILE__, 256);
|
||||
file[255] = '\0';
|
||||
|
||||
char buf[128]; //shouldent have any function names longer than this.
|
||||
char buf[128]; //shouldent have any function names longer than this.
|
||||
|
||||
//add the strcpy stuff to get rid of const warnings....
|
||||
|
||||
@@ -58,20 +60,20 @@ EXTERN_C void xs_init(pTHX)
|
||||
|
||||
Embperl::Embperl()
|
||||
{
|
||||
char **argv = (char **)argv_eqemu;
|
||||
char **env = { nullptr };
|
||||
in_use = true; //in case one of these files generates an event
|
||||
char** argv = (char**) argv_eqemu;
|
||||
char** env = { nullptr };
|
||||
PERL_SYS_INIT3(&argc, &argv, &env);
|
||||
DoInit();
|
||||
}
|
||||
|
||||
void Embperl::DoInit() {
|
||||
char **argv = (char **)argv_eqemu;
|
||||
char **env = { nullptr };
|
||||
void Embperl::DoInit()
|
||||
{
|
||||
char** argv = (char**) argv_eqemu;
|
||||
my_perl = perl_alloc();
|
||||
//setup perl...
|
||||
if(!my_perl)
|
||||
if (!my_perl) {
|
||||
throw "Failed to init Perl (perl_alloc)";
|
||||
}
|
||||
PERL_SET_CONTEXT(my_perl);
|
||||
PERL_SET_INTERP(my_perl);
|
||||
PL_perl_destruct_level = 1;
|
||||
@@ -80,17 +82,17 @@ void Embperl::DoInit() {
|
||||
perl_run(my_perl);
|
||||
|
||||
//a little routine we use a lot.
|
||||
eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error
|
||||
eval_pv("sub my_eval { eval $_[0];}", TRUE); //dies on error
|
||||
|
||||
//ruin the perl exit and command:
|
||||
eval_pv("sub my_exit {}",TRUE);
|
||||
eval_pv("sub my_sleep {}",TRUE);
|
||||
if(gv_stashpv("CORE::GLOBAL", FALSE)) {
|
||||
GV *exitgp = gv_fetchpv("CORE::GLOBAL::exit", TRUE, SVt_PVCV);
|
||||
GvCV_set(exitgp, perl_get_cv("my_exit", TRUE)); //dies on error
|
||||
eval_pv("sub my_exit {}", TRUE);
|
||||
eval_pv("sub my_sleep {}", TRUE);
|
||||
if (gv_stashpv("CORE::GLOBAL", FALSE)) {
|
||||
GV* exitgp = gv_fetchpv("CORE::GLOBAL::exit", TRUE, SVt_PVCV);
|
||||
GvCV_set(exitgp, perl_get_cv("my_exit", TRUE)); //dies on error
|
||||
GvIMPORTED_CV_on(exitgp);
|
||||
GV *sleepgp = gv_fetchpv("CORE::GLOBAL::sleep", TRUE, SVt_PVCV);
|
||||
GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error
|
||||
GV* sleepgp = gv_fetchpv("CORE::GLOBAL::sleep", TRUE, SVt_PVCV);
|
||||
GvCV_set(sleepgp, perl_get_cv("my_sleep", TRUE)); //dies on error
|
||||
GvIMPORTED_CV_on(sleepgp);
|
||||
}
|
||||
|
||||
@@ -98,8 +100,7 @@ void Embperl::DoInit() {
|
||||
try {
|
||||
init_eval_file();
|
||||
}
|
||||
catch(std::string& e)
|
||||
{
|
||||
catch (std::string& e) {
|
||||
//remember... lasterr() is no good if we crap out here, in construction
|
||||
LogQuests("Perl Error [{}]", e);
|
||||
throw "failed to install eval_file hook";
|
||||
@@ -110,69 +111,62 @@ void Embperl::DoInit() {
|
||||
//make a tieable class to capture IO and pass it into EQEMuLog
|
||||
eval_pv(
|
||||
"package EQEmuIO; "
|
||||
"sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '. $me); return($me); } "
|
||||
"sub WRITE { } "
|
||||
//dunno why I need to shift off fmt here, but it dosent like without it
|
||||
"sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } "
|
||||
"sub CLOSE { my $me = shift; $me->PRINT('Closing '.$me); } "
|
||||
"sub DESTROY { my $me = shift; $me->PRINT('Destroying '.$me); } "
|
||||
//this ties us for all packages, just do it in quest since thats kinda 'our' package
|
||||
"package quest;"
|
||||
" if(tied *STDOUT) { untie(*STDOUT); }"
|
||||
" if(tied *STDERR) { untie(*STDERR); }"
|
||||
" tie *STDOUT, 'EQEmuIO';"
|
||||
" tie *STDERR, 'EQEmuIO';"
|
||||
,FALSE);
|
||||
"sub TIEHANDLE { my $me = bless {}, $_[0]; $me->PRINT('Creating '. $me); return($me); } "
|
||||
"sub WRITE { } "
|
||||
"sub PRINTF { my $me = shift; my $fmt = shift; $me->PRINT(sprintf($fmt, @_)); } "
|
||||
"sub CLOSE { my $me = shift; $me->PRINT('Closing '.$me); } "
|
||||
"sub DESTROY { my $me = shift; $me->PRINT('Destroying '.$me); } "
|
||||
"package quest;"
|
||||
" if(tied *STDOUT) { untie(*STDOUT); }"
|
||||
" if(tied *STDERR) { untie(*STDERR); }"
|
||||
" tie *STDOUT, 'EQEmuIO';"
|
||||
" tie *STDERR, 'EQEmuIO';", FALSE);
|
||||
#endif //EMBPERL_IO_CAPTURE
|
||||
|
||||
#ifdef EMBPERL_PLUGIN
|
||||
eval_pv(
|
||||
"package plugin; "
|
||||
,FALSE
|
||||
"package plugin; ", FALSE
|
||||
);
|
||||
|
||||
LogQuests("Loading perlemb plugins");
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::string perl_command;
|
||||
perl_command = "main::eval_file('plugin', '" + Config->PluginPlFile + "');";
|
||||
eval_pv(perl_command.c_str(), FALSE);
|
||||
}
|
||||
catch(std::string& e)
|
||||
{
|
||||
catch (std::string& e) {
|
||||
LogQuests("Warning [{}]: [{}]", Config->PluginPlFile, e);
|
||||
}
|
||||
try
|
||||
{
|
||||
try {
|
||||
//should probably read the directory in c, instead, so that
|
||||
//I can echo filenames as I do it, but c'mon... I'm lazy and this 1 line reads in all the plugins
|
||||
std::string perl_command =
|
||||
"if(opendir(D,'" + path.GetPluginsPath() +"')) { "
|
||||
const std::string& perl_command = (
|
||||
"if(opendir(D,'" +
|
||||
path.GetPluginsPath() +
|
||||
"')) { "
|
||||
" my @d = readdir(D);"
|
||||
" closedir(D);"
|
||||
" foreach(@d){ "
|
||||
" main::eval_file('plugin','" + path.GetPluginsPath() + "/'.$_)if/\\.pl$/;"
|
||||
" main::eval_file('plugin','" +
|
||||
path.GetPluginsPath() +
|
||||
"/'.$_)if/\\.pl$/;"
|
||||
" }"
|
||||
"}";
|
||||
eval_pv(perl_command.c_str(),FALSE);
|
||||
"}");
|
||||
eval_pv(perl_command.c_str(), FALSE);
|
||||
}
|
||||
catch(std::string& e)
|
||||
{
|
||||
catch (std::string& e) {
|
||||
LogQuests("Warning [{}]", e);
|
||||
}
|
||||
#endif //EMBPERL_PLUGIN
|
||||
in_use = false;
|
||||
}
|
||||
|
||||
Embperl::~Embperl()
|
||||
{
|
||||
in_use = true;
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
eval_pv(
|
||||
"package quest;"
|
||||
" if(tied *STDOUT) { untie(*STDOUT); }"
|
||||
" if(tied *STDERR) { untie(*STDERR); }"
|
||||
,FALSE);
|
||||
" if(tied *STDERR) { untie(*STDERR); }", FALSE);
|
||||
#endif
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_destruct(my_perl);
|
||||
@@ -181,17 +175,15 @@ Embperl::~Embperl()
|
||||
my_perl = NULL;
|
||||
}
|
||||
|
||||
void Embperl::Reinit() {
|
||||
in_use = true;
|
||||
void Embperl::Reinit()
|
||||
{
|
||||
PERL_SET_CONTEXT(my_perl);
|
||||
PERL_SET_INTERP(my_perl);
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_destruct(my_perl);
|
||||
perl_free(my_perl);
|
||||
my_perl = NULL;
|
||||
//Now reinit...
|
||||
DoInit();
|
||||
in_use = false;
|
||||
}
|
||||
|
||||
void Embperl::init_eval_file(void)
|
||||
@@ -201,38 +193,30 @@ void Embperl::init_eval_file(void)
|
||||
"no warnings 'all';"
|
||||
"use Symbol qw(delete_package);"
|
||||
"sub eval_file {"
|
||||
"my($package, $filename) = @_;"
|
||||
"$filename=~s/\'//g;"
|
||||
"if(! -r $filename) { print \"Unable to read perl file '$filename'\\n\"; return; }"
|
||||
"my $mtime = -M $filename;"
|
||||
"if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){"
|
||||
" return;"
|
||||
"} else {"
|
||||
// we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here.
|
||||
" eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require './$filename'; \");"
|
||||
" print $@ if $@;"
|
||||
/* "local *FH;open FH, $filename or die \"open '$filename' $!\";"
|
||||
"local($/) = undef;my $sub = <FH>;close FH;"
|
||||
"my $eval = qq{package $package; sub handler { $sub; }};"
|
||||
"{ my($filename,$mtime,$package,$sub); eval $eval; }"
|
||||
"die $@ if $@;"
|
||||
"$Cache{$package}{mtime} = $mtime; ${$package.'::isloaded'} = 1;}"
|
||||
*/
|
||||
"}"
|
||||
"my($package, $filename) = @_;"
|
||||
"$filename=~s/\'//g;"
|
||||
"if(! -r $filename) { print \"Unable to read perl file '$filename'\\n\"; return; }"
|
||||
"my $mtime = -M $filename;"
|
||||
"if(defined $Cache{$package}{mtime}&&$Cache{$package}{mtime} <= $mtime && !($package eq 'plugin')){"
|
||||
" return;"
|
||||
"} else {"
|
||||
// we 'my' $filename,$mtime,$package,$sub to prevent them from changing our state up here.
|
||||
" eval(\"package $package; my(\\$filename,\\$mtime,\\$package,\\$sub); \\$isloaded = 1; require './$filename'; \");"
|
||||
" print $@ if $@;"
|
||||
"}"
|
||||
,FALSE);
|
||||
}
|
||||
"}", FALSE);
|
||||
}
|
||||
|
||||
int Embperl::eval_file(const char * packagename, const char * filename)
|
||||
int Embperl::eval_file(const char* package_name, const char* filename)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
args.push_back(packagename);
|
||||
args.push_back(package_name);
|
||||
args.push_back(filename);
|
||||
|
||||
return dosub("main::eval_file", &args);
|
||||
}
|
||||
|
||||
int Embperl::dosub(const char * subname, const std::vector<std::string> * args, int mode)
|
||||
int Embperl::dosub(const char* sub_name, const std::vector<std::string>* args, int mode)
|
||||
{
|
||||
dSP;
|
||||
int ret_value = 0;
|
||||
@@ -242,27 +226,29 @@ int Embperl::dosub(const char * subname, const std::vector<std::string> * args,
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
|
||||
if (args && !args->empty()) {
|
||||
for (auto i = args->begin(); i != args->end(); ++i) {
|
||||
XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length())));
|
||||
}
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
|
||||
count = call_pv(subname, mode);
|
||||
count = call_pv(sub_name, mode);
|
||||
SPAGAIN;
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
error = SvPV_nolen(ERRSV);
|
||||
POPs;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (count == 1) {
|
||||
SV *ret = POPs;
|
||||
SV* ret = POPs;
|
||||
if (SvTYPE(ret) == SVt_IV) {
|
||||
IV v = SvIV(ret);
|
||||
ret_value = v;
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
}
|
||||
}
|
||||
@@ -273,8 +259,8 @@ int Embperl::dosub(const char * subname, const std::vector<std::string> * args,
|
||||
// not sure why we pass this as blind args, strange
|
||||
// check for syntax errors
|
||||
if (args && !args->empty()) {
|
||||
const std::string &filename = args->back();
|
||||
std::string sub = subname;
|
||||
const std::string& filename = args->back();
|
||||
std::string sub = sub_name;
|
||||
if (sub == "main::eval_file" && !filename.empty() && File::Exists(filename)) {
|
||||
BenchTimer benchmark;
|
||||
|
||||
@@ -286,8 +272,10 @@ int Embperl::dosub(const char * subname, const std::vector<std::string> * args,
|
||||
std::string syntax_error = Process::execute(
|
||||
fmt::format("{} -c {} 2>&1", perl, filename)
|
||||
);
|
||||
|
||||
LogQuests("Perl eval [{}] took [{}]", filename, benchmark.elapsed());
|
||||
syntax_error = Strings::Trim(syntax_error);
|
||||
|
||||
if (!Strings::Contains(syntax_error, "syntax OK")) {
|
||||
syntax_error += SvPVX(ERRSV);
|
||||
throw syntax_error;
|
||||
@@ -305,19 +293,22 @@ int Embperl::dosub(const char * subname, const std::vector<std::string> * args,
|
||||
}
|
||||
|
||||
//evaluate an expression. throw error on fail
|
||||
int Embperl::eval(const char * code)
|
||||
int Embperl::eval(const char* code)
|
||||
{
|
||||
std::vector<std::string> arg;
|
||||
arg.push_back(code);
|
||||
return dosub("main::my_eval", &arg, G_SCALAR|G_EVAL|G_KEEPERR);
|
||||
return dosub("main::my_eval", &arg, G_SCALAR | G_EVAL | G_KEEPERR);
|
||||
}
|
||||
|
||||
bool Embperl::SubExists(const char *package, const char *sub) {
|
||||
HV *stash = gv_stashpv(package, false);
|
||||
if(!stash)
|
||||
return(false);
|
||||
bool Embperl::SubExists(const char* package, const char* sub)
|
||||
{
|
||||
HV* stash = gv_stashpv(package, false);
|
||||
if (!stash) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
int len = strlen(sub);
|
||||
return(hv_exists(stash, sub, len));
|
||||
return (hv_exists(stash, sub, len));
|
||||
}
|
||||
|
||||
#ifdef EMBPERL_IO_CAPTURE
|
||||
@@ -331,8 +322,8 @@ XS(XS_EQEmuIO_PRINT)
|
||||
}
|
||||
|
||||
for (int r = 1; r < items; r++) {
|
||||
char *str = SvPV_nolen(ST(r));
|
||||
char *cur = str;
|
||||
char* str = SvPV_nolen(ST(r));
|
||||
char* cur = str;
|
||||
|
||||
/* Strip newlines from log message 'str' */
|
||||
*std::remove(str, str + strlen(str), '\n') = '\0';
|
||||
|
||||
Reference in New Issue
Block a user