-- mark up comments and strings
STR1 = "\001"
STR2 = "\002"
STR3 = "\003"
STR4 = "\004"
REM = "\005"
ANY = "([\001-\005])"
ESC1 = "\006"
ESC2 = "\007"

MASK = {
	-- the substitution order is important
	{ESC1, "\\'"},
	{ESC2, '\\"'},
	{STR1, "'"},
	{STR2, '"'},
	{STR3, "%[%["},
	{STR4, "%]%]"},
	{REM, "%-%-"}
}

function mask(s)
	for i = 1, getn(MASK) do
		s = gsub(s, MASK[i][2], MASK[i][1])
	end
	return s
end

function unmask(s)
	for i = 1, getn(MASK) do
		s = gsub(s, MASK[i][1], MASK[i][2])
	end
	return s
end

function clean(s)
	-- check for compilation error
	local code = "return function ()\n" .. s .. "\n end"
	if not dostring(code) then
		return nil
	end

	if flags["C"] then
		return s
	end

	local S = "" -- saved string

	s = mask(s)

	-- remove blanks and comments
	while 1 do
		local b, e, d = strfind(s, ANY)
		if b then
			S = S .. strsub(s, 1, b - 1)
			s = strsub(s, b + 1)
			if d == STR1 or d == STR2 then
				e = strfind(s, d)
				S = S .. d .. strsub(s, 1, e)
				s = strsub(s, e + 1)
			elseif d == STR3 then
				e = strfind(s, STR4)
				S = S .. d .. strsub(s, 1, e)
				s = strsub(s, e + 1)
			elseif d == REM then
				s = gsub(s, "[^\n]*(\n?)", "%1", 1)
			end
		else
			S = S .. s
			break
		end
	end
	-- eliminate unecessary spaces
	S = gsub(S, "[ \t]+", " ")
	S = gsub(S, "[ \t]*\n[ \t]*", "\n")
	S = gsub(S, "\n+", "\n")
	S = unmask(S)
	return S
end

