ph7_interp.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Compile this file together with the ph7 engine source code to generate
  3. * the simple PH7 interpreter executable. For example:
  4. * gcc -W -Wall -O6 -D PH7_ENABLE_MATH_FUNC -o ph7 ph7_interp.c ph7.c
  5. */
  6. /*
  7. * The PH7 interpreter is a simple stand-alone PHP interpreter that allows
  8. * the user to enter and execute PHP files against a PH7 engine.
  9. * To start the ph7 program, just type "ph7" followed by the name of the PHP file
  10. * to compile and execute. That is, the first argument is to the interpreter, the rest
  11. * are scripts arguments, press "Enter" and the PHP code will be executed.
  12. * If something goes wrong while processing the PHP script due to a compile-time error
  13. * your error output (STDOUT) should display the compile-time error messages.
  14. *
  15. * Usage example of the ph7 interpreter:
  16. * ph7 scripts/hello_world.php
  17. * Running the interpreter with script arguments
  18. * ph7 scripts/mp3_tag.php /usr/local/path/to/my_mp3s
  19. *
  20. * The PH7 interpreter package includes more than 70 PHP scripts to test ranging from
  21. * simple hello world programs to XML processing, ZIP archive extracting, MP3 tag extracting,
  22. * UUID generation, JSON encoding/decoding, INI processing, Base32 encoding/decoding and many
  23. * more. These scripts are available in the scripts directory from the zip archive.
  24. */
  25. /* $SymiscID: ph7_interp.c v1.7.4 Win7 2012-10-06 03:22 stable <devel@symisc.net> $ */
  26. /* Make sure you have the latest release of the PH7 engine
  27. * from:
  28. * http://ph7.symisc.net/downloads.html
  29. */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. /* Make sure this header file is available.*/
  33. #include "ph7.h"
  34. /*
  35. * Display an error message and exit.
  36. */
  37. static void Fatal(const char *zMsg)
  38. {
  39. puts(zMsg);
  40. /* Shutdown the library */
  41. ph7_lib_shutdown();
  42. /* Exit immediately */
  43. exit(0);
  44. }
  45. /*
  46. * Banner.
  47. */
  48. static const char zBanner[] = {
  49. "============================================================\n"
  50. "Simple PH7 Interpreter \n"
  51. " http://ph7.symisc.net/\n"
  52. "============================================================\n"
  53. };
  54. /*
  55. * Display the banner,a help message and exit.
  56. */
  57. static void Help(void)
  58. {
  59. puts(zBanner);
  60. puts("ph7 [-h|-r|-d] path/to/php_file [script args]");
  61. puts("\t-d: Dump PH7 byte-code instructions");
  62. puts("\t-r: Report run-time errors");
  63. puts("\t-h: Display this message an exit");
  64. /* Exit immediately */
  65. exit(0);
  66. }
  67. #ifdef __WINNT__
  68. #include <Windows.h>
  69. #else
  70. /* Assume UNIX */
  71. #include <unistd.h>
  72. #endif
  73. /*
  74. * The following define is used by the UNIX built and have
  75. * no particular meaning on windows.
  76. */
  77. #ifndef STDOUT_FILENO
  78. #define STDOUT_FILENO 1
  79. #endif
  80. /*
  81. * VM output consumer callback.
  82. * Each time the virtual machine generates some outputs,the following
  83. * function gets called by the underlying virtual machine to consume
  84. * the generated output.
  85. * All this function does is redirecting the VM output to STDOUT.
  86. * This function is registered later via a call to ph7_vm_config()
  87. * with a configuration verb set to: PH7_VM_CONFIG_OUTPUT.
  88. */
  89. static int Output_Consumer(const void *pOutput,unsigned int nOutputLen,void *pUserData /* Unused */)
  90. {
  91. #ifdef __WINNT__
  92. BOOL rc;
  93. rc = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),pOutput,(DWORD)nOutputLen,0,0);
  94. if( !rc ){
  95. /* Abort processing */
  96. return PH7_ABORT;
  97. }
  98. #else
  99. ssize_t nWr;
  100. nWr = write(STDOUT_FILENO,pOutput,nOutputLen);
  101. if( nWr < 0 ){
  102. /* Abort processing */
  103. return PH7_ABORT;
  104. }
  105. #endif /* __WINT__ */
  106. /* All done,VM output was redirected to STDOUT */
  107. return PH7_OK;
  108. }
  109. /*
  110. * Main program: Compile and execute the PHP file.
  111. */
  112. int main(int argc,char **argv)
  113. {
  114. ph7 *pEngine; /* PH7 engine */
  115. ph7_vm *pVm; /* Compiled PHP program */
  116. int dump_vm = 0; /* Dump VM instructions if TRUE */
  117. int err_report = 0; /* Report run-time errors if TRUE */
  118. int n; /* Script arguments */
  119. int rc;
  120. /* Process interpreter arguments first*/
  121. for(n = 1 ; n < argc ; ++n ){
  122. int c;
  123. if( argv[n][0] != '-' ){
  124. /* No more interpreter arguments */
  125. break;
  126. }
  127. c = argv[n][1];
  128. if( c == 'd' || c == 'D' ){
  129. /* Dump byte-code instructions */
  130. dump_vm = 1;
  131. }else if( c == 'r' || c == 'R' ){
  132. /* Report run-time errors */
  133. err_report = 1;
  134. }else{
  135. /* Display a help message and exit */
  136. Help();
  137. }
  138. }
  139. if( n >= argc ){
  140. puts("Missing PHP file to compile");
  141. Help();
  142. }
  143. /* Allocate a new PH7 engine instance */
  144. rc = ph7_init(&pEngine);
  145. if( rc != PH7_OK ){
  146. /*
  147. * If the supplied memory subsystem is so sick that we are unable
  148. * to allocate a tiny chunk of memory,there is no much we can do here.
  149. */
  150. Fatal("Error while allocating a new PH7 engine instance");
  151. }
  152. /* Set an error log consumer callback. This callback [Output_Consumer()] will
  153. * redirect all compile-time error messages to STDOUT.
  154. */
  155. ph7_config(pEngine,PH7_CONFIG_ERR_OUTPUT,
  156. Output_Consumer, /* Error log consumer */
  157. 0 /* NULL: Callback Private data */
  158. );
  159. /* Now,it's time to compile our PHP file */
  160. rc = ph7_compile_file(
  161. pEngine, /* PH7 Engine */
  162. argv[n], /* Path to the PHP file to compile */
  163. &pVm, /* OUT: Compiled PHP program */
  164. 0 /* IN: Compile flags */
  165. );
  166. if( rc != PH7_OK ){ /* Compile error */
  167. if( rc == PH7_IO_ERR ){
  168. Fatal("IO error while opening the target file");
  169. }else if( rc == PH7_VM_ERR ){
  170. Fatal("VM initialization error");
  171. }else{
  172. /* Compile-time error, your output (STDOUT) should display the error messages */
  173. Fatal("Compile error");
  174. }
  175. }
  176. /*
  177. * Now we have our script compiled,it's time to configure our VM.
  178. * We will install the VM output consumer callback defined above
  179. * so that we can consume the VM output and redirect it to STDOUT.
  180. */
  181. rc = ph7_vm_config(pVm,
  182. PH7_VM_CONFIG_OUTPUT,
  183. Output_Consumer, /* Output Consumer callback */
  184. 0 /* Callback private data */
  185. );
  186. if( rc != PH7_OK ){
  187. Fatal("Error while installing the VM output consumer callback");
  188. }
  189. /* Register script agruments so we can access them later using the $argv[]
  190. * array from the compiled PHP program.
  191. */
  192. for( n = n + 1; n < argc ; ++n ){
  193. ph7_vm_config(pVm,PH7_VM_CONFIG_ARGV_ENTRY,argv[n]/* Argument value */);
  194. }
  195. if( err_report ){
  196. /* Report script run-time errors */
  197. ph7_vm_config(pVm,PH7_VM_CONFIG_ERR_REPORT);
  198. }
  199. if( dump_vm ){
  200. /* Dump PH7 byte-code instructions */
  201. ph7_vm_dump_v2(pVm,
  202. Output_Consumer, /* Dump consumer callback */
  203. 0
  204. );
  205. }
  206. /*
  207. * And finally, execute our program. Note that your output (STDOUT in our case)
  208. * should display the result.
  209. */
  210. ph7_vm_exec(pVm,0);
  211. /* All done, cleanup the mess left behind.
  212. */
  213. ph7_vm_release(pVm);
  214. ph7_release(pEngine);
  215. return 0;
  216. }