diff --git a/examples/ph7_const_intro.c b/examples/ph7_const_intro.c new file mode 100644 index 0000000..4b63d6e --- /dev/null +++ b/examples/ph7_const_intro.c @@ -0,0 +1,240 @@ +/* + * Compile this file together with the ph7 engine source code to generate + * the executable. For example: + * gcc -W -Wall -O6 -o ph7_test ph7_const_intro.c ph7.c + */ +/* + * For an introductory course to the constant expansion meachanism, you can refer + * to the following tutorial: + * http://ph7.symisc.net/const_intro.html + * This simple program is a quick introduction to the constant expansion + * mechanism introduced by the PH7 engine. + * The constant expansion mechanism under PH7 is extremely powerful yet + * simple and work as follows: + * Each registered constant have a C procedure associated with it. + * This procedure known as the constant expansion callback is responsible of expanding + * the invoked constant to the desired value, for example: + * The C procedure associated with the "__PI__" constant expands to 3.14 (the value of PI). + * the "__OS__" constant procedure expands to the name of the host Operating + * Systems (Windows, Linux, ...), the "__TIME__" constants expands to the current system time + * and so on. + */ +/* $SymiscID: ph7_const_intro.c v1.9 FreeBSD 2012-08-24 14:34 stable $ */ +/* + * Make sure you have the latest release of the PH7 engine + * from: + * http://ph7.symisc.net/downloads.html + * Make sure this header file is available. + */ +#include "ph7.h" +/* + * __PI__: expand the value of PI (3.14...) + * Our first constant is the __PI__ constant.The following procedure + * is the callback associated with the __PI__ identifier. That is, when + * the __PI__ identifier is seen in the running script, this procedure + * gets called by the underlying PH7 virtual machine. + * This procedure is responsible of expanding the constant identifier to + * the desired value (3.14 in our case). + */ +static void PI_Constant( + ph7_value *pValue, /* Store expanded value here */ + void *pUserData /* User private data (unused in our case) */ + ){ + /* Expand the value of PI */ + ph7_value_double(pValue, 3.1415926535898); +} +/* + * __TIME__: expand the current local time. + * Our second constant is the __TIME__ constant. + * When the __TIME__ identifier is seen in the running script, this procedure + * gets called by the underlying PH7 virtual machine. + * This procedure is responsible of expanding the constant identifier to + * the desired value (local time in our case). + */ +#include +static void TIME_Constant(ph7_value *pValue, void *pUserData) +{ + struct tm *pLocal; + time_t tt; + /* Get the current local time */ + time(&tt); + pLocal = localtime(&tt); + /* Expand the current time now */ + ph7_value_string_format(pValue, "%02d:%02d:%02d", + pLocal->tm_hour, + pLocal->tm_min, + pLocal->tm_sec + ); +} +/* + * __OS__: expand the name of the Host Operating System. + * Our last constant is the __OS__ constant. + * When the __OS__ identifier is seen in the running script, this procedure + * gets called by the underlying PH7 virtual machine. + * This procedure is responsible of expanding the constant identifier to + * the desired value (OS name in our case). + */ +static void OS_Constant(ph7_value *pValue, void *pUserData) +{ +#ifdef __WINNT__ + ph7_value_string(pValue, "Windows", -1 /*Compute input length automatically */); +#else + /* Assume UNIX */ + ph7_value_string(pValue, "UNIX", -1 /*Compute input length automatically */); +#endif /* __WINNT__ */ +} +/* + * Test now the constant expansion mechanism: + * The following is the PHP program to execute. + * + * When running, you should see something like that: + * __PI__ value: 3.1415926535898 + * __TIME__ value: 15:02:27 + * __OS__ value: UNIX + */ +#define PHP_PROG "" +#include +#include +/* + * Display an error message and exit. + */ +static void Fatal(const char *zMsg) +{ + puts(zMsg); + /* Shutdown the library */ + ph7_lib_shutdown(); + /* Exit immediately */ + exit(0); +} +#ifdef __WINNT__ +#include +#else +/* Assume UNIX */ +#include +#endif +/* + * The following define is used by the UNIX built and have + * no particular meaning on windows. + */ +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +/* + * VM output consumer callback. + * Each time the virtual machine generates some outputs, the following + * function gets called by the underlying virtual machine to consume + * the generated output. + * All this function does is redirecting the VM output to STDOUT. + * This function is registered later via a call to ph7_vm_config() + * with a configuration verb set to: PH7_VM_CONFIG_OUTPUT. + */ +static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *pUserData/* Unused */) +{ +#ifdef __WINNT__ + BOOL rc; + rc = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pOutput, (DWORD)nOutputLen, 0, 0); + if( !rc ){ + /* Abort processing */ + return PH7_ABORT; + } +#else + ssize_t nWr; + nWr = write(STDOUT_FILENO, pOutput, nOutputLen); + if( nWr < 0 ){ + /* Abort processing */ + return PH7_ABORT; + } +#endif /* __WINT__ */ + /* All done, VM output was redirected to STDOUT */ + return PH7_OK; +} +/* + * Main program: Register the constants defined above, compile and execute + * our PHP test program. + */ +int main(void) +{ + ph7 *pEngine; /* PH7 engine */ + ph7_vm *pVm; /* Compiled PHP program */ + int rc; + /* Allocate a new PH7 engine instance */ + rc = ph7_init(&pEngine); + if( rc != PH7_OK ){ + /* + * If the supplied memory subsystem is so sick that we are unable + * to allocate a tiny chunk of memory, there is no much we can do here. + */ + Fatal("Error while allocating a new PH7 engine instance"); + } + /* Compile the PHP test program defined above */ + rc = ph7_compile_v2( + pEngine, /* PH7 engine */ + PHP_PROG, /* PHP test program */ + -1 /* Compute input length automatically*/, + &pVm, /* OUT: Compiled PHP program */ + 0 /* IN: Compile flags */ + ); + if( rc != PH7_OK ){ + if( rc == PH7_COMPILE_ERR ){ + const char *zErrLog; + int nLen; + /* Extract error log */ + ph7_config(pEngine, + PH7_CONFIG_ERR_LOG, + &zErrLog, + &nLen + ); + if( nLen > 0 ){ + /* zErrLog is null terminated */ + puts(zErrLog); + } + } + /* Exit */ + Fatal("Compile error"); + } + /* Now we have our program compiled, it's time to register our constants + * and their associated C procedure. + */ + rc = ph7_create_constant(pVm, "__PI__", PI_Constant, 0); + if( rc != PH7_OK ){ + Fatal("Error while installing the __PI__ constant"); + } + rc = ph7_create_constant(pVm, "__TIME__", TIME_Constant, 0); + if( rc != PH7_OK ){ + Fatal("Error while installing the __TIME__ constant"); + } + rc = ph7_create_constant(pVm, "__OS__", OS_Constant, 0); + if( rc != PH7_OK ){ + Fatal("Error while installing the __OS__ constant"); + } + /* + * Configure our VM: + * Install the VM output consumer callback defined above. + */ + rc = ph7_vm_config(pVm, + PH7_VM_CONFIG_OUTPUT, + Output_Consumer, /* Output Consumer callback */ + 0 /* Callback private data */ + ); + if( rc != PH7_OK ){ + Fatal("Error while installing the VM output consumer callback"); + } + /* + * And finally, execute our program. Note that your output (STDOUT in our case) + * should display the result. + */ + ph7_vm_exec(pVm, 0); + /* All done, cleanup the mess left behind. + */ + ph7_vm_release(pVm); + ph7_release(pEngine); + return 0; +}