You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.9 KiB
225 lines
6.9 KiB
/* |
|
* Compile this file together with the ph7 engine source code to generate |
|
* the simple PH7 interpreter executable. For example: |
|
* gcc -W -Wall -O6 -D PH7_ENABLE_MATH_FUNC -o ph7 ph7_interp.c ph7.c |
|
*/ |
|
/* |
|
* The PH7 interpreter is a simple stand-alone PHP interpreter that allows |
|
* the user to enter and execute PHP files against a PH7 engine. |
|
* To start the ph7 program, just type "ph7" followed by the name of the PHP file |
|
* to compile and execute. That is, the first argument is to the interpreter, the rest |
|
* are scripts arguments, press "Enter" and the PHP code will be executed. |
|
* If something goes wrong while processing the PHP script due to a compile-time error |
|
* your error output (STDOUT) should display the compile-time error messages. |
|
* |
|
* Usage example of the ph7 interpreter: |
|
* ph7 scripts/hello_world.php |
|
* Running the interpreter with script arguments |
|
* ph7 scripts/mp3_tag.php /usr/local/path/to/my_mp3s |
|
* |
|
* The PH7 interpreter package includes more than 70 PHP scripts to test ranging from |
|
* simple hello world programs to XML processing, ZIP archive extracting, MP3 tag extracting, |
|
* UUID generation, JSON encoding/decoding, INI processing, Base32 encoding/decoding and many |
|
* more. These scripts are available in the scripts directory from the zip archive. |
|
*/ |
|
/* $SymiscID: ph7_interp.c v1.7.4 Win7 2012-10-06 03:22 stable <devel@symisc.net> $ */ |
|
/* Make sure you have the latest release of the PH7 engine |
|
* from: |
|
* http://ph7.symisc.net/downloads.html |
|
*/ |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
/* Make sure this header file is available.*/ |
|
#include "ph7.h" |
|
/* |
|
* Display an error message and exit. |
|
*/ |
|
static void Fatal(const char *zMsg) { |
|
puts(zMsg); |
|
/* Shutdown the library */ |
|
ph7_lib_shutdown(); |
|
/* Exit immediately */ |
|
exit(0); |
|
} |
|
/* |
|
* Banner. |
|
*/ |
|
static const char zBanner[] = { |
|
"============================================================\n" |
|
"Simple PH7 Interpreter \n" |
|
" http://ph7.symisc.net/\n" |
|
"============================================================\n" |
|
}; |
|
/* |
|
* Display the banner,a help message and exit. |
|
*/ |
|
static void Help(void) { |
|
puts(zBanner); |
|
puts("ph7 [-h|-r|-d] path/to/php_file [script args]"); |
|
puts("\t-d: Dump PH7 byte-code instructions"); |
|
puts("\t-r: Report run-time errors"); |
|
puts("\t-h: Display this message an exit"); |
|
/* Exit immediately */ |
|
exit(0); |
|
} |
|
#ifdef __WINNT__ |
|
#include <Windows.h> |
|
#else |
|
/* Assume UNIX */ |
|
#include <unistd.h> |
|
#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: Compile and execute the PHP file. |
|
*/ |
|
int main(int argc, char **argv) { |
|
ph7 *pEngine; /* PH7 engine */ |
|
ph7_vm *pVm; /* Compiled PHP program */ |
|
int dump_vm = 0; /* Dump VM instructions if TRUE */ |
|
int err_report = 0; /* Report run-time errors if TRUE */ |
|
int n; /* Script arguments */ |
|
int rc; |
|
/* Process interpreter arguments first*/ |
|
for(n = 1 ; n < argc ; ++n) { |
|
int c; |
|
if(argv[n][0] != '-') { |
|
/* No more interpreter arguments */ |
|
break; |
|
} |
|
c = argv[n][1]; |
|
if(c == 'd' || c == 'D') { |
|
/* Dump byte-code instructions */ |
|
dump_vm = 1; |
|
} else if(c == 'r' || c == 'R') { |
|
/* Report run-time errors */ |
|
err_report = 1; |
|
} else { |
|
/* Display a help message and exit */ |
|
Help(); |
|
} |
|
} |
|
if(n >= argc) { |
|
puts("Missing PHP file to compile"); |
|
Help(); |
|
} |
|
/* 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"); |
|
} |
|
/* Set an error log consumer callback. This callback [Output_Consumer()] will |
|
* redirect all compile-time error messages to STDOUT. |
|
*/ |
|
ph7_config(pEngine, PH7_CONFIG_ERR_OUTPUT, |
|
Output_Consumer, /* Error log consumer */ |
|
0 /* NULL: Callback Private data */ |
|
); |
|
/* Initialize the VM */ |
|
rc = ph7_vm_init(pEngine, &pVm); |
|
if(rc != PH7_OK) { |
|
if(rc == PH7_NOMEM) { |
|
Fatal("Out of memory"); |
|
} else if(rc == PH7_VM_ERR) { |
|
Fatal("VM initialization error"); |
|
} |
|
} |
|
/* |
|
* Now we have our VM initialized,it's time to configure our VM. |
|
* We will install the VM output consumer callback defined above |
|
* so that we can consume the VM output and redirect it to STDOUT. |
|
*/ |
|
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"); |
|
} |
|
rc = ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT, 1, 0); |
|
if(rc != PH7_OK) { |
|
Fatal("Error while configuring the VM error reporting"); |
|
} |
|
if(err_report) { |
|
/* Report script run-time errors */ |
|
ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT); |
|
} |
|
/* Now,it's time to compile our PHP file */ |
|
rc = ph7_compile_file( |
|
pEngine, /* PH7 Engine */ |
|
argv[n], /* Path to the PHP file to compile */ |
|
&pVm, /* OUT: Compiled PHP program */ |
|
0 /* IN: Compile flags */ |
|
); |
|
if(rc != PH7_OK) { /* Compile error */ |
|
if(rc == PH7_IO_ERR) { |
|
Fatal("IO error while opening the target file"); |
|
} else if(rc == PH7_VM_ERR) { |
|
Fatal("VM initialization error"); |
|
} else { |
|
/* Compile-time error, your output (STDOUT) should display the error messages */ |
|
Fatal("Compile error"); |
|
} |
|
} |
|
/* Register script agruments so we can access them later using the $argv[] |
|
* array from the compiled PHP program. |
|
*/ |
|
for(n = n + 1; n < argc ; ++n) { |
|
ph7_vm_config(pVm, PH7_VM_CONFIG_ARGV_ENTRY, argv[n]/* Argument value */); |
|
} |
|
if(dump_vm) { |
|
/* Dump PH7 byte-code instructions */ |
|
ph7_vm_dump_v2(pVm, |
|
Output_Consumer, /* Dump consumer callback */ |
|
0 |
|
); |
|
} |
|
/* |
|
* 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; |
|
} |