|  | @@ -361,7 +361,9 @@ lsp_abort(lua_State *L)
 | 
	
		
			
				|  |  |  struct lsp_var_reader_data {
 | 
	
		
			
				|  |  |  	const char *begin;
 | 
	
		
			
				|  |  |  	int64_t len;
 | 
	
		
			
				|  |  | -	int64_t state;
 | 
	
		
			
				|  |  | +	unsigned char state;
 | 
	
		
			
				|  |  | +	int64_t consumed;
 | 
	
		
			
				|  |  | +	char tag;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -377,6 +379,7 @@ lsp_var_reader(lua_State *L, void *ud, size_t *sz)
 | 
	
		
			
				|  |  |  	switch (reader->state) {
 | 
	
		
			
				|  |  |  	case 0:
 | 
	
		
			
				|  |  |  		/* First call: what function to call */
 | 
	
		
			
				|  |  | +		reader->consumed = 0;
 | 
	
		
			
				|  |  |  		ret = "mg.write(";
 | 
	
		
			
				|  |  |  		*sz = strlen(ret);
 | 
	
		
			
				|  |  |  		break;
 | 
	
	
		
			
				|  | @@ -384,6 +387,7 @@ lsp_var_reader(lua_State *L, void *ud, size_t *sz)
 | 
	
		
			
				|  |  |  		/* Second call: forward variable name */
 | 
	
		
			
				|  |  |  		ret = reader->begin;
 | 
	
		
			
				|  |  |  		*sz = reader->len;
 | 
	
		
			
				|  |  | +		reader->consumed += reader->len;
 | 
	
		
			
				|  |  |  		break;
 | 
	
		
			
				|  |  |  	case 2:
 | 
	
		
			
				|  |  |  		/* Third call: close function call */
 | 
	
	
		
			
				|  | @@ -414,23 +418,29 @@ lsp_kepler_reader_impl(lua_State *L, void *ud, size_t *sz)
 | 
	
		
			
				|  |  |  	(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 */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (reader->state == 0) {
 | 
	
		
			
				|  |  | +		/* First call: Send opening tag - what function to call */
 | 
	
		
			
				|  |  |  		ret = "mg.write([=======[";
 | 
	
		
			
				|  |  |  		*sz = strlen(ret);
 | 
	
		
			
				|  |  | -		reader->state = 0;
 | 
	
		
			
				|  |  | +		reader->state = 1;
 | 
	
		
			
				|  |  | +		reader->consumed = 0;
 | 
	
		
			
				|  |  |  		return ret;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	if (reader->state == -2) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (reader->state == 4) {
 | 
	
		
			
				|  |  | +		/* Final call: Tell Lua reader, we reached the end */
 | 
	
		
			
				|  |  |  		*sz = 0;
 | 
	
		
			
				|  |  |  		return 0;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	left = reader->len - reader->state;
 | 
	
		
			
				|  |  | +	left = reader->len - reader->consumed;
 | 
	
		
			
				|  |  |  	if (left == 0) {
 | 
	
		
			
				|  |  | +		/* We reached the end of the file/available data. */
 | 
	
		
			
				|  |  | +		/* Send closing tag. */
 | 
	
		
			
				|  |  |  		ret = "]=======]);\n";
 | 
	
		
			
				|  |  |  		*sz = strlen(ret);
 | 
	
		
			
				|  |  | -		reader->state = -2;
 | 
	
		
			
				|  |  | +		reader->state = 4; /* Next will be the final call */
 | 
	
		
			
				|  |  |  		return ret;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	if (left > MG_BUF_LEN / 100) {
 | 
	
	
		
			
				|  | @@ -438,39 +448,77 @@ lsp_kepler_reader_impl(lua_State *L, void *ud, size_t *sz)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	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;
 | 
	
		
			
				|  |  | +	if (reader->state == 1) {
 | 
	
		
			
				|  |  | +		/* State 1: plain text - put inside mg.write(...) */
 | 
	
		
			
				|  |  | +		for (;;) {
 | 
	
		
			
				|  |  | +			/* Find next tag */
 | 
	
		
			
				|  |  | +			while ((i < left) && (reader->begin[i + reader->state] != '<')) {
 | 
	
		
			
				|  |  | +				i++;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			if (i > 0) {
 | 
	
		
			
				|  |  | +				/* Forward all data until the next tag */
 | 
	
		
			
				|  |  | +				int64_t j = reader->consumed;
 | 
	
		
			
				|  |  | +				reader->consumed += 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 + reader->state, "<?lua", 5)) {
 | 
	
		
			
				|  |  | +				i = 5;
 | 
	
		
			
				|  |  | +				break;
 | 
	
		
			
				|  |  | +			} else if (0 == memcmp(reader->begin + reader->state, "<%", 2)) {
 | 
	
		
			
				|  |  | +				i = 2;
 | 
	
		
			
				|  |  | +				break;
 | 
	
		
			
				|  |  | +			} else {
 | 
	
		
			
				|  |  | +				i = 1;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		/* We found an opening or closing tag, or we reached the end of the
 | 
	
		
			
				|  |  | +		 * file/data block */
 | 
	
		
			
				|  |  | +		ret = "]=======]);\n";
 | 
	
		
			
				|  |  | +		*sz = strlen(ret);
 | 
	
		
			
				|  |  | +		reader->state == 2;
 | 
	
		
			
				|  |  | +		reader->tag = reader->begin[1];
 | 
	
		
			
				|  |  | +		reader->consumed += i; /* length of <?lua or <% tag */
 | 
	
		
			
				|  |  | +		return ret;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	end[0] = reader->begin[1];
 | 
	
		
			
				|  |  | -	end[1] = '>';
 | 
	
		
			
				|  |  | -	end[2] = 0;
 | 
	
		
			
				|  |  | -	/* here we have a <?lua or <% tag */
 | 
	
		
			
				|  |  | +	/* State 2: Lua code - keep outside mg.write(...) */
 | 
	
		
			
				|  |  | +	for (;;) {
 | 
	
		
			
				|  |  | +		/* Find end tag */
 | 
	
		
			
				|  |  | +		while ((i < left)
 | 
	
		
			
				|  |  | +		       && (reader->begin[i + reader->state] != reader->tag)) {
 | 
	
		
			
				|  |  | +			i++;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		if (i > 0) {
 | 
	
		
			
				|  |  | +			/* Check for closing tag */
 | 
	
		
			
				|  |  | +			if ((i + 1 < left) && (reader->begin[i + reader->state] == '>')) {
 | 
	
		
			
				|  |  | +				i--;                   /* don't send the tag */
 | 
	
		
			
				|  |  | +				reader->consumed += 2; /* but mark it as consumed */
 | 
	
		
			
				|  |  | +				reader->state = 3;
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	ret = "]=======]);\n";
 | 
	
		
			
				|  |  | -	*sz = strlen(ret);
 | 
	
		
			
				|  |  | +			/* Forward all data inside the Lua script tag */
 | 
	
		
			
				|  |  | +			int64_t j = reader->consumed;
 | 
	
		
			
				|  |  | +			reader->consumed += i;
 | 
	
		
			
				|  |  | +			*sz = (size_t)i; /* cast is ok, i is limited to MG_BUF_LEN */
 | 
	
		
			
				|  |  | +			return reader->begin + j;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	printf("XXX end\n");
 | 
	
		
			
				|  |  | +	if (reader->state == 3) {
 | 
	
		
			
				|  |  | +		/* State 3: Send a new opening tag */
 | 
	
		
			
				|  |  | +		ret = "\nmg.write([=======[";
 | 
	
		
			
				|  |  | +		*sz = strlen(ret);
 | 
	
		
			
				|  |  | +		reader->state = 1;
 | 
	
		
			
				|  |  | +		return ret;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	reader->state = reader->len;
 | 
	
		
			
				|  |  | -	return ret;
 | 
	
		
			
				|  |  | +	/* Must never be reached */
 | 
	
		
			
				|  |  | +	*sz = 0;
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static const char *
 | 
	
	
		
			
				|  | @@ -509,7 +557,9 @@ run_lsp(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	data.begin = p;
 | 
	
		
			
				|  |  |  	data.len = len;
 | 
	
		
			
				|  |  | -	data.state = -1;
 | 
	
		
			
				|  |  | +	data.state = 0;
 | 
	
		
			
				|  |  | +	data.consumed = 0;
 | 
	
		
			
				|  |  | +	data.tag = 0;
 | 
	
		
			
				|  |  |  	lua_ok = mg_lua_load(L, lsp_kepler_reader, &data, path, NULL);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (lua_ok) {
 | 
	
	
		
			
				|  | @@ -613,6 +663,8 @@ run_lsp_classic(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  						data.begin = p + (i + 3 + s);
 | 
	
		
			
				|  |  |  						data.len = j - (i + 3 + s);
 | 
	
		
			
				|  |  |  						data.state = 0;
 | 
	
		
			
				|  |  | +						data.consumed = 0;
 | 
	
		
			
				|  |  | +						data.tag = 0;
 | 
	
		
			
				|  |  |  						lua_ok = mg_lua_load(
 | 
	
		
			
				|  |  |  						    L, lsp_var_reader, &data, chunkname, NULL);
 | 
	
		
			
				|  |  |  					} else {
 |