|  | @@ -360,8 +360,8 @@ lsp_abort(lua_State *L)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  struct lsp_var_reader_data {
 | 
	
		
			
				|  |  |  	const char *begin;
 | 
	
		
			
				|  |  | -	unsigned len;
 | 
	
		
			
				|  |  | -	unsigned state;
 | 
	
		
			
				|  |  | +	int64_t len;
 | 
	
		
			
				|  |  | +	int64_t state;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -402,6 +402,86 @@ lsp_var_reader(lua_State *L, void *ud, size_t *sz)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static const char *
 | 
	
		
			
				|  |  | +lsp_kepler_reader_impl(lua_State *L, void *ud, size_t *sz)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	struct lsp_var_reader_data *reader = (struct lsp_var_reader_data *)ud;
 | 
	
		
			
				|  |  | +	const char *ret;
 | 
	
		
			
				|  |  | +	int64_t i;
 | 
	
		
			
				|  |  | +	int64_t left;
 | 
	
		
			
				|  |  | +	char end[4];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	(void)(L); /* unused */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* This reader is called multiple times, to fetch the full Lua script */
 | 
	
		
			
				|  |  | +	if (reader->state == -1) {
 | 
	
		
			
				|  |  | +		/* First call: what function to call */
 | 
	
		
			
				|  |  | +		ret = "mg.write([=======[";
 | 
	
		
			
				|  |  | +		*sz = strlen(ret);
 | 
	
		
			
				|  |  | +		reader->state = 0;
 | 
	
		
			
				|  |  | +		return ret;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if (reader->state == -2) {
 | 
	
		
			
				|  |  | +		*sz = 0;
 | 
	
		
			
				|  |  | +		return 0;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	left = reader->len - reader->state;
 | 
	
		
			
				|  |  | +	if (left == 0) {
 | 
	
		
			
				|  |  | +		ret = "]=======]);\n";
 | 
	
		
			
				|  |  | +		*sz = strlen(ret);
 | 
	
		
			
				|  |  | +		reader->state = -2;
 | 
	
		
			
				|  |  | +		return ret;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	if (left > MG_BUF_LEN / 100) {
 | 
	
		
			
				|  |  | +		left = MG_BUF_LEN / 100; /* TODO XXX */
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	i = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +forward:
 | 
	
		
			
				|  |  | +	while ((i < left) && (reader->begin[i + reader->state] != '<'))
 | 
	
		
			
				|  |  | +		i++;
 | 
	
		
			
				|  |  | +	if (i > 0) {
 | 
	
		
			
				|  |  | +		int64_t j = reader->state;
 | 
	
		
			
				|  |  | +		reader->state += i;
 | 
	
		
			
				|  |  | +		*sz = (size_t)i; /* cast is ok, i is limited to MG_BUF_LEN */
 | 
	
		
			
				|  |  | +		return reader->begin + j;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* assert (reader->begin[reader->state] == '<') */
 | 
	
		
			
				|  |  | +	/* assert (i == 0) */
 | 
	
		
			
				|  |  | +	if (0 == memcmp(reader->begin, "<?lua", 5)) {
 | 
	
		
			
				|  |  | +		i = 5;
 | 
	
		
			
				|  |  | +	} else if (0 == memcmp(reader->begin, "<%", 2)) {
 | 
	
		
			
				|  |  | +		i = 2;
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +		i = 1;
 | 
	
		
			
				|  |  | +		goto forward;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	end[0] = reader->begin[1];
 | 
	
		
			
				|  |  | +	end[1] = '>';
 | 
	
		
			
				|  |  | +	end[2] = 0;
 | 
	
		
			
				|  |  | +	/* here we have a <?lua or <% tag */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	ret = "]=======]);\n";
 | 
	
		
			
				|  |  | +	*sz = strlen(ret);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	printf("XXX end\n");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	reader->state = reader->len;
 | 
	
		
			
				|  |  | +	return ret;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static const char *
 | 
	
		
			
				|  |  | +lsp_kepler_reader(lua_State *L, void *ud, size_t *sz)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	/* debugging */
 | 
	
		
			
				|  |  | +	const char *ret = lsp_kepler_reader_impl(L, ud, sz);
 | 
	
		
			
				|  |  | +	printf("%.*s", *sz, ret);
 | 
	
		
			
				|  |  | +	return ret;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  |  run_lsp(struct mg_connection *conn,
 | 
	
		
			
				|  |  |          const char *path,
 | 
	
	
		
			
				|  | @@ -409,18 +489,58 @@ run_lsp(struct mg_connection *conn,
 | 
	
		
			
				|  |  |          int64_t len,
 | 
	
		
			
				|  |  |          lua_State *L)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	int lua_ok;
 | 
	
		
			
				|  |  | +	struct lsp_var_reader_data data;
 | 
	
		
			
				|  |  | +	char date[64];
 | 
	
		
			
				|  |  | +	time_t curtime = time(NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	gmt_time_string(date, sizeof(date), &curtime);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	conn->must_close = 1;
 | 
	
		
			
				|  |  | +	mg_printf(conn, "HTTP/1.1 200 OK\r\n");
 | 
	
		
			
				|  |  | +	send_no_cache_header(conn);
 | 
	
		
			
				|  |  | +	send_additional_header(conn);
 | 
	
		
			
				|  |  | +	mg_printf(conn,
 | 
	
		
			
				|  |  | +	          "Date: %s\r\n"
 | 
	
		
			
				|  |  | +	          "Connection: close\r\n"
 | 
	
		
			
				|  |  | +	          "Content-Type: text/html; charset=utf-8\r\n\r\n",
 | 
	
		
			
				|  |  | +	          date);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	data.begin = p;
 | 
	
		
			
				|  |  | +	data.len = len;
 | 
	
		
			
				|  |  | +	data.state = -1;
 | 
	
		
			
				|  |  | +	lua_ok = mg_lua_load(L, lsp_kepler_reader, &data, path, NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (lua_ok) {
 | 
	
		
			
				|  |  | +		/* Syntax error or OOM.
 | 
	
		
			
				|  |  | +		 * Error message is pushed on stack. */
 | 
	
		
			
				|  |  | +		lua_pcall(L, 1, 0, 0);
 | 
	
		
			
				|  |  | +		printf("XXX err\n");
 | 
	
		
			
				|  |  | +		lua_cry(conn, lua_ok, L, "LSP", "execute"); /* XXX TODO: everywhere ! */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +		/* Success loading chunk. Call it. */
 | 
	
		
			
				|  |  | +		lua_pcall(L, 0, 0, 1);
 | 
	
		
			
				|  |  | +		printf("XXX succ\n");
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int
 | 
	
		
			
				|  |  | +run_lsp_classic(struct mg_connection *conn,
 | 
	
		
			
				|  |  | +                const char *path,
 | 
	
		
			
				|  |  | +                const char *p,
 | 
	
		
			
				|  |  | +                int64_t len,
 | 
	
		
			
				|  |  | +                lua_State *L)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  |  	int i, j, s, pos = 0, lines = 1, lualines = 0, is_var, lua_ok;
 | 
	
		
			
				|  |  |  	char chunkname[MG_BUF_LEN];
 | 
	
		
			
				|  |  |  	struct lsp_var_reader_data data;
 | 
	
		
			
				|  |  |  	const char lsp_mark1 = '?'; /* Use <? code ?> */
 | 
	
		
			
				|  |  |  	const char lsp_mark2 = '%'; /* Use <% code %> */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	static void *sp = 0;
 | 
	
		
			
				|  |  | -	if (!sp)
 | 
	
		
			
				|  |  | -		sp = &i;
 | 
	
		
			
				|  |  | -	else
 | 
	
		
			
				|  |  | -		printf("stack: %lli", (int64_t)sp - (int64_t)&i);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	for (i = 0; i < len; i++) {
 | 
	
		
			
				|  |  |  		if (p[i] == '\n') {
 | 
	
		
			
				|  |  |  			lines++;
 |