-- chktab: Check correct usage of spaces and tabs (in Eiffel)
-- Public Domain (may be copied, modified and sold freely)
--
-- Detected errors:
-- * Tab(s) not at the beginning of line: tabs in the middle of the text 
--   are dependent on user setup and not necessary in Eiffel.
-- * Double spaces are redundant too (spaces at the beginning of lines are 
--   tabs). Double spaces are ignored inside comments.
--
-- FA 1996-09-24

indexing
	description: "Simple program to check correct usage of tabs and spaces"
	licence: public_domain
	version: "1996-09"

class CHECK_TAB inherit ARGUMENTS end

creation make
	
feature { NONE }
	
	Usage : STRING is "usage: chktab <in"

feature
	
	make is
			-- Root procedure.
		do
			if argument_count > 0 then
				io.put_string(Usage)
				io.put_new_line
			else
				-- process stdin
				from
					line := 1
				until
					io.end_of_file -- portability issue
				loop
					io.read_line
					check_line(io.last_string)
					line := line + 1
				end
			end

		end
		
feature { NONE } -- Attribute(s)

	line,column : INTEGER

feature { NONE }
	
	check_line(str : STRING) is
			-- Check one line.
		require
			valid_str: str /= Void
		local
			in_comment : BOOLEAN
		do
			from
				column := 1
			variant
				str.count + 1 - column
			until
				column > str.count
			loop
				-- misplaced tabs
				if column > 1 then
					-- detect comment
					if str.item(column) = '-' and str.item(column-1) = '-' then
						in_comment := true
					end
					
					-- tabs
					if str.item(column) = '%T' and str.item(column-1) /= '%T' then
						error("tab(s) not at the beginning of line")
					end

					-- double spaces
					if not in_comment then
						if str.item(column) = ' ' and str.item(column-1) = ' ' then
							error("double spaces")
						end
					end
				end

				column := column + 1
			end
		end

	error(msg : STRING) is
			-- Print error message.
		require
			ok: msg /= Void
		do
			io.put_string("-:")
			io.put_integer(line)
			io.put_character(':')
			io.put_integer(column)
			io.put_character(':')
			io.put_string(msg)
			io.put_new_line
		end

end -- class CHECK_TAB