#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <php_embed.h>

#define PHP_EMB_VERSION "0.1"

extern zend_module_entry php_emb_module_entry;

int main(int argc, char *argv[]) {
	FILE *fp;
	struct stat st;	
	char *compiled_string_description;
	char *source = NULL;
	zval *var;

	/* Grab the template and stick it in char *source */
	fp = fopen(argv[1],"r");
	if(!fp) exit(-1);
	fstat(fileno(fp), &st);
	source = (char *)malloc(st.st_size+3);
	strcpy(source,"?>");  /* Start in non-PHP mode */
	fread(source+2, sizeof(char), st.st_size, fp);	
	fclose(fp);

	/* Initialize the embedded php parser */
	if(php_embed_init(1, argv PTSRMLS_CC)==FAILURE) {
		fprintf(stderr,"PHP Embedding failed to initialize");
		exit(-1);
	}

	/* Load our module */
	zend_startup_module(&php_emb_module_entry);

	/* We can hardcode a few ini settings - might want to macro this uglyness */
	zend_alter_ini_entry("html_errors", strlen("html_errors")+1, "0", strlen("0")+1, PHP_INI_USER, PHP_INI_STAGE_ACTIVATE);
	zend_alter_ini_entry("display_errors", strlen("display_errors")+1, "1", strlen("1")+1, PHP_INI_USER, PHP_INI_STAGE_ACTIVATE);
	zend_alter_ini_entry("display_startup_errors", strlen("display_startup_errors")+1, "1", strlen("1")+1, PHP_INI_USER, PHP_INI_STAGE_ACTIVATE);

	/* We can also create some variables and preload them into the global symbol table */
	MAKE_STD_ZVAL(var);
	Z_LVAL_P(var) = 99;
	Z_TYPE_P(var) = IS_LONG;
	ZEND_SET_SYMBOL(EG(active_symbol_table), "emb_var", var);

	/* Build a description string that our compiled opcodes will be known as */
	compiled_string_description = zend_make_compiled_string_description("emb test" TSRMLS_CC);

	zend_first_try {
		/* Parse the template */
		if(zend_eval_string(source, NULL, compiled_string_description) != SUCCESS) {
			fprintf(stderr,"eval_string failed [%s]\n", source);
		}
	} zend_catch {
		fprintf(stderr,"It blew up in your face!");
	} zend_end_try();
	
	php_embed_shutdown(TSRMLS_C);
	return 0;
}

PHP_MINIT_FUNCTION(emb) {
	REGISTER_STRING_CONSTANT("VERSION", PHP_EMB_VERSION, CONST_CS|CONST_PERSISTENT);
	return SUCCESS;
}

/* 
 * Bogus example function which takes a string and returns an array with
 * the same string in index 0 and the length of the string in index 1
 */
PHP_FUNCTION(emb_example_function) {
	char *str;
	int str_len;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
		return;
	}
	array_init(return_value);
	add_index_stringl(return_value, 0, str, str_len, 1);
	add_index_long(return_value, 1, str_len);
}

function_entry php_emb_functions[] = {
	PHP_FE(emb_example_function, NULL)
	{NULL, NULL, NULL}	
};

zend_module_entry php_emb_module_entry = {
	STANDARD_MODULE_HEADER,
	"emb",
	php_emb_functions,
	PHP_MINIT(emb),
	NULL,
	NULL,
	NULL,
	NULL,
	PHP_EMB_VERSION,
	STANDARD_MODULE_PROPERTIES
};

