# Path: scanner.py
# class ScannerIterator(object):
# 	# string iterator that allows look ahead and push back
# 	# can also push/pop state (for deep lookaheads)
# 	def __init__(self, data):
# 		logger.debug("ScannerIterator datalen=%d", len(data))
# 		self.data = data
# 		self.idx = 0
# 		self.max_idx = len(self.data)
# 		self.state_stack = []
# 
# 	def __iter__(self):
# 		return self
# 
# 	def next(self):
# 		return self.__next__()
# 
# 	def __next__(self):
# 		if self.idx >= self.max_idx:
# 			raise StopIteration
# 		self.idx += 1
# 		return self.data[self.idx-1]
# 
# 	def lookahead(self):
# 		if self.idx >= self.max_idx:
# 			return None
# #		print("lookahead={0}".format(self.data[self.idx]))
# 		return self.data[self.idx]
# 
# 	def pushback(self):
# 		if self.idx <= 0 :
# 			raise StopIteration
# 		self.idx -= 1
# 
# 	def push_state(self):
# 		self.state_stack.append(self.idx)
# #		print( "push stack=", self.state_stack )
# 
# 	def pop_state(self):
# #		print( "pop stack=", self.state_stack )
# 		self.idx = self.state_stack.pop()
# 
# 	def remain(self):
# 		# Test/debug method. Return what remains of the data.
# 		return self.data[self.idx:]
# 
# #	def stop(self):
# #		# truncate the iterator at the current position
# #		assert self.idx < self.max_idx, self.idx
# #
# #		# kill anything after the current position
# #		self.data = self.data[:self.idx]
# #		self.max_idx = len(self.data)
# 
# 	def lstrip(self):
# 		# strip left leading whitespace (like "".strip)
# 		try : 
# 			while str(self.data[self.idx]) in string.whitespace :
# 				self.next()
# 		except IndexError:
# 			raise StopIteration
# 
# 		# allow chaining
# 		return self
# 
# 	def eat(self, s):
# 		# consume a string from the leading part of the data
# 		# for example:  eat("hello") from "hello, world" will result in 
# 		# ", world"
# 		#
# 		# Requires the string be found in the data, like string's index method.
# 		# Requires the string start exactly at the current position.
# 
# 		errmsg = "\"{0}\" not found in {1}".format(s, self)
# 		for c in s :
# 			if self.idx >= self.max_idx:
# 				# full substring not found so error!
# 				raise ValueError(errmsg)
# 
# 			if str(self.data[self.idx]) == c :
# 				self.next()
# 			else :
# 				# full substring not found so error!
# 				raise ValueError(errmsg)
# 
# 		# allow chaining
# 		return self
# 
# Path: printable.py
# def printable_char(c):
# 	if ord(c) < 32:
# 		if c == '\t':
# 			return "\\t"
# 		if c == '\n':
# 			return "\\n"
# 		return "\\x{0:02x}".format(ord(c))
# 	if c == '\\': 
# 		return '\\\\'
# 	if c == '"': 
# 		return '\\"'
# 	return c
# 
# def printable_string(s): 
# 	# Convert a string with unprintable chars and/or weird printing chars into
# 	# something that can be printed without side effects.
# 	# For example, 
# 	#   <tab> -> "\t"   
# 	#   <eol> -> "\n"
# 	#   "	 -> \"
# 	#
# 	# Want to be able to round trip the output of the Symbol hierarchy back
# 	# into valid Python code.
# 	return "".join([printable_char(vc.char) for vc in s if not vc.hide])


import sys
import itertools
import logging
import hexdump
from scanner import ScannerIterator
from printable import printable_char, printable_string
	# parse_recipes() and the idx can change with push_back
	for line in line_iter :
		# line_iter.idx is the *next* line number counting from zero 
		starting_line_number = line_iter.idx-1
		logger.debug("get_vline line_num=%d state=%d", starting_line_number, state)
#		print("{0}".format(hexdump.dump(line), end=""))

		if state==state_start : 
			start_line_stripped = line.strip()

			# ignore blank lines
			if len(start_line_stripped)==0:
				continue

			line_list = [ line ] 

			if is_line_continuation(line):
				# We found a line with trailing \+eol
				# We will start collecting the next lines until we see a line
				# that doesn't end with \+eol
				state = state_backslash
			else :
				# We found a single line of makefile. Tokenize!
				state = state_tokenize

		elif state==state_backslash : 
			line_list.append( line )
			if not is_line_continuation(line):
				# This is the last line of our continuation block. Create a
				# virtual block for this array of lines.

