Asm-Preproc

 view release on metacpan or  search on metacpan

lib/Asm/Preproc.pm  view on Meta::CPAN

					return $1;
				}
			}
			shift @input;							# end of input
		}
	};
	$self->_push_iter($iter, "-");
}

#------------------------------------------------------------------------------
# prepare the object to read the given iterator and file name
sub _push_iter {
	my($self, $iter, $file) = @_;
	
	# new file in the stack
	push @{$self->_stack}, Asm::Preproc::File->new($iter, $file);
}
#------------------------------------------------------------------------------

=head2 getline

Returns the next line from the input, after doing all the pre-processing.
The line is returned as a L<Asm::Preproc::Line|Asm::Preproc::Line> object
containing the actual text, and the file and line number where the text
was found.

Returns C<undef> at the end of the input.

=cut

#------------------------------------------------------------------------------
# return next line as a Asm::Preproc::Line object
sub getline {
	my($self) = @_;

	while (1) {
		return undef unless @{$self->_stack};	# no more files
		my $top = $self->_stack->[TOP];

		# read line
		my $text = $top->iter->();
		if (! defined $text) {					# file finished, read next
			pop @{$self->_stack};
			next;
		}

		# inc line number, save it to use as the line_nr of a multi-line
		# continuation
		my $line_nr = $top->line_nr( $top->line_nr + $top->line_inc );

			# while line ends in \\, remove all blanks before it and \r \n after
		# the line contains at most one \n, due to include_list() iterator
		while ($text =~ s/ \s* \\ [\r\n]* \z / /x) {
				my $next = $top->iter->();
				$top->line_nr( $top->line_nr + $top->line_inc );
				
				defined($next) or last;		# no more input, ignore last \\
				$text .= $next;
			}
		
		# normalize eol
		$text =~ s/ \s* \z /\n/x;		# any ending blanks replaced by \n

		# line to be returned, is used in %include below
		my $line = Asm::Preproc::Line->new($text, $top->file, $line_nr);
		
		# check for pre-processor directives
		if ($text =~ /^ \s* [\#\%] /gcix) {
			if ($text =~ / \G line /gcix) {
				# %line n+m file
				# #line n "file"
				if ($text =~ / \G \s+ (\d+) /gcix) {	# line_nr
					$top->line_nr( $1 );
		
					if ($text =~ / \G \+ (\d+) /gcix) {	# optional line_inc
						$top->line_inc( $1 );
					}
					else {
						$top->line_inc( 1 );
	}

					if ($text =~ / \G \s+ \"? ([^\"\s]+) \"? /gcix) {	# file
						$top->file( $1 );
					}

					# next line in nr+inc
					$top->line_nr( $top->line_nr - $top->line_inc );
					next;		# get next line
				}
	}
			elsif ($text =~ / \G include /gcix) {
				# %include <file>
				# #include 'file'
				# %include "file"
				# #include  file 
				if ($text =~ / \G \s+	(?: \< ([^\>]+) \>  | 
											\' ([^\']+) \'  | 
											\" ([^\"]+) \"  |
											   (\S+)
										) /gcix) {
					my $file = $1 || $2 || $3 || $4;	
					$self->include($file, $line);
					next;		# get next line
		}
				else {
		$line->error("%include expects a file name\n");
	}
			}
			else {
				# ignore other unknown directives
				next;		# get next line
			}
		}
		else {
			# TODO: macro expansion
		}
		
		# return complete line
		return $line;
	}
}



( run in 1.417 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )