perl.c
来自「Linux下的多协议即时通讯程序源代码」· C语言 代码 · 共 650 行 · 第 1/2 页
C
650 行
/* * purple * * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifdef HAVE_CONFIG_H#include <config.h># ifdef HAVE_LIMITS_H# include <limits.h># ifndef NAME_MAX# define NAME_MAX _POSIX_NAME_MAX# endif# endif#endif#ifdef DEBUG# undef DEBUG#endif#undef PACKAGE#define group perl_group#ifdef _WIN32/* This took me an age to figure out.. without this __declspec(dllimport) * will be ignored. */# define HASATTRIBUTE#endif#include <EXTERN.h>#ifndef _SEM_SEMUN_UNDEFINED# define HAS_UNION_SEMUN#endif#include <perl.h>#include <XSUB.h>#ifndef _WIN32# include <sys/mman.h>#endif#undef PACKAGE#ifndef _WIN32# include <dirent.h>#else /* We're using perl's win32 port of this */# define dirent direct#endif#undef group/* perl module support */#ifdef OLD_PERLextern void boot_DynaLoader _((CV * cv));#elseextern void boot_DynaLoader _((pTHX_ CV * cv)); /* perl is so wacky */#endif#undef _#ifdef DEBUG# undef DEBUG#endif#ifdef _WIN32# undef pipe#endif#ifdef _WIN32#define _WIN32DEP_H_#endif#include "internal.h"#include "debug.h"#include "plugin.h"#include "signals.h"#include "version.h"#include "perl-common.h"#include "perl-handlers.h"#include <gmodule.h>#define PERL_PLUGIN_ID "core-perl"PerlInterpreter *my_perl = NULL;static PurplePluginUiInfo ui_info ={ purple_perl_get_plugin_frame, 0, /* page_num (Reserved) */ NULL, /* frame (Reserved) */ /* Padding */ NULL, NULL, NULL, NULL};#ifdef PURPLE_GTKPERLstatic PurpleGtkPluginUiInfo gtk_ui_info ={ purple_perl_gtk_get_plugin_frame, 0 /* page_num (Reserved) */};#endifstatic void#ifdef OLD_PERLxs_init()#elsexs_init(pTHX)#endif{ char *file = __FILE__; /* This one allows dynamic loading of perl modules in perl scripts by * the 'use perlmod;' construction */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);}static voidperl_init(void){ /* changed the name of the variable from load_file to perl_definitions * since now it does much more than defining the load_file sub. * Moreover, deplaced the initialisation to the xs_init function. * (TheHobbit) */ char *perl_args[] = { "", "-e", "0", "-w" }; char perl_definitions[] = { /* We use to function one to load a file the other to execute * the string obtained from the first and holding the file * contents. This allows to have a really local $/ without * introducing temp variables to hold the old value. Just a * question of style:) */ "package Purple::PerlLoader;" "use Symbol;" "sub load_file {" "my $f_name=shift;" "local $/=undef;" "open FH,$f_name or return \"__FAILED__\";" "$_=<FH>;" "close FH;" "return $_;" "}" "sub destroy_package {" "eval { $_[0]->UNLOAD() if $_[0]->can('UNLOAD'); };" "Symbol::delete_package($_[0]);" "}" "sub load_n_eval {" "my ($f_name, $package) = @_;" "destroy_package($package);" "my $strin=load_file($f_name);" "return 2 if($strin eq \"__FAILED__\");" "my $eval = qq{package $package; $strin;};" "{" " eval $eval;" "}" "if($@) {" /*" #something went wrong\n"*/ "die(\"Errors loading file $f_name: $@\");" "}" "return 0;" "}" }; my_perl = perl_alloc(); PERL_SET_CONTEXT(my_perl); PL_perl_destruct_level = 1; perl_construct(my_perl);#ifdef DEBUG perl_parse(my_perl, xs_init, 4, perl_args, NULL);#else perl_parse(my_perl, xs_init, 3, perl_args, NULL);#endif#ifdef HAVE_PERL_EVAL_PV eval_pv(perl_definitions, TRUE);#else perl_eval_pv(perl_definitions, TRUE); /* deprecated */#endif perl_run(my_perl);}static voidperl_end(void){ if (my_perl == NULL) return; PL_perl_destruct_level = 1; PERL_SET_CONTEXT(my_perl); perl_eval_pv( "foreach my $lib (@DynaLoader::dl_modules) {" "if ($lib =~ /^Purple\\b/) {" "$lib .= '::deinit();';" "eval $lib;" "}" "}", TRUE); PL_perl_destruct_level = 1; PERL_SET_CONTEXT(my_perl); perl_destruct(my_perl); perl_free(my_perl); my_perl = NULL;}voidpurple_perl_callXS(void (*subaddr)(pTHX_ CV *cv), CV *cv, SV **mark){ dSP; PUSHMARK(mark); (*subaddr)(aTHX_ cv); PUTBACK;}static gbooleanprobe_perl_plugin(PurplePlugin *plugin){ /* XXX This would be much faster if I didn't create a new * PerlInterpreter every time I probed a plugin */ PerlInterpreter *prober = perl_alloc(); char *argv[] = {"", plugin->path }; gboolean status = TRUE; HV *plugin_info; PERL_SET_CONTEXT(prober); PL_perl_destruct_level = 1; perl_construct(prober); perl_parse(prober, xs_init, 2, argv, NULL); perl_run(prober); plugin_info = perl_get_hv("PLUGIN_INFO", FALSE); if (plugin_info == NULL) status = FALSE; else if (!hv_exists(plugin_info, "perl_api_version", strlen("perl_api_version")) || !hv_exists(plugin_info, "name", strlen("name")) || !hv_exists(plugin_info, "load", strlen("load"))) { /* Not a valid plugin. */ status = FALSE; } else { SV **key; int perl_api_ver; key = hv_fetch(plugin_info, "perl_api_version", strlen("perl_api_version"), 0); perl_api_ver = SvIV(*key); if (perl_api_ver != 2) status = FALSE; else { PurplePluginInfo *info; PurplePerlScript *gps; char *basename; STRLEN len; info = g_new0(PurplePluginInfo, 1); gps = g_new0(PurplePerlScript, 1); info->magic = PURPLE_PLUGIN_MAGIC; info->major_version = PURPLE_MAJOR_VERSION; info->minor_version = PURPLE_MINOR_VERSION; info->type = PURPLE_PLUGIN_STANDARD; info->dependencies = g_list_append(info->dependencies, PERL_PLUGIN_ID); gps->plugin = plugin; basename = g_path_get_basename(plugin->path); purple_perl_normalize_script_name(basename); gps->package = g_strdup_printf("Purple::Script::%s", basename); g_free(basename); /* We know this one exists. */ key = hv_fetch(plugin_info, "name", strlen("name"), 0); info->name = g_strdup(SvPV(*key, len)); /* Set id here in case we don't find one later. */ info->id = g_strdup(SvPV(*key, len));#ifdef PURPLE_GTKPERL if ((key = hv_fetch(plugin_info, "GTK_UI", strlen("GTK_UI"), 0))) info->ui_requirement = PURPLE_GTK_PLUGIN_TYPE;#endif if ((key = hv_fetch(plugin_info, "url", strlen("url"), 0))) info->homepage = g_strdup(SvPV(*key, len)); if ((key = hv_fetch(plugin_info, "author", strlen("author"), 0))) info->author = g_strdup(SvPV(*key, len)); if ((key = hv_fetch(plugin_info, "summary",
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?