# Path: scanner.py
# class ScannerIterator(object):
# 	# string iterator that allows look ahead and push back
# 	# can also push/pop state (for deep lookaheads)
# 	def __init__(self, data):
# 		logger.debug("ScannerIterator datalen=%d", len(data))
# 		self.data = data
# 		self.idx = 0
# 		self.max_idx = len(self.data)
# 		self.state_stack = []
# 
# 	def __iter__(self):
# 		return self
# 
# 	def next(self):
# 		return self.__next__()
# 
# 	def __next__(self):
# 		if self.idx >= self.max_idx:
# 			raise StopIteration
# 		self.idx += 1
# 		return self.data[self.idx-1]
# 
# 	def lookahead(self):
# 		if self.idx >= self.max_idx:
# 			return None
# #		print("lookahead={0}".format(self.data[self.idx]))
# 		return self.data[self.idx]
# 
# 	def pushback(self):
# 		if self.idx <= 0 :
# 			raise StopIteration
# 		self.idx -= 1
# 
# 	def push_state(self):
# 		self.state_stack.append(self.idx)
# #		print( "push stack=", self.state_stack )
# 
# 	def pop_state(self):
# #		print( "pop stack=", self.state_stack )
# 		self.idx = self.state_stack.pop()
# 
# 	def remain(self):
# 		# Test/debug method. Return what remains of the data.
# 		return self.data[self.idx:]
# 
# #	def stop(self):
# #		# truncate the iterator at the current position
# #		assert self.idx < self.max_idx, self.idx
# #
# #		# kill anything after the current position
# #		self.data = self.data[:self.idx]
# #		self.max_idx = len(self.data)
# 
# 	def lstrip(self):
# 		# strip left leading whitespace (like "".strip)
# 		try : 
# 			while str(self.data[self.idx]) in string.whitespace :
# 				self.next()
# 		except IndexError:
# 			raise StopIteration
# 
# 		# allow chaining
# 		return self
# 
# 	def eat(self, s):
# 		# consume a string from the leading part of the data
# 		# for example:  eat("hello") from "hello, world" will result in 
# 		# ", world"
# 		#
# 		# Requires the string be found in the data, like string's index method.
# 		# Requires the string start exactly at the current position.
# 
# 		errmsg = "\"{0}\" not found in {1}".format(s, self)
# 		for c in s :
# 			if self.idx >= self.max_idx:
# 				# full substring not found so error!
# 				raise ValueError(errmsg)
# 
# 			if str(self.data[self.idx]) == c :
# 				self.next()
# 			else :
# 				# full substring not found so error!
# 				raise ValueError(errmsg)
# 
# 		# allow chaining
# 		return self
# 
# Path: printable.py
# def printable_char(c):
# 	if ord(c) < 32:
# 		if c == '\t':
# 			return "\\t"
# 		if c == '\n':
# 			return "\\n"
# 		return "\\x{0:02x}".format(ord(c))
# 	if c == '\\': 
# 		return '\\\\'
# 	if c == '"': 
# 		return '\\"'
# 	return c
# 
# def printable_string(s): 
# 	# Convert a string with unprintable chars and/or weird printing chars into
# 	# something that can be printed without side effects.
# 	# For example, 
# 	#   <tab> -> "\t"   
# 	#   <eol> -> "\n"
# 	#   "	 -> \"
# 	#
# 	# Want to be able to round trip the output of the Symbol hierarchy back
# 	# into valid Python code.
# 	return "".join([printable_char(vc.char) for vc in s if not vc.hide])


# Path: vline.py
import sys
import itertools
import logging
import hexdump
from scanner import ScannerIterator
from printable import printable_char, printable_string

	# parse_recipes() and the idx can change with push_back
	for line in line_iter :
		# line_iter.idx is the *next* line number counting from zero 
		starting_line_number = line_iter.idx-1
		logger.debug("get_vline line_num=%d state=%d", starting_line_number, state)
#		print("{0}".format(hexdump.dump(line), end=""))

		if state==state_start : 
			start_line_stripped = line.strip()

			# ignore blank lines
			if len(start_line_stripped)==0:
				continue

			line_list = [ line ] 

			if is_line_continuation(line):
				# We found a line with trailing \+eol
				# We will start collecting the next lines until we see a line
				# that doesn't end with \+eol
				state = state_backslash
			else :
				# We found a single line of makefile. Tokenize!
				state = state_tokenize

		elif state==state_backslash : 
			line_list.append( line )
			if not is_line_continuation(line):
				# This is the last line of our continuation block. Create a
				# virtual block for this array of lines.

				state = state_tokenize