//
// Class: CPerl
// Desc.: A class to embed a persistent Perl interpreter in your MFC app
//
// Compiler: Visual C++
// Tested on: Visual C++ 6.0, Visual C++ .NET
//
// Version: 1.1
//
// Created: 13/July/2003
// Updated: 13/July/2003
//
// Author: PixiGreg mailto:pixigreg@ifrance.com
//
// Disclaimer
// ----------
// THIS SOFTWARE AND THE ACCOMPANYING FILES ARE DISTRIBUTED "AS IS" AND WITHOUT
// ANY WARRANTIES WHETHER EXPRESSED OR IMPLIED. NO REPONSIBILITIES FOR POSSIBLE
// DAMAGES OR EVEN FUNCTIONALITY CAN BE TAKEN. THE USER MUST ASSUME THE ENTIRE
// RISK OF USING THIS SOFTWARE.
//
// Terms of Use
// ------------
// THIS SOFTWARE IS FREE FOR PERSONAL USE OR FREEWARE APPLICATIONS.
// IF YOU USE THIS SOFTWARE IN COMMERCIAL OR SHAREWARE APPLICATIONS YOU
// ARE GENTLY ASKED TO DONATE 5$ (FIVE U.S. DOLLARS) OR 5 EUROS TO THE AUTHOR,
// USING PAYPAL (CONTACT THE AUTHOR FOR DETAILS).
//
////////////////////////////////////////////////////////////////////////////////
//
// Important Notes
// ---------------
//
// Perl : Copyright 1987-2002, Larry Wall.
//
// To write this class, I inspired from the existing class CPerlWrap
// (http://www.codeproject.com/useritems/CPerlWrap.asp) by Harold Bamford.
// Copied section from this class have been marked as such
// (using <CPerlWrap>...</CPerlWrap>).
//
// The idea of persistent interpreter has been found in the Perl doc `perlembed' ;
// perlembed : copyright (C) 1995, 1996, 1997, 1998 Doug MacEachern and Jon Orwant.
//
// If you're looking for a good Perl distribution that includes Perl docs, I sug-
// gest you ActivePerl (http://www.activestate.com) from ActiveState Corp.
//
// Credits for the `Disclaimer' and `Terms of use' goes directly to Davide' Calabro.
//
//
#pragma once
#include <afxtempl.h>
#include <shlwapi.h>
#ifndef CStringA // seemingly compiling with MS VC++ 6
#ifdef _UNICODE
#error Unicode not supported with MS Visual C++ 6
#else
typedef CString CStringA;
#endif
#endif
typedef CArray<CStringA, const CStringA&> CStringArrayA;
namespace PXPerl
{
class CPerl;
class CPerlConfigFile
{
friend class CPerl;
public:
// Configurarion File Creation Helpers
// -----------------------------------
// Gets current output (configuration file contents).
// [returns] const string with configuration file contents.
LPCSTR GetOutput(void)
{
return LPCSTR(m_strOutput);
};
// Appends your own stuff to current configuration file contents.
// szText : [in] text to be appended.
void Write(LPCSTR szText)
{
m_strOutput += szText;
};
// Empty the current configuration file contents.
void Empty(void)
{
m_strOutput.Empty();
};
// Appends an integer type variable to current configuration file contents.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] value of variable.
// szComment(optional) : [in] comment about variable.
// pnDefault(optional) : [in] default value.
void WriteInt(LPCSTR szVariable, int value, LPCSTR szComment=NULL,
int *pnDefault=NULL);
// Appends a boolean type variable to current configuration file contents.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] value of variable (true or false).
// szComment(optional) : [in] comment about variable.
// pbDefault(optional) : [in] default value.
void WriteBool(LPCSTR szVariable, bool value, LPCSTR szComment=NULL,
bool *pbDefault=NULL);
// Appends a floating point type variable to current configuration file contents.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] value of variable.
// szComment(optional) : [in] comment about variable.
// pdDefault(optional) : [in] default value.
void WriteFloat(LPCSTR szVariable, double value, LPCSTR szComment=NULL,
double *pdDefault=NULL);
// Appends a string type variable to current configuration file contents.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] value of variable.
// szComment(optional) : [in] comment about variable.
// cDelim(optional) : [in] string delimiter. MUST NOT BE A CHARACTER OF YOUR STRING.
void WriteString(LPCSTR szVariable, LPCSTR value, LPCSTR szComment=NULL,
char cDelim='~', CStringA *pstrDefault=NULL);
// Appends a string array type variable to current configuration file contents.
// szVariable : [in] variable name (sample: abc for array @abc).
// array : [in] array.
// szComment(optional) : [in] comment about variable.
// cDelim(optional) : [in] strings delimiter. MUST NOT BE A CHARACTER OF YOUR STRINGS.
void WriteStringArray(LPCSTR szVariable, CStringArray &array, LPCSTR szComment=NULL,
char cDelim='~');
// Flushes the current configuration file contents to the disk
// (write the contents to a file).
// Reset the current configuration file contents.
// szFile : [in] path to a file.
// bReset(optional) : [in] reset the configuration file contents (m_strOutput) ?
bool Flush(LPCSTR szFile, bool bReset=true);
protected:
CStringA m_strOutput;
public:
static LPCSTR g_szOutputFormat;
static LPCSTR g_szOutputFormatWithDefault;
};
class CScript
{
friend class CPerl;
public:
CScript(int nIndex=-1)
{
m_nIndex = nIndex;
};
// Tells if the script object is valid.
bool IsValid(void)
{
return m_nIndex >= 0;
};
// Tells if the script object is invalid.
bool IsInvalid(void)
{
return m_nIndex < 0;
};
protected:
int m_nIndex;
};
class CPerl
{
public:
////
// Constructor.
CPerl();
// Destructor calls Unload() if you forget it.
virtual ~CPerl();
////
// Loads the persistent interpreter.
// [returns] true if successfuly loaded, false otherwise.
bool Load(void);
// Unloads the persistent interpreter and frees all memory.
void Unload(void);
////
// Compiles a script.
// szName : [in] an unique name to identify the script,
// must contain only letters and digits, mustn't start with a digit.
// szScript : [in] the script itself.
// [returns] a CScript object. Can be invalid in case of error.
CScript Compile(LPCSTR szName, LPCSTR szScript);
// Compiles a script produced by CPerlConfigFile.
// szName : [in] an unique name to identify the script,
// must contain only letters and digits, mustn't start with a digit.
// perlConfig : [in] a CPerlConfigFile object.
// [returns] a CScript object. Can be invalid in case of error.
CScript Compile(LPCSTR szName, const CPerlConfigFile& perlConfig);
// Compiles a script loaded from a resource of type RT_PERL.
// szName : [in] an unique name to identify the script,
// must contain only letters and digits, mustn't start with a digit.
// nID : [in] the RT_PERL resource ID.
// [returns] a CScript object. Can be invalid in case of error.
CScript Compile(LPCSTR szName, int nResID);
// Compiles a file.
// szName : [in] an unique name to identify the script,
// must contain only letters and digits, mustn't start with a digit.
// szScript : [in] a file containing a script.
// [returns] a CScript object. Can be invalid in case of error.
CScript CompileFile(LPCSTR szName, LPCSTR szFile);
// Executes a compiled script.
// script : [in] a valid CScript object.
// [returns] true is successful, false otherwise.
bool Exec(const CScript& script);
// Cleans the namespace (variables plus script itself)
// associated with a compiled script, freeing memory associated with it.
// Note that the script object passed is no longer valid after cleaning.
// script : [in] a valid CScript object.
void Clean(CScript & script);
// DoScript/DoFile are helpers to execute a single script a single time.
// Note that you can't access scripts variables with these methods.
// [returns] true if successfuly run, false otherwise.
bool DoScript(LPCSTR szScript);
bool DoScript(const CPerlConfigFile& perlConfig);
bool DoScript(int nResID);
bool DoFile(LPCSTR szFile);
////
// Checks the STDERR output of the interpreter.
// Useful to know if any error occured.
// [returns] true if strContents is not empty.
bool GetSTDERR(CStringA &strContents);
// Grabs the STDOUT output (the default output) of the interpreter.
// [returns] true if strContents is not empty.
bool GetSTDOUT(CStringA &strContents);
// Empties STDERR output.
void EmptySTDERR(void);
// Empties STDOUT output.
void EmptySTDOUT(void);
// Empties both STDERR and STDOUT outputs.
void EmptyOutputs(void);
// Empty outputs automatically at each Compile/Exec call ?
void SetAutoEmpty(bool bAuto=true)
{
m_bAutoEmpty = bAuto;
};
// Getting/Setting Variables Value
// -------------------------------
// Sets the integer value of a scalar variable.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] value to assign.
// [returns] true if successful, false otherwise.
bool SetInt(const CScript& script, LPCSTR szVariable, const int value);
// Gets the integer value of a scalar variable.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] default value,
// [out] fetched value if variable exists.
// [returns] true if successful, false otherwise.
bool GetInt(const CScript& script, LPCSTR szVariable, int &value);
// Sets the floating point value of a scalar variable.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] value to assign.
// [returns] true if successful, false otherwise.
bool SetFloat(const CScript& script, LPCSTR szVariable, const double value);
// Gets the floating point value of a scalar variable.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] default value,
// [out] fetched value if variable exists.
// [returns] true if successful, false otherwise.
bool GetFloat(const CScript& script, LPCSTR szVariable, double &value);
// Sets the string value of a scalar variable.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] value to assign.
// [returns] true if successful, false otherwise.
bool SetString(const CScript& script, LPCSTR szVariable, LPCSTR value);
// Gets the string value of a scalar variable.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for scalar $abc).
// value : [in] default value,
// [out] fetched value if variable exists.
// [returns] true if successful, false otherwise.
bool GetString(const CScript& script, LPCSTR szVariable, CStringA &value);
#ifndef _UNICODE
// Sets a string array.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for array @abc).
// array : [in] array to assign.
// bAppend : [in] empty Perl array before adding items to it ?
// [returns] true if successful, false otherwise.
bool SetArray(const CScript& script, LPCSTR szVariable, const CStringArray &array,
bool bAppend=false);
// Gets a string array.
// script : [in] a valid CScript object.
// szVariable : [in] variable name (sample: abc for array @abc).
// array : [in] existing array,
// [out] modified array with new items.
// bAppend : [in] empty CStringArray array before adding items to it ?
// [returns] true if successful, false otherwise.
bool GetArray(const CScript& script, LPCSTR szVariable, CStringArray &array,
bool bAppend=true);
#else
// Will someone use them ?
bool SetArray(const CScript& script, LPCSTR szVariable, const CStringArrayA &array,
bool bAppend=false);
bool GetArray(const CScript& script, LPCSTR szVariable, CStringArrayA &array,
bool bAppend=true);
#endif
protected:
CStringArrayA m_strAPackages; // Used to store package names
int m_nMaxPackageIndex; // Somewhat upper bound of array above
void *m_pMyPerl; // current instance of Perl (cast-ed as PerlInterpreter*)
bool m_bAutoEmpty;
public:
static CStringA g_strExeDir;
};
}