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 + -
显示快捷键?