line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# $Id: Preproc.pm,v 1.15 2013/07/26 01:57:26 Paulo Exp $
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Asm::Preproc;
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 NAME
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Asm::Preproc - Preprocessor to be called from an assembler
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=cut
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
14
|
|
|
|
|
|
|
|
15
|
6
|
|
|
6
|
|
35728
|
use warnings;
|
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
206
|
|
16
|
6
|
|
|
6
|
|
35
|
use strict;
|
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
142
|
|
17
|
|
|
|
|
|
|
|
18
|
6
|
|
|
6
|
|
32
|
use File::Spec;
|
|
6
|
|
|
|
|
17
|
|
|
6
|
|
|
|
|
166
|
|
19
|
6
|
|
|
6
|
|
3811
|
use Asm::Preproc::Line;
|
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
166
|
|
20
|
6
|
|
|
6
|
|
11218
|
use Iterator::Simple::Lookahead;
|
|
6
|
|
|
|
|
34434
|
|
|
6
|
|
|
|
|
403
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our $VERSION = '1.02';
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
use Asm::Preproc;
|
29
|
|
|
|
|
|
|
my $pp = Asm::Preproc->new();
|
30
|
|
|
|
|
|
|
my $pp = Asm::Preproc->new(@files);
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$pp->add_path(@path); @path = $pp->path;
|
33
|
|
|
|
|
|
|
$pp->include($file); $pp->include($file, $from_line);
|
34
|
|
|
|
|
|
|
my $full_path = $pp->path_search($file);
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
$pp->include_list(@input);
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my $iter = sub {return scalar };
|
39
|
|
|
|
|
|
|
$pp->include_list($iter);
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my $line = $pp->getline; # isa Asm::Preproc::Line
|
42
|
|
|
|
|
|
|
my $strm = $pp->line_stream; # isa Iterator::Simple::Lookahead
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
This module implements a preprocessor that reads source files
|
47
|
|
|
|
|
|
|
and handles recursive file includes.
|
48
|
|
|
|
|
|
|
It is intended to be called from inside an assembler or compiler.
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=cut
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# TODO: does conditional text expansion and macro substitution.
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head1 METHODS
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=head2 new
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
Creates a new object. If an argument list is given, calls C
|
59
|
|
|
|
|
|
|
for each of the file starting from the last, so that the files are
|
60
|
|
|
|
|
|
|
read in the given order.
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=cut
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
65
|
|
|
|
|
|
|
# Asm::Preproc::File : current file being read
|
66
|
|
|
|
|
|
|
use Class::XSAccessor::Array {
|
67
|
6
|
|
|
|
|
67
|
class => 'Asm::Preproc::File',
|
68
|
|
|
|
|
|
|
accessors => {
|
69
|
|
|
|
|
|
|
iter => 0, # iter() to read each line
|
70
|
|
|
|
|
|
|
file => 1, # file name
|
71
|
|
|
|
|
|
|
line_nr => 2, # current line number
|
72
|
|
|
|
|
|
|
line_inc => 3, # line number increment
|
73
|
|
|
|
|
|
|
},
|
74
|
6
|
|
|
6
|
|
44
|
};
|
|
6
|
|
|
|
|
23
|
|
75
|
|
|
|
|
|
|
sub Asm::Preproc::File::new {
|
76
|
|
|
|
|
|
|
#my($class, $iter, $file) = @_;
|
77
|
30
|
|
|
30
|
|
54
|
my $class = shift;
|
78
|
30
|
|
|
|
|
173
|
bless [@_, 0, 1], $class;
|
79
|
|
|
|
|
|
|
}
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
82
|
|
|
|
|
|
|
# Asm::Preproc : stack of stuff to read
|
83
|
|
|
|
|
|
|
use Class::XSAccessor::Array {
|
84
|
6
|
|
|
|
|
42
|
accessors => {
|
85
|
|
|
|
|
|
|
_stack => 0, # stack of Asm::Preproc::File
|
86
|
|
|
|
|
|
|
_path => 1, # path of search directories
|
87
|
|
|
|
|
|
|
},
|
88
|
6
|
|
|
6
|
|
1654
|
};
|
|
6
|
|
|
|
|
14
|
|
89
|
|
|
|
|
|
|
|
90
|
6
|
|
|
6
|
|
880
|
use constant TOP => -1; # top of stack, i.e. current input file
|
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
8287
|
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub new {
|
93
|
20
|
|
|
20
|
1
|
11005
|
my($class, @files) = @_;
|
94
|
20
|
|
|
|
|
74
|
my $self = bless [
|
95
|
|
|
|
|
|
|
[], # stack
|
96
|
|
|
|
|
|
|
[], # path
|
97
|
|
|
|
|
|
|
], $class;
|
98
|
20
|
|
|
|
|
100
|
$self->include($_) for reverse @files;
|
99
|
19
|
|
|
|
|
115
|
return $self;
|
100
|
|
|
|
|
|
|
}
|
101
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=head2 path
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Returns the list of directories to search in sequence for source files.
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=cut
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
110
|
3
|
|
|
3
|
1
|
7
|
sub path { @{$_[0]->_path} }
|
|
3
|
|
|
|
|
22
|
|
111
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head2 add_path
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Adds the given directories to the path searched for include files.
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=cut
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
120
|
|
|
|
|
|
|
sub add_path {
|
121
|
2
|
|
|
2
|
1
|
7
|
my($self, @dirs) = @_;
|
122
|
2
|
|
|
|
|
4
|
push @{$self->_path}, @dirs;
|
|
2
|
|
|
|
|
10
|
|
123
|
|
|
|
|
|
|
}
|
124
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head2 path_search
|
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
Searches for the given file in the C created by C, returns
|
129
|
|
|
|
|
|
|
the first full path name where the file can be found.
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Returns the input file name if the file is found in the current directory,
|
132
|
|
|
|
|
|
|
or if it is not found in any of the C directories.
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=cut
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
137
|
|
|
|
|
|
|
sub path_search {
|
138
|
27
|
|
|
27
|
1
|
49
|
my($self, $file) = @_;
|
139
|
|
|
|
|
|
|
|
140
|
27
|
100
|
|
|
|
534
|
return $file if -f $file; # found
|
141
|
|
|
|
|
|
|
|
142
|
7
|
|
|
|
|
15
|
for my $dir (@{$self->_path}) {
|
|
7
|
|
|
|
|
31
|
|
143
|
8
|
|
|
|
|
111
|
my $full_path = File::Spec->catfile($dir, $file);
|
144
|
8
|
100
|
|
|
|
171
|
return $full_path if -f $full_path;
|
145
|
|
|
|
|
|
|
}
|
146
|
|
|
|
|
|
|
|
147
|
2
|
|
|
|
|
32
|
return $file; # not found
|
148
|
|
|
|
|
|
|
}
|
149
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head2 include
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Open the input file and sets-up the object to read each line in sequence.
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
The optional second argument is a L
|
156
|
|
|
|
|
|
|
object pointing at the C<%include> line that included the file, to be used
|
157
|
|
|
|
|
|
|
in error messages.
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
An exception is raised if the input file cannot be read, or if a file is
|
160
|
|
|
|
|
|
|
included recursively, to avoid an infinite include loop.
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=cut
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
165
|
|
|
|
|
|
|
sub include {
|
166
|
23
|
|
|
23
|
1
|
47
|
my($self, $file, $from_line) = @_;
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# search include path
|
169
|
23
|
|
|
|
|
62
|
my $full_path = $self->path_search($file);
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# check for include loop
|
172
|
23
|
100
|
|
|
|
47
|
if (grep {$_->file eq $full_path} @{$self->_stack}) {
|
|
16
|
|
|
|
|
79
|
|
|
23
|
|
|
|
|
114
|
|
173
|
1
|
|
33
|
|
|
15
|
($from_line || Asm::Preproc::Line->new)
|
174
|
|
|
|
|
|
|
->error("%include loop")
|
175
|
|
|
|
|
|
|
}
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# open the file
|
178
|
22
|
100
|
33
|
|
|
772
|
open(my $fh, $full_path) or
|
179
|
|
|
|
|
|
|
($from_line || Asm::Preproc::Line->new)
|
180
|
|
|
|
|
|
|
->error("unable to open input file '$full_path'");
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# create a new iterator to read file lines
|
183
|
|
|
|
|
|
|
my $iter = sub {
|
184
|
48
|
50
|
|
48
|
|
113
|
return undef unless $fh;
|
185
|
48
|
|
|
|
|
424
|
my $text = <$fh>;
|
186
|
48
|
100
|
|
|
|
169
|
defined($text) and return $text;
|
187
|
|
|
|
|
|
|
|
188
|
18
|
|
|
|
|
200
|
undef $fh; # close fh at end of file
|
189
|
18
|
|
|
|
|
41
|
return undef;
|
190
|
21
|
|
|
|
|
103
|
};
|
191
|
21
|
|
|
|
|
65
|
$self->_push_iter($iter, $full_path);
|
192
|
|
|
|
|
|
|
}
|
193
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head2 include_list
|
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Sets-up the object to read each element of the passed input
|
198
|
|
|
|
|
|
|
list one line at a time.
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Each element of the list is either a text string
|
201
|
|
|
|
|
|
|
or a code reference of an iterator.
|
202
|
|
|
|
|
|
|
The iterator may return text strings, or other iterators that will be
|
203
|
|
|
|
|
|
|
called recursively. The iterator returns C at the end of input.
|
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
The text strings are split by lines, so that each C calls returns
|
206
|
|
|
|
|
|
|
one complete line.
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
As the text lines are scanned for pre-processor directives, the following two
|
209
|
|
|
|
|
|
|
lines are equivalent:
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
$pp->include('file.asm');
|
212
|
|
|
|
|
|
|
$pp->include_list('%include ');
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=cut
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
217
|
|
|
|
|
|
|
sub include_list {
|
218
|
9
|
|
|
9
|
1
|
37
|
my($self, @input) = @_;
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# create a new iterator to read text lines from iterators or strings
|
221
|
|
|
|
|
|
|
my $iter = sub {
|
222
|
66
|
|
|
66
|
|
106
|
while (1) {
|
223
|
106
|
100
|
|
|
|
252
|
return undef unless @input;
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# call iterator to get first string, if any
|
226
|
96
|
100
|
|
|
|
256
|
if (ref $input[0]) {
|
227
|
32
|
|
|
|
|
80
|
my $text = $input[0]->(); # get first from iterator
|
228
|
32
|
100
|
|
|
|
169
|
if (defined $text) {
|
229
|
29
|
|
|
|
|
58
|
unshift @input, $text; # insert line at head
|
230
|
|
|
|
|
|
|
}
|
231
|
|
|
|
|
|
|
else {
|
232
|
3
|
|
|
|
|
8
|
shift @input; # iter exhausted, drop it
|
233
|
|
|
|
|
|
|
}
|
234
|
32
|
|
|
|
|
59
|
next; # need to test list again
|
235
|
|
|
|
|
|
|
}
|
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# line is a string, return each complete line
|
238
|
64
|
|
|
|
|
139
|
for ($input[0]) {
|
239
|
64
|
100
|
|
|
|
157
|
last unless defined $_; # skip undef lines
|
240
|
60
|
100
|
|
|
|
359
|
if (/ \G ( .*? \n | .+ ) /gcx) {
|
241
|
56
|
100
|
|
|
|
153
|
shift @input if pos == length; # consumed all, drop it
|
242
|
56
|
|
|
|
|
236
|
return $1;
|
243
|
|
|
|
|
|
|
}
|
244
|
|
|
|
|
|
|
}
|
245
|
8
|
|
|
|
|
14
|
shift @input; # end of input
|
246
|
|
|
|
|
|
|
}
|
247
|
9
|
|
|
|
|
58
|
};
|
248
|
9
|
|
|
|
|
32
|
$self->_push_iter($iter, "-");
|
249
|
|
|
|
|
|
|
}
|
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
252
|
|
|
|
|
|
|
# prepare the object to read the given iterator and file name
|
253
|
|
|
|
|
|
|
sub _push_iter {
|
254
|
30
|
|
|
30
|
|
66
|
my($self, $iter, $file) = @_;
|
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# new file in the stack
|
257
|
30
|
|
|
|
|
105
|
push @{$self->_stack}, Asm::Preproc::File->new($iter, $file);
|
|
30
|
|
|
|
|
232
|
|
258
|
|
|
|
|
|
|
}
|
259
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=head2 getline
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
Returns the next line from the input, after doing all the pre-processing.
|
264
|
|
|
|
|
|
|
The line is returned as a L object
|
265
|
|
|
|
|
|
|
containing the actual text, and the file and line number where the text
|
266
|
|
|
|
|
|
|
was found.
|
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Returns C at the end of the input.
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=cut
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
273
|
|
|
|
|
|
|
# return next line as a Asm::Preproc::Line object
|
274
|
|
|
|
|
|
|
sub getline {
|
275
|
99
|
|
|
99
|
1
|
8951
|
my($self) = @_;
|
276
|
|
|
|
|
|
|
|
277
|
99
|
|
|
|
|
153
|
while (1) {
|
278
|
142
|
100
|
|
|
|
180
|
return undef unless @{$self->_stack}; # no more files
|
|
142
|
|
|
|
|
625
|
|
279
|
109
|
|
|
|
|
234
|
my $top = $self->_stack->[TOP];
|
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# read line
|
282
|
109
|
|
|
|
|
273
|
my $text = $top->iter->();
|
283
|
109
|
100
|
|
|
|
283
|
if (! defined $text) { # file finished, read next
|
284
|
27
|
|
|
|
|
41
|
pop @{$self->_stack};
|
|
27
|
|
|
|
|
68
|
|
285
|
27
|
|
|
|
|
225
|
next;
|
286
|
|
|
|
|
|
|
}
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
# inc line number, save it to use as the line_nr of a multi-line
|
289
|
|
|
|
|
|
|
# continuation
|
290
|
82
|
|
|
|
|
254
|
my $line_nr = $top->line_nr( $top->line_nr + $top->line_inc );
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
# while line ends in \\, remove all blanks before it and \r \n after
|
293
|
|
|
|
|
|
|
# the line contains at most one \n, due to include_list() iterator
|
294
|
82
|
|
|
|
|
307
|
while ($text =~ s/ \s* \\ [\r\n]* \z / /x) {
|
295
|
5
|
|
|
|
|
16
|
my $next = $top->iter->();
|
296
|
5
|
|
|
|
|
19
|
$top->line_nr( $top->line_nr + $top->line_inc );
|
297
|
|
|
|
|
|
|
|
298
|
5
|
100
|
|
|
|
13
|
defined($next) or last; # no more input, ignore last \\
|
299
|
4
|
|
|
|
|
21
|
$text .= $next;
|
300
|
|
|
|
|
|
|
}
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# normalize eol
|
303
|
82
|
|
|
|
|
485
|
$text =~ s/ \s* \z /\n/x; # any ending blanks replaced by \n
|
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# line to be returned, is used in %include below
|
306
|
82
|
|
|
|
|
487
|
my $line = Asm::Preproc::Line->new($text, $top->file, $line_nr);
|
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# check for pre-processor directives
|
309
|
82
|
100
|
|
|
|
321
|
if ($text =~ /^ \s* [\#\%] /gcix) {
|
310
|
18
|
100
|
|
|
|
80
|
if ($text =~ / \G line /gcix) {
|
|
|
50
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# %line n+m file
|
312
|
|
|
|
|
|
|
# #line n "file"
|
313
|
6
|
50
|
|
|
|
22
|
if ($text =~ / \G \s+ (\d+) /gcix) { # line_nr
|
314
|
6
|
|
|
|
|
17
|
$top->line_nr( $1 );
|
315
|
|
|
|
|
|
|
|
316
|
6
|
100
|
|
|
|
16
|
if ($text =~ / \G \+ (\d+) /gcix) { # optional line_inc
|
317
|
3
|
|
|
|
|
8
|
$top->line_inc( $1 );
|
318
|
|
|
|
|
|
|
}
|
319
|
|
|
|
|
|
|
else {
|
320
|
3
|
|
|
|
|
8
|
$top->line_inc( 1 );
|
321
|
|
|
|
|
|
|
}
|
322
|
|
|
|
|
|
|
|
323
|
6
|
100
|
|
|
|
19
|
if ($text =~ / \G \s+ \"? ([^\"\s]+) \"? /gcix) { # file
|
324
|
4
|
|
|
|
|
12
|
$top->file( $1 );
|
325
|
|
|
|
|
|
|
}
|
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# next line in nr+inc
|
328
|
6
|
|
|
|
|
68
|
$top->line_nr( $top->line_nr - $top->line_inc );
|
329
|
6
|
|
|
|
|
17
|
next; # get next line
|
330
|
|
|
|
|
|
|
}
|
331
|
|
|
|
|
|
|
}
|
332
|
|
|
|
|
|
|
elsif ($text =~ / \G include /gcix) {
|
333
|
|
|
|
|
|
|
# %include
|
334
|
|
|
|
|
|
|
# #include 'file'
|
335
|
|
|
|
|
|
|
# %include "file"
|
336
|
|
|
|
|
|
|
# #include file
|
337
|
12
|
100
|
|
|
|
56
|
if ($text =~ / \G \s+ (?: \< ([^\>]+) \> |
|
338
|
|
|
|
|
|
|
\' ([^\']+) \' |
|
339
|
|
|
|
|
|
|
\" ([^\"]+) \" |
|
340
|
|
|
|
|
|
|
(\S+)
|
341
|
|
|
|
|
|
|
) /gcix) {
|
342
|
11
|
|
33
|
|
|
84
|
my $file = $1 || $2 || $3 || $4;
|
343
|
11
|
|
|
|
|
28
|
$self->include($file, $line);
|
344
|
10
|
|
|
|
|
38
|
next; # get next line
|
345
|
|
|
|
|
|
|
}
|
346
|
|
|
|
|
|
|
else {
|
347
|
1
|
|
|
|
|
6
|
$line->error("%include expects a file name\n");
|
348
|
|
|
|
|
|
|
}
|
349
|
|
|
|
|
|
|
}
|
350
|
|
|
|
|
|
|
else {
|
351
|
|
|
|
|
|
|
# ignore other unknown directives
|
352
|
0
|
|
|
|
|
0
|
next; # get next line
|
353
|
|
|
|
|
|
|
}
|
354
|
|
|
|
|
|
|
}
|
355
|
|
|
|
|
|
|
else {
|
356
|
|
|
|
|
|
|
# TODO: macro expansion
|
357
|
|
|
|
|
|
|
}
|
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# return complete line
|
360
|
64
|
|
|
|
|
195
|
return $line;
|
361
|
|
|
|
|
|
|
}
|
362
|
|
|
|
|
|
|
}
|
363
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head2 line_stream
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
Returns a L object that will
|
368
|
|
|
|
|
|
|
return the result of C on each C call.
|
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=cut
|
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
373
|
|
|
|
|
|
|
sub line_stream {
|
374
|
1
|
|
|
1
|
1
|
2
|
my($self) = @_;
|
375
|
1
|
|
|
4
|
|
6
|
return Iterator::Simple::Lookahead->new(sub {$self->getline});
|
|
4
|
|
|
|
|
524
|
|
376
|
|
|
|
|
|
|
}
|
377
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head1 PREPROCESSING
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
The following preprocessor-like lines are processed:
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
%line N+M FILE
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
nasm-like line directive, telling that the next input line is
|
386
|
|
|
|
|
|
|
line N from file FILE,
|
387
|
|
|
|
|
|
|
followed by lines N+M, N+2*M, ...
|
388
|
|
|
|
|
|
|
This information is used to generate error messages.
|
389
|
|
|
|
|
|
|
Usefull to parse a file preprocessed by nasm.
|
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
#line N "FILE"
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
cpp-like line directive, telling that the next input line is
|
394
|
|
|
|
|
|
|
line N from file FILE,
|
395
|
|
|
|
|
|
|
followed by lines N+1, N+2, ...
|
396
|
|
|
|
|
|
|
This information is used to generate error messages.
|
397
|
|
|
|
|
|
|
Usefull to parse a file preprocessed by cpp.
|
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
%include 'FILE'
|
400
|
|
|
|
|
|
|
%include "FILE"
|
401
|
|
|
|
|
|
|
%include
|
402
|
|
|
|
|
|
|
%include FILE
|
403
|
|
|
|
|
|
|
#include 'FILE'
|
404
|
|
|
|
|
|
|
#include "FILE"
|
405
|
|
|
|
|
|
|
#include
|
406
|
|
|
|
|
|
|
#include FILE
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
nasm/cpp-like include directive, asking to insert the contents
|
409
|
|
|
|
|
|
|
of the given file in the input stream.
|
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
All the other preprocessor-like lines are ignored, i.e. lines starting with '#' or '%'.
|
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=head1 AUTHOR
|
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
Paulo Custodio, C<< >>
|
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=head1 BUGS and FEEDBACK
|
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
Please report any bugs or feature requests through the web interface at
|
420
|
|
|
|
|
|
|
L.
|
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS
|
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
Inspired in the Netwide Assembler, L
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=head1 LICENSE and COPYRIGHT
|
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
Copyright (c) 2010 Paulo Custodio.
|
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
431
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published
|
432
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License.
|
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information.
|
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=cut
|
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
1; # End of Asm::Preproc
|