diff --git a/Makefile b/Makefile index 90edc9d..192a83b 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,2 @@ -ph7: ph7.c - cc -o ph7 ph7.c examples/ph7_intro.c -W -Wunused -Wall -I. -Ofast \ No newline at end of file +ph7: api.c builtin.c compile.c constant.c hashmap.c lex.c lib.c memobj.c oo.c parse.c vfs.c vm.c interpreter.c + cc -o ph7 api.c builtin.c compile.c constant.c hashmap.c lex.c lib.c memobj.c oo.c parse.c vfs.c vm.c interpreter.c -W -Wunused -Wall -I. -Ofast diff --git a/interpreter.c b/interpreter.c new file mode 100644 index 0000000..f8ad8f1 --- /dev/null +++ b/interpreter.c @@ -0,0 +1,216 @@ +/* + * 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 $ */ +/* Make sure you have the latest release of the PH7 engine + * from: + * http://ph7.symisc.net/downloads.html + */ +#include +#include +/* 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 +#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: 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 */ + ); + /* 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"); + } + } + /* + * Now we have our script compiled,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"); + } + /* 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( err_report ){ + /* Report script run-time errors */ + ph7_vm_config(pVm,PH7_VM_CONFIG_ERR_REPORT); + } + 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; +} \ No newline at end of file