line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/local/bin/perl -w
|
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
|
|
2
|
eval 'exec /usr/local/bin/perl -w
-S $0 ${1+"$@"}' |
4
|
|
|
|
|
|
|
if 0; # not running under some shell |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# $Id: sqlpp,v 1.15 2007/03/24 12:22:30 dk Exp $
|
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
8
|
use strict;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
46
|
|
9
|
1
|
|
|
1
|
|
5
|
use vars qw($input $output @inc @context $context $sigdie %defines %macros $debug $VERSION);
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
239
|
|
10
|
1
|
|
|
1
|
|
5
|
use vars qw(%global); # for perldef
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
436
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
|
|
3
|
$VERSION = '0.06';
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# special predefined macros
|
15
|
|
|
|
|
|
|
%defines = (
|
16
|
|
|
|
|
|
|
__LINE__ => {
|
17
|
0
|
|
|
0
|
|
0
|
code => sub { $context->{line} },
|
18
|
|
|
|
|
|
|
},
|
19
|
|
|
|
|
|
|
__FILE__ => {
|
20
|
0
|
|
|
0
|
|
0
|
code => sub { $context->{file} },
|
21
|
|
|
|
|
|
|
},
|
22
|
|
|
|
|
|
|
__VERSION__ => {
|
23
|
0
|
|
|
0
|
|
0
|
code => sub { $VERSION },
|
24
|
|
|
|
|
|
|
},
|
25
|
|
|
|
|
|
|
'#' => {
|
26
|
|
|
|
|
|
|
num => 1,
|
27
|
|
|
|
|
|
|
name => '#',
|
28
|
|
|
|
|
|
|
code => sub {
|
29
|
1
|
|
|
1
|
|
3
|
my $x = $_[0];
|
30
|
1
|
|
|
|
|
4
|
$x =~ s/([\\'])/\\$1/gs;
|
31
|
1
|
|
|
|
|
5
|
"'$x'";
|
32
|
|
|
|
|
|
|
},
|
33
|
|
|
|
|
|
|
},
|
34
|
1
|
|
|
|
|
23
|
);
|
35
|
|
|
|
|
|
|
|
36
|
1
|
|
|
1
|
|
7
|
use constant MACRO_OFF => 0; # none
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
289
|
|
37
|
1
|
|
|
1
|
|
6
|
use constant MACRO_SIMPLE => 1; # #defines with no-parameters only
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
42
|
|
38
|
1
|
|
|
1
|
|
5
|
use constant MACRO_COMPLEX => 2; # #defines with parameters only
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
40
|
|
39
|
1
|
|
|
1
|
|
6
|
use constant MACRO_ALL => 3; # all #defines
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
33989
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# run
|
42
|
1
|
|
|
|
|
3
|
$debug = 0;
|
43
|
|
|
|
|
|
|
|
44
|
1
|
|
|
|
|
5
|
$context = new_context( file => 'command line', macro => MACRO_OFF );
|
45
|
1
|
|
|
|
|
8
|
parse_argv();
|
46
|
|
|
|
|
|
|
|
47
|
1
|
|
|
|
|
3
|
$context = new_context();
|
48
|
1
|
|
|
|
|
7
|
parse_input();
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# used for serving 'defined' call from #if, which is basically perl code
|
52
|
0
|
0
|
|
0
|
|
0
|
sub is_defined { exists ($defines{$_[0]}) ? 1 : 0 }
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
$SIG{__DIE__} = sub {
|
55
|
|
|
|
|
|
|
# avoid multiple wrappings by perl's "use" - careful when recovering from an eval!
|
56
|
1
|
50
|
|
1
|
|
5
|
die @_ if $sigdie++;
|
57
|
|
|
|
|
|
|
|
58
|
1
|
|
|
|
|
0
|
die "error in `$context->{file}', line #$context->{line}: ", @_, "\n";
|
59
|
1
|
|
|
|
|
20
|
};
|
60
|
1
|
|
|
|
|
4
|
parse_file(1);
|
61
|
0
|
|
|
|
|
0
|
exit;
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# a context defines state of parser in a file
|
64
|
|
|
|
|
|
|
sub new_context
|
65
|
|
|
|
|
|
|
{
|
66
|
|
|
|
|
|
|
{
|
67
|
2
|
|
|
2
|
|
25
|
line => 0,
|
68
|
|
|
|
|
|
|
buf => '',
|
69
|
|
|
|
|
|
|
in_comment => 0,
|
70
|
|
|
|
|
|
|
ifdef => [{state => 1,passive=>[]}],
|
71
|
|
|
|
|
|
|
in_sql => 0,
|
72
|
|
|
|
|
|
|
macro => MACRO_ALL,
|
73
|
|
|
|
|
|
|
strip => 1,
|
74
|
|
|
|
|
|
|
@_
|
75
|
|
|
|
|
|
|
}
|
76
|
|
|
|
|
|
|
}
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# does buffered input
|
79
|
|
|
|
|
|
|
sub getline
|
80
|
|
|
|
|
|
|
{
|
81
|
131
|
|
|
131
|
|
165
|
my $undef_if_eof = $_[0];
|
82
|
131
|
100
|
|
|
|
274
|
if ( length $context->{buf}) {
|
83
|
17
|
|
|
|
|
29
|
my $ret = $context->{buf};
|
84
|
17
|
|
|
|
|
26
|
$context->{buf} = '';
|
85
|
17
|
|
|
|
|
42
|
return $ret;
|
86
|
|
|
|
|
|
|
}
|
87
|
114
|
|
|
|
|
129
|
my $ret;
|
88
|
114
|
50
|
|
|
|
349
|
unless ( defined ($ret = <$input>)) {
|
89
|
0
|
0
|
|
|
|
0
|
die "Unexpected end of input\n" unless $undef_if_eof;
|
90
|
|
|
|
|
|
|
} else {
|
91
|
114
|
|
|
|
|
161
|
$context->{line}++;
|
92
|
|
|
|
|
|
|
}
|
93
|
114
|
|
|
|
|
371
|
$ret;
|
94
|
|
|
|
|
|
|
}
|
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# skips input until the EOL
|
97
|
43
|
|
|
43
|
|
134
|
sub eatline { $context->{buf} = '' }
|
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# returns next token from input stream
|
100
|
|
|
|
|
|
|
sub gettok
|
101
|
|
|
|
|
|
|
{
|
102
|
28
|
|
|
28
|
|
36
|
while ( 1) {
|
103
|
28
|
50
|
|
|
|
64
|
unless ( length $context->{buf}) {
|
104
|
0
|
0
|
|
|
|
0
|
unless ( defined ($context->{buf} = <$input>)) {
|
105
|
0
|
|
|
|
|
0
|
die "Unexpected end of input\n";
|
106
|
|
|
|
|
|
|
}
|
107
|
0
|
|
|
|
|
0
|
chomp $context->{buf};
|
108
|
0
|
|
|
|
|
0
|
$context->{line}++;
|
109
|
|
|
|
|
|
|
}
|
110
|
|
|
|
|
|
|
|
111
|
28
|
|
|
|
|
64
|
$context->{buf} =~ s/^\s+//;
|
112
|
|
|
|
|
|
|
|
113
|
28
|
50
|
|
|
|
157
|
return $1
|
114
|
|
|
|
|
|
|
if $context-> {buf} =~ s/^(\w+|\S)//;
|
115
|
|
|
|
|
|
|
}
|
116
|
|
|
|
|
|
|
}
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# returns ID from input stream
|
119
|
|
|
|
|
|
|
sub getid
|
120
|
|
|
|
|
|
|
{
|
121
|
28
|
|
|
28
|
|
77
|
my $tok = gettok;
|
122
|
28
|
50
|
|
|
|
109
|
die "Identificator expected\n" unless $tok =~ /^\w+$/;
|
123
|
28
|
|
|
|
|
51
|
$tok;
|
124
|
|
|
|
|
|
|
}
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Line handle is a state of the parser as it progresses through input .
|
127
|
|
|
|
|
|
|
# The idea is to avoid accumultaion of input until the end of input, and
|
128
|
|
|
|
|
|
|
# spew processed data as soon as possible. The calling routing thus is
|
129
|
|
|
|
|
|
|
# begin_line / while( not parse_line) / print end_line, with different
|
130
|
|
|
|
|
|
|
# variations.
|
131
|
|
|
|
|
|
|
#
|
132
|
|
|
|
|
|
|
# Currently, parse_line returns 0 ( a signal to call end_line ) when
|
133
|
|
|
|
|
|
|
# bracket balance is achieved - but there's a bug with macro
|
134
|
|
|
|
|
|
|
# call MACRO\n() where MACRO and () are on different lines.
|
135
|
|
|
|
|
|
|
|
136
|
2
|
|
|
2
|
|
8
|
sub new_line_handle { {} }
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub begin_line
|
139
|
|
|
|
|
|
|
{
|
140
|
47
|
|
66
|
47
|
|
112
|
my $k = $_[0] || new_line_handle;
|
141
|
47
|
|
|
|
|
80
|
$k-> {var} = ''; # text to parse
|
142
|
47
|
|
|
|
|
103
|
$k-> {ids} = []; # stack of IDs met, f.ex. if var="A(b,C(d,", then ids=(A,C)
|
143
|
47
|
|
|
|
|
73
|
$k-> {last_id} = ''; # a candidate to ids
|
144
|
47
|
|
|
|
|
68
|
$k-> {last_pos} = 0; # stores pos(var) between calls
|
145
|
47
|
|
|
|
|
104
|
$k-> {storage} = [ 'copy', 0 ]; # accululates parsed info, to be run throung substitute_parameters later
|
146
|
47
|
|
|
|
|
111
|
$k-> {run_stack}= []; # stack of macro calls
|
147
|
47
|
|
|
|
|
72
|
$k-> {run} = $k-> {storage};# current macro call context
|
148
|
47
|
|
|
|
|
164
|
$k;
|
149
|
|
|
|
|
|
|
}
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub parse_line
|
152
|
|
|
|
|
|
|
{
|
153
|
52
|
|
|
52
|
|
68
|
my $k = $_[0];
|
154
|
52
|
|
100
|
|
|
227
|
$k-> {last_pos} = pos( $k-> {var}) || 0;
|
155
|
52
|
|
|
|
|
114
|
$k-> {var} .= $_[1];
|
156
|
52
|
|
|
|
|
76
|
my $full = $context-> {macro} & MACRO_COMPLEX;
|
157
|
52
|
|
|
|
|
71
|
my $simple = $context-> {macro} & MACRO_SIMPLE;
|
158
|
52
|
|
|
|
|
131
|
pos( $k-> {var}) = $k-> {last_pos};
|
159
|
|
|
|
|
|
|
{
|
160
|
|
|
|
|
|
|
# do comments
|
161
|
52
|
50
|
33
|
|
|
98
|
$context->{multiline_comment} and $k-> {var} =~ m/\G.*?(\*\/)?/gcs and do {
|
|
271
|
|
|
|
|
674
|
|
162
|
0
|
0
|
|
|
|
0
|
$context-> {multiline_comment} = 0 if $1;
|
163
|
0
|
|
|
|
|
0
|
redo;
|
164
|
|
|
|
|
|
|
};
|
165
|
|
|
|
|
|
|
( $k-> {var} =~ m/\G--/ or (
|
166
|
|
|
|
|
|
|
not $k-> {macro} and $k-> {var} =~ m/\G#/
|
167
|
271
|
50
|
66
|
|
|
1672
|
)) and do {
|
|
|
|
33
|
|
|
|
|
168
|
0
|
0
|
|
|
|
0
|
if ( $context->{strip}) {
|
|
|
0
|
|
|
|
|
|
169
|
0
|
|
|
|
|
0
|
my $savepos = pos( $k-> {var});
|
170
|
0
|
|
|
|
|
0
|
$k-> {var} =~ s/\G.*$//g;
|
171
|
0
|
|
|
|
|
0
|
pos( $k-> {var}) = $savepos;
|
172
|
|
|
|
|
|
|
} elsif ( $k-> {macro}) {
|
173
|
0
|
|
|
|
|
0
|
$k-> {var} =~ m/\G--/gc;
|
174
|
|
|
|
|
|
|
} else {
|
175
|
0
|
|
|
|
|
0
|
$k-> {var} =~ m/\G(--|#)/gc;
|
176
|
|
|
|
|
|
|
}
|
177
|
0
|
|
|
|
|
0
|
redo;
|
178
|
|
|
|
|
|
|
};
|
179
|
271
|
50
|
|
|
|
586
|
$k-> {var} =~ m/\G\/\*/gcs and do {
|
180
|
0
|
|
|
|
|
0
|
$context-> {multiline_comment} = 1;
|
181
|
0
|
|
|
|
|
0
|
redo;
|
182
|
|
|
|
|
|
|
};
|
183
|
271
|
50
|
|
|
|
501
|
$k-> {var} =~ m/\G-+/gc and redo;
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# do identifiers
|
186
|
271
|
100
|
|
|
|
714
|
$k-> {var} =~ m/\G(\w+)/gcs and do {
|
187
|
82
|
100
|
100
|
|
|
509
|
if ( $k->{parameters} and exists $k->{parameters}->{$1}) {
|
|
|
100
|
66
|
|
|
|
|
188
|
10
|
|
|
|
|
18
|
$k-> {last_id} = '';
|
189
|
10
|
|
|
|
|
11
|
push @{$k->{run}},
|
|
10
|
|
|
|
|
64
|
|
190
|
|
|
|
|
|
|
pos( $k->{var}) - length($1),
|
191
|
|
|
|
|
|
|
'parameter', $k->{parameters}->{$1},
|
192
|
|
|
|
|
|
|
'copy', pos( $k->{var});
|
193
|
|
|
|
|
|
|
} elsif ( $simple and exists $defines{$1}) {
|
194
|
8
|
|
|
|
|
24
|
my ( $l1, $d, $p) = ( length( $1), $defines{$1}, pos($k->{var}));
|
195
|
8
|
|
|
|
|
13
|
$k-> {last_id} = '';
|
196
|
8
|
|
|
|
|
11
|
push @{$k->{run}},
|
|
8
|
|
|
|
|
37
|
|
197
|
|
|
|
|
|
|
$p - $l1,
|
198
|
|
|
|
|
|
|
'define', $defines{$1},
|
199
|
|
|
|
|
|
|
'copy', $p;
|
200
|
|
|
|
|
|
|
} else {
|
201
|
64
|
|
|
|
|
121
|
$k-> {last_id} = $1;
|
202
|
64
|
|
|
|
|
150
|
$k-> {last_id_pos_start} = pos($k-> {var}) - length($1);
|
203
|
|
|
|
|
|
|
}
|
204
|
82
|
50
|
|
|
|
221
|
print "- id $k->{last_id}\n" if $debug;
|
205
|
82
|
|
|
|
|
90
|
redo;
|
206
|
|
|
|
|
|
|
};
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# do opening bracket
|
209
|
189
|
100
|
66
|
|
|
821
|
$full and $k-> {var} =~ m/\G\(\s*/gcs and do {
|
210
|
24
|
|
|
|
|
25
|
push @{$k-> {ids}}, [ $k-> {last_id}, $context->{line}];
|
|
24
|
|
|
|
|
100
|
|
211
|
24
|
100
|
66
|
|
|
133
|
if ( length $k->{last_id} and $macros{$k->{last_id}}) {
|
212
|
22
|
|
|
|
|
23
|
push @{$k->{run_stack}}, $k->{run};
|
|
22
|
|
|
|
|
55
|
|
213
|
22
|
|
|
|
|
27
|
push @{$k->{run}},
|
|
22
|
|
|
|
|
121
|
|
214
|
|
|
|
|
|
|
$k-> {last_id_pos_start},
|
215
|
|
|
|
|
|
|
'macro', $macros{$k->{last_id}},
|
216
|
|
|
|
|
|
|
[
|
217
|
|
|
|
|
|
|
'copy', pos($k->{var}),
|
218
|
|
|
|
|
|
|
];
|
219
|
22
|
|
|
|
|
50
|
$k->{run} = $k->{run}->[-1];
|
220
|
|
|
|
|
|
|
}
|
221
|
24
|
|
|
|
|
28
|
$k-> {last_id} = '';
|
222
|
24
|
50
|
|
|
|
56
|
print "- open\n" if $debug;
|
223
|
24
|
|
|
|
|
28
|
redo;
|
224
|
|
|
|
|
|
|
};
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# nulling ID after right after comments and IDs are processed is basically
|
227
|
|
|
|
|
|
|
# a grammar rule that states that in a macro call nothing except a comment
|
228
|
|
|
|
|
|
|
# and whitespace can be present between a macro ID and an opening bracket
|
229
|
165
|
100
|
|
|
|
408
|
$k-> {var} =~ m/\G\s+/gcs and redo;
|
230
|
112
|
|
|
|
|
218
|
$k-> {last_id} = '';
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# do closing bracket
|
233
|
112
|
100
|
66
|
|
|
513
|
$full and $k-> {var} =~ m/\G(\s*\))/gcs and do {
|
234
|
24
|
|
|
|
|
62
|
die "Brackets mismatch at character ", pos($k-> {var})-$k-> {last_pos}, "\n"
|
235
|
24
|
50
|
|
|
|
27
|
unless @{$k-> {ids}};
|
236
|
24
|
|
|
|
|
27
|
my $id = (pop @{$k->{ids}})->[0];
|
|
24
|
|
|
|
|
75
|
|
237
|
24
|
50
|
|
|
|
63
|
print "- close [$id]\n" if $debug;
|
238
|
|
|
|
|
|
|
|
239
|
24
|
100
|
66
|
|
|
97
|
if ( length $id and $macros{$id}) {
|
240
|
22
|
|
|
|
|
24
|
push @{$k->{run}}, pos($k->{var}) - length($1);
|
|
22
|
|
|
|
|
65
|
|
241
|
22
|
|
|
|
|
27
|
$k->{run} = pop @{$k->{run_stack}};
|
|
22
|
|
|
|
|
40
|
|
242
|
22
|
|
|
|
|
29
|
push @{$k->{run}}, 'copy', pos($k->{var});
|
|
22
|
|
|
|
|
59
|
|
243
|
|
|
|
|
|
|
}
|
244
|
24
|
|
|
|
|
32
|
redo;
|
245
|
|
|
|
|
|
|
};
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# do next param
|
248
|
88
|
100
|
66
|
|
|
354
|
$full and $k-> {var} =~ m/\G(\s*,\s*)/gcs and do {
|
249
|
16
|
50
|
|
|
|
20
|
redo unless @{$k->{ids}};
|
|
16
|
|
|
|
|
36
|
|
250
|
|
|
|
|
|
|
|
251
|
16
|
50
|
66
|
|
|
86
|
if ( length($k->{ids}->[-1]->[0]) and
|
|
14
|
|
66
|
|
|
64
|
|
252
|
|
|
|
|
|
|
$macros{$k->{ids}->[-1]->[0]} and @{$k->{run_stack}}) {
|
253
|
14
|
|
|
|
|
18
|
push @{$k->{run}},
|
|
14
|
|
|
|
|
71
|
|
254
|
|
|
|
|
|
|
pos($k-> {var}) - length($1),
|
255
|
|
|
|
|
|
|
'next',
|
256
|
|
|
|
|
|
|
'copy', pos($k-> {var})
|
257
|
|
|
|
|
|
|
}
|
258
|
16
|
|
|
|
|
22
|
redo;
|
259
|
|
|
|
|
|
|
};
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# special # and ## operators
|
262
|
72
|
100
|
100
|
|
|
211
|
$k->{macro} and $k->{var} =~ /\G\#(?:(\#\s*)|(\s*)(\w+)|(.*))/gcs and do {
|
263
|
5
|
100
|
66
|
|
|
24
|
if ( defined $1) {
|
|
|
100
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# concatenation
|
265
|
3
|
|
|
|
|
6
|
my $minus = 1 + length($1);
|
266
|
3
|
|
66
|
|
|
34
|
$minus++ while
|
267
|
|
|
|
|
|
|
$minus < pos($k->{var}) and
|
268
|
|
|
|
|
|
|
substr( $k->{var}, pos($k->{var}) - $minus - 1, 1) eq ' ';
|
269
|
3
|
|
|
|
|
5
|
push @{$k->{run}},
|
|
3
|
|
|
|
|
22
|
|
270
|
|
|
|
|
|
|
pos($k->{var}) - $minus,
|
271
|
|
|
|
|
|
|
'copy', pos($k->{var});
|
272
|
|
|
|
|
|
|
} elsif ( defined $3 and exists $k->{parameters}->{$3}) {
|
273
|
|
|
|
|
|
|
# stringification
|
274
|
1
|
|
|
|
|
2
|
push @{$k->{run}},
|
|
1
|
|
|
|
|
10
|
|
275
|
|
|
|
|
|
|
pos($k->{var}) - 1 - length($2) - length($3),
|
276
|
|
|
|
|
|
|
'macro', $defines{'#'},
|
277
|
|
|
|
|
|
|
[ 'parameter', $k->{parameters}->{$3} ],
|
278
|
|
|
|
|
|
|
'copy', pos($k->{var});
|
279
|
|
|
|
|
|
|
} else {
|
280
|
1
|
50
|
|
|
|
20
|
die "'#' is not followed by a macro parameter (",
|
281
|
|
|
|
|
|
|
(( defined $3) ? $3 : $4),
|
282
|
|
|
|
|
|
|
")\n";
|
283
|
|
|
|
|
|
|
}
|
284
|
4
|
|
|
|
|
6
|
redo;
|
285
|
|
|
|
|
|
|
};
|
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
# we do ''-only strings
|
288
|
67
|
100
|
66
|
|
|
293
|
$full and $k-> {var} =~ m/\G'[^']*'/gcs and redo;
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# everything else
|
291
|
66
|
50
|
|
|
|
145
|
if ( $full) {
|
292
|
66
|
100
|
|
|
|
167
|
$k-> {var} =~ m/\G[^\w\(\)\'\-\,\#]+/gcs and redo;
|
293
|
|
|
|
|
|
|
} else {
|
294
|
0
|
0
|
|
|
|
0
|
$k-> {var} =~ m/\G[^\w\-\#]+/gcs and redo;
|
295
|
|
|
|
|
|
|
}
|
296
|
51
|
50
|
33
|
|
|
116
|
!$full and $k-> {var} =~ m/\G[\(\)\']+/gcs and redo;
|
297
|
|
|
|
|
|
|
|
298
|
51
|
50
|
|
|
|
99
|
print "? stop at ", pos($k-> {var}), "\n" if $debug;
|
299
|
51
|
50
|
|
|
|
84
|
print +('.' x (pos($k-> {var})-1)), "v\n$k->{var}\n" if $debug;
|
300
|
|
|
|
|
|
|
}
|
301
|
|
|
|
|
|
|
|
302
|
51
|
50
|
|
|
|
48
|
return scalar(@{$k-> {ids}}) ? 0 : 1;
|
|
51
|
|
|
|
|
247
|
|
303
|
|
|
|
|
|
|
}
|
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub end_parse_line
|
306
|
|
|
|
|
|
|
{
|
307
|
45
|
|
|
45
|
|
50
|
my $k = $_[0];
|
308
|
45
|
|
|
|
|
109
|
die "Brackets don't match at character ", pos($k->{var}) - $k-> {last_pos}, ", line $k->{ids}->[-1]->[1]\n"
|
309
|
45
|
50
|
|
|
|
43
|
if @{$k-> {ids}};
|
310
|
45
|
|
|
|
|
51
|
push @{$k->{run}}, length($k->{var});
|
|
45
|
|
|
|
|
151
|
|
311
|
45
|
|
|
|
|
185
|
delete @$k{qw(run run_stack last_id last_pos last_id_pos_start ids)};
|
312
|
|
|
|
|
|
|
}
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# input:
|
315
|
|
|
|
|
|
|
# k - text reference object
|
316
|
|
|
|
|
|
|
# v - set of commands, where 'copy' referes to text chunks in k
|
317
|
|
|
|
|
|
|
# p - set of actual parameters to be substututed
|
318
|
|
|
|
|
|
|
# output:
|
319
|
|
|
|
|
|
|
# text with parameters substituted
|
320
|
|
|
|
|
|
|
sub substitute_parameters
|
321
|
|
|
|
|
|
|
{
|
322
|
70
|
|
|
70
|
|
103
|
my ( $k, $v, $parameters) = @_;
|
323
|
|
|
|
|
|
|
|
324
|
70
|
|
|
|
|
177
|
my @output = ('');
|
325
|
|
|
|
|
|
|
|
326
|
70
|
|
|
|
|
826
|
for ( my $i = 0; $i < @$v; ) {
|
327
|
182
|
|
|
|
|
280
|
my $cmd = $v->[$i++];
|
328
|
182
|
100
|
|
|
|
391
|
if ( $cmd eq 'copy') {
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
329
|
126
|
|
|
|
|
341
|
$output[-1] .= substr( $k->{var}, $v->[$i], $v->[$i+1] - $v->[$i]);
|
330
|
126
|
|
|
|
|
299
|
$i += 2;
|
331
|
|
|
|
|
|
|
} elsif ( $cmd eq 'parameter') {
|
332
|
13
|
|
|
|
|
35
|
$output[-1] .= $parameters->[ $v->[$i++] ];
|
333
|
|
|
|
|
|
|
} elsif ( $cmd eq 'next') {
|
334
|
13
|
|
|
|
|
174
|
push @output, '';
|
335
|
|
|
|
|
|
|
} elsif ( $cmd eq 'macro') {
|
336
|
23
|
|
|
|
|
78
|
$output[-1] .= execute_macro(
|
337
|
|
|
|
|
|
|
$v->[$i],
|
338
|
|
|
|
|
|
|
substitute_parameters( $k, $v->[$i+1], $parameters)
|
339
|
|
|
|
|
|
|
);
|
340
|
23
|
|
|
|
|
76
|
$i += 2;
|
341
|
|
|
|
|
|
|
} elsif ( $cmd eq 'define') {
|
342
|
7
|
|
|
|
|
16
|
$output[-1] .= execute_macro( $v->[$i++]);
|
343
|
|
|
|
|
|
|
} else {
|
344
|
0
|
|
|
|
|
0
|
die "Internal error: unknown directive `$cmd' (i=$i, stack=@$v)\n";
|
345
|
|
|
|
|
|
|
}
|
346
|
|
|
|
|
|
|
}
|
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# XXX special case - zero parameters
|
349
|
70
|
100
|
100
|
|
|
354
|
return if 1 == @output and $output[0] eq '';
|
350
|
|
|
|
|
|
|
|
351
|
67
|
|
|
|
|
311
|
return @output;
|
352
|
|
|
|
|
|
|
}
|
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub execute_macro
|
355
|
|
|
|
|
|
|
{
|
356
|
30
|
|
|
30
|
|
55
|
my ( $handle, @params) = @_;
|
357
|
|
|
|
|
|
|
|
358
|
30
|
0
|
66
|
|
|
257
|
die sprintf "Macro `%s' requires %d argument%s, %d %s passed\n",
|
|
|
0
|
66
|
|
|
|
|
|
|
50
|
|
|
|
|
|
359
|
|
|
|
|
|
|
$handle->{name},
|
360
|
|
|
|
|
|
|
$handle->{num}, ( $handle->{num} == 1) ? '' : 's',
|
361
|
|
|
|
|
|
|
scalar(@params), (scalar(@params) == 1) ? 'was' : 'were'
|
362
|
|
|
|
|
|
|
unless $handle->{ellipsis} or
|
363
|
|
|
|
|
|
|
!defined($handle->{num}) or
|
364
|
|
|
|
|
|
|
$handle->{num} == scalar(@params);
|
365
|
|
|
|
|
|
|
|
366
|
30
|
100
|
|
|
|
511
|
return join($", $handle->{code}->(@params)) if $handle-> {code};
|
367
|
|
|
|
|
|
|
|
368
|
13
|
|
|
|
|
30
|
return join('', substitute_parameters(
|
369
|
|
|
|
|
|
|
$handle,
|
370
|
|
|
|
|
|
|
$handle->{storage},
|
371
|
|
|
|
|
|
|
\@params
|
372
|
|
|
|
|
|
|
));
|
373
|
|
|
|
|
|
|
}
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
sub end_line
|
376
|
|
|
|
|
|
|
{
|
377
|
34
|
|
|
34
|
|
50
|
my $k = $_[0];
|
378
|
34
|
|
|
|
|
64
|
end_parse_line($k);
|
379
|
34
|
|
|
|
|
126
|
return join('', substitute_parameters( $k, $k->{storage}, [] ));
|
380
|
|
|
|
|
|
|
}
|
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# begin_macro/end_macro pairs are same as begin_line/end_line, but for macro declaration purposes
|
383
|
|
|
|
|
|
|
sub begin_macro
|
384
|
|
|
|
|
|
|
{
|
385
|
12
|
|
|
12
|
|
24
|
my ( $name, $parametric, @params ) = @_;
|
386
|
|
|
|
|
|
|
|
387
|
12
|
|
|
|
|
16
|
my %p;
|
388
|
12
|
|
|
|
|
14
|
my $pno = 0;
|
389
|
12
|
|
|
|
|
20
|
for my $p ( @params) {
|
390
|
11
|
50
|
|
|
|
23
|
die "Error in macros `$name' definition: argument `$p' is used twice\n"
|
391
|
|
|
|
|
|
|
if $p{$p};
|
392
|
11
|
50
|
|
|
|
74
|
die "Error in macros `$name' definition: argument name `$p' is not a valid identifier\n"
|
393
|
|
|
|
|
|
|
if $p =~ /\'\(\)\#/;
|
394
|
11
|
|
|
|
|
36
|
$p{$p} = $pno++;
|
395
|
|
|
|
|
|
|
}
|
396
|
|
|
|
|
|
|
|
397
|
12
|
|
|
|
|
133
|
return begin_line {
|
398
|
|
|
|
|
|
|
parametric => $parametric,
|
399
|
|
|
|
|
|
|
parameters => \%p,
|
400
|
|
|
|
|
|
|
name => $name,
|
401
|
|
|
|
|
|
|
macro => 1,
|
402
|
|
|
|
|
|
|
line => $context->{line},
|
403
|
|
|
|
|
|
|
file => $context->{file},
|
404
|
|
|
|
|
|
|
};
|
405
|
|
|
|
|
|
|
}
|
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
sub end_macro
|
408
|
|
|
|
|
|
|
{
|
409
|
11
|
|
|
11
|
|
17
|
my $handle = $_[0];
|
410
|
11
|
|
|
|
|
14
|
end_parse_line( $handle);
|
411
|
|
|
|
|
|
|
|
412
|
11
|
100
|
|
|
|
26
|
if ( $handle->{parametric}) {
|
413
|
9
|
|
|
|
|
20
|
$macros{ $handle->{name} } = $handle;
|
414
|
9
|
|
|
|
|
12
|
$handle->{num} = scalar keys %{$handle->{parameters}};
|
|
9
|
|
|
|
|
27
|
|
415
|
|
|
|
|
|
|
} else {
|
416
|
2
|
|
|
|
|
6
|
$defines{ $handle->{name} } = $handle;
|
417
|
2
|
|
|
|
|
5
|
$handle->{num} = 0;
|
418
|
|
|
|
|
|
|
}
|
419
|
11
|
|
|
|
|
38
|
delete @$handle{qw(parametric macro)};
|
420
|
|
|
|
|
|
|
}
|
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub parse_pragma
|
423
|
|
|
|
|
|
|
{
|
424
|
0
|
|
|
0
|
|
0
|
my ( $pragma, $param) = @_;
|
425
|
0
|
0
|
|
|
|
0
|
if ( $pragma eq 'macro') {
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
426
|
0
|
0
|
|
|
|
0
|
if ( $param eq 'simple') {
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
427
|
0
|
|
|
|
|
0
|
$context->{macro} = MACRO_SIMPLE;
|
428
|
|
|
|
|
|
|
} elsif ( $param eq 'all') {
|
429
|
0
|
|
|
|
|
0
|
$context->{macro} = MACRO_ALL;
|
430
|
|
|
|
|
|
|
} elsif ( $param eq 'off') {
|
431
|
0
|
|
|
|
|
0
|
$context->{macro} = MACRO_OFF;
|
432
|
|
|
|
|
|
|
} else {
|
433
|
0
|
|
|
|
|
0
|
die "Invalid '#pragma macro($param)': should be 'all', 'simple', or 'off'\n";
|
434
|
|
|
|
|
|
|
}
|
435
|
|
|
|
|
|
|
} elsif ( $pragma eq 'comment') {
|
436
|
0
|
0
|
|
|
|
0
|
if ( $param eq 'strip') {
|
|
|
0
|
|
|
|
|
|
437
|
0
|
|
|
|
|
0
|
$context->{strip} = 1;
|
438
|
|
|
|
|
|
|
} elsif ( $param eq 'leave') {
|
439
|
0
|
|
|
|
|
0
|
$context->{strip} = 0;
|
440
|
|
|
|
|
|
|
} else {
|
441
|
0
|
|
|
|
|
0
|
die "Invalid '#pragma comments($param)': should be 'strip' or 'leave'\n";
|
442
|
|
|
|
|
|
|
}
|
443
|
|
|
|
|
|
|
} elsif ( $pragma eq 'lang') {
|
444
|
0
|
0
|
|
|
|
0
|
if ( $param eq 'sql') {
|
|
|
0
|
|
|
|
|
|
445
|
0
|
|
|
|
|
0
|
parse_pragma(qw(macro all));
|
446
|
0
|
|
|
|
|
0
|
parse_pragma(qw(comment strip));
|
447
|
|
|
|
|
|
|
} elsif ( $param eq 'perl') {
|
448
|
0
|
|
|
|
|
0
|
parse_pragma(qw(macro simple));
|
449
|
0
|
|
|
|
|
0
|
parse_pragma(qw(comment leave));
|
450
|
|
|
|
|
|
|
} else {
|
451
|
0
|
|
|
|
|
0
|
die "Invalid '#pragma lang($param)': should be 'sql' or 'perl'\n";
|
452
|
|
|
|
|
|
|
}
|
453
|
|
|
|
|
|
|
} else {
|
454
|
0
|
|
|
|
|
0
|
die "Unknown #pragma $pragma\n";
|
455
|
|
|
|
|
|
|
}
|
456
|
|
|
|
|
|
|
}
|
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# if a line begins with #, then parse_comment checks it first
|
459
|
|
|
|
|
|
|
sub parse_comment
|
460
|
|
|
|
|
|
|
{
|
461
|
63
|
|
|
63
|
|
70
|
my $eatline = 1;
|
462
|
63
|
|
|
|
|
64
|
my $what;
|
463
|
|
|
|
|
|
|
|
464
|
63
|
100
|
|
|
|
249
|
if ( $context->{buf} !~ s/^(\w+)\s+//) {
|
465
|
|
|
|
|
|
|
# a comment
|
466
|
21
|
|
|
|
|
56
|
eatline;
|
467
|
21
|
|
|
|
|
54
|
return;
|
468
|
|
|
|
|
|
|
} else {
|
469
|
42
|
|
|
|
|
78
|
$what = $1;
|
470
|
|
|
|
|
|
|
}
|
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
# parse if/else/elif/endif in the passive code less heavily
|
473
|
42
|
100
|
|
|
|
127
|
unless ( $context->{ifdef}->[-1]->{state}) {
|
474
|
6
|
50
|
|
|
|
27
|
if ( $what =~ /^if(n?def)?$/) {
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
475
|
0
|
|
|
|
|
0
|
push @{$context->{ifdef}->[-1]->{passive}}, 1; # flipsleft
|
|
0
|
|
|
|
|
0
|
|
476
|
|
|
|
|
|
|
} elsif ( $what eq 'else') {
|
477
|
3
|
50
|
|
|
|
4
|
goto NORMAL unless @{$context->{ifdef}->[-1]->{passive}};
|
|
3
|
|
|
|
|
31
|
|
478
|
0
|
0
|
|
|
|
0
|
die "Too many #else\n" unless $context->{ifdef}->[-1]->{passive}->[-1]--;
|
479
|
|
|
|
|
|
|
} elsif ( $what eq 'elif') {
|
480
|
0
|
0
|
|
|
|
0
|
goto NORMAL unless @{$context->{ifdef}->[-1]->{passive}};
|
|
0
|
|
|
|
|
0
|
|
481
|
|
|
|
|
|
|
} elsif ( $what eq 'endif') {
|
482
|
3
|
50
|
|
|
|
4
|
goto NORMAL unless @{$context->{ifdef}->[-1]->{passive}};
|
|
3
|
|
|
|
|
36
|
|
483
|
0
|
|
|
|
|
0
|
pop @{$context->{ifdef}->[-1]->{passive}};
|
|
0
|
|
|
|
|
0
|
|
484
|
|
|
|
|
|
|
}
|
485
|
0
|
|
|
|
|
0
|
eatline;
|
486
|
0
|
|
|
|
|
0
|
return;
|
487
|
|
|
|
|
|
|
}
|
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# normal '#' pragmas
|
490
|
|
|
|
|
|
|
NORMAL:
|
491
|
42
|
100
|
|
|
|
193
|
if ( $what eq 'define') {
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
492
|
14
|
|
|
|
|
32
|
my $heredoc = $context->{buf} =~ s/^</;
|
493
|
14
|
|
|
|
|
25
|
my $def = getid();
|
494
|
|
|
|
|
|
|
|
495
|
14
|
|
|
|
|
18
|
my @params;
|
496
|
14
|
|
|
|
|
15
|
my $parametric = 0;
|
497
|
14
|
100
|
|
|
|
63
|
if ( $context->{buf} =~ s/^\(([^\)]*)\)//) {
|
498
|
11
|
|
|
|
|
35
|
@params = map {
|
499
|
10
|
|
|
|
|
487
|
s/^\s*//;
|
500
|
11
|
|
|
|
|
34
|
s/\s*$//;
|
501
|
11
|
50
|
|
|
|
31
|
die "`$1' may not appear in macro parameter list\n"
|
502
|
|
|
|
|
|
|
if m/(\W)/;
|
503
|
11
|
|
|
|
|
36
|
$_
|
504
|
|
|
|
|
|
|
} split ',', $1;
|
505
|
10
|
|
|
|
|
18
|
$parametric = 1;
|
506
|
|
|
|
|
|
|
}
|
507
|
14
|
|
|
|
|
44
|
$context->{buf} =~ s/^\s*//;
|
508
|
|
|
|
|
|
|
|
509
|
14
|
|
|
|
|
20
|
$eatline = 0;
|
510
|
14
|
100
|
100
|
|
|
64
|
if ( $heredoc or length $context->{buf}) {
|
|
|
100
|
|
|
|
|
|
511
|
12
|
|
|
|
|
28
|
my $v = begin_macro( $def, $parametric, @params);
|
512
|
|
|
|
|
|
|
|
513
|
12
|
|
|
|
|
17
|
my $do_ml = 1;
|
514
|
12
|
|
|
|
|
24
|
while ( $do_ml) {
|
515
|
18
|
|
|
|
|
28
|
my $l = getline;
|
516
|
18
|
|
|
|
|
31
|
chomp $l;
|
517
|
18
|
100
|
|
|
|
28
|
if ( $heredoc) {
|
518
|
7
|
50
|
|
|
|
17
|
last if $l eq $def;
|
519
|
|
|
|
|
|
|
} else {
|
520
|
11
|
|
|
|
|
29
|
$do_ml = $l =~ s/\\\s*$//;
|
521
|
|
|
|
|
|
|
}
|
522
|
18
|
100
|
|
|
|
59
|
parse_line( $v, $l . ( $do_ml ? "\n" : ''));
|
523
|
|
|
|
|
|
|
}
|
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
# check if macro already exists by comparing with the macro body
|
526
|
11
|
100
|
|
|
|
27
|
my $ref = $parametric ? $macros{$def} : $defines{$def};
|
527
|
11
|
50
|
|
|
|
23
|
if ( defined $ref) {
|
528
|
0
|
|
|
|
|
0
|
my $fail;
|
529
|
0
|
0
|
|
|
|
0
|
if ( !defined $ref->{var}) {
|
530
|
0
|
|
|
|
|
0
|
$fail = 1;
|
531
|
|
|
|
|
|
|
} else {
|
532
|
|
|
|
|
|
|
$fail = (
|
533
|
0
|
|
0
|
|
|
0
|
join(':', keys %{$ref->{parameters}})
|
534
|
|
|
|
|
|
|
ne
|
535
|
|
|
|
|
|
|
join(':', @params)
|
536
|
|
|
|
|
|
|
) || (
|
537
|
|
|
|
|
|
|
$ref->{var}
|
538
|
|
|
|
|
|
|
ne
|
539
|
|
|
|
|
|
|
$v->{var}
|
540
|
|
|
|
|
|
|
);
|
541
|
|
|
|
|
|
|
}
|
542
|
0
|
0
|
|
|
|
0
|
warn "`$def' redefined, previous declaration in $ref->{file}:$ref->{line}\n"
|
543
|
|
|
|
|
|
|
if $fail;
|
544
|
|
|
|
|
|
|
}
|
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
# register the macro
|
547
|
11
|
|
|
|
|
21
|
end_macro( $v);
|
548
|
|
|
|
|
|
|
} elsif ( $parametric) { # special macro
|
549
|
1
|
50
|
33
|
|
|
6
|
warn "`$def' redefined, previous declaration in $macros{$def}->{file}:$macros{$def}->{line}\n"
|
550
|
|
|
|
|
|
|
if exists $macros{$def} and defined $macros{$def}->{var};
|
551
|
1
|
|
|
|
|
8
|
$macros{$def} = {
|
552
|
|
|
|
|
|
|
name => $def,
|
553
|
|
|
|
|
|
|
num => scalar(@params),
|
554
|
|
|
|
|
|
|
storage => [],
|
555
|
|
|
|
|
|
|
line => $context->{line},
|
556
|
|
|
|
|
|
|
file => $context->{file},
|
557
|
|
|
|
|
|
|
}
|
558
|
|
|
|
|
|
|
} else { # special define
|
559
|
1
|
50
|
33
|
|
|
46
|
warn "`$def' redefined, previous declaration in $defines{$def}->{file}:$defines{$def}->{line}\n"
|
560
|
|
|
|
|
|
|
if exists $defines{$def} and defined $defines{$def}->{var};
|
561
|
1
|
|
|
|
|
7
|
$defines{$def} = {
|
562
|
|
|
|
|
|
|
name => $def,
|
563
|
|
|
|
|
|
|
num => 0,
|
564
|
|
|
|
|
|
|
storage => [],
|
565
|
|
|
|
|
|
|
line => $context->{line},
|
566
|
|
|
|
|
|
|
file => $context->{file},
|
567
|
|
|
|
|
|
|
}
|
568
|
|
|
|
|
|
|
}
|
569
|
|
|
|
|
|
|
} elsif ( $what eq 'undef') {
|
570
|
3
|
|
|
|
|
7
|
my $def = getid();
|
571
|
3
|
|
|
|
|
12
|
delete $defines{$def};
|
572
|
3
|
|
|
|
|
6
|
delete $macros{$def};
|
573
|
|
|
|
|
|
|
} elsif ( $what =~ /if(n?)def/) {
|
574
|
6
|
|
|
|
|
12
|
my $def = getid();
|
575
|
6
|
100
|
|
|
|
16
|
my $notdef = length($1) ? 1 : 0;
|
576
|
6
|
100
|
|
|
|
7
|
push @{$context->{ifdef}}, {
|
|
6
|
100
|
|
|
|
43
|
|
577
|
|
|
|
|
|
|
state => exists($defines{$def}) ? !$notdef : $notdef,
|
578
|
|
|
|
|
|
|
flipsleft => 1,
|
579
|
|
|
|
|
|
|
passive => [],
|
580
|
|
|
|
|
|
|
do_else => exists($defines{$def}) ? $notdef : !$notdef,
|
581
|
|
|
|
|
|
|
};
|
582
|
|
|
|
|
|
|
} elsif ( $what eq 'if') {
|
583
|
1
|
|
|
|
|
2
|
my $do_ml = 1;
|
584
|
1
|
|
|
|
|
2
|
my $v = begin_line;
|
585
|
1
|
|
|
|
|
3
|
while ( $do_ml) {
|
586
|
1
|
|
|
|
|
3
|
my $l = getline;
|
587
|
1
|
|
|
|
|
3
|
chomp $l;
|
588
|
1
|
|
|
|
|
3
|
$do_ml = $l =~ s/\\\s*$//;
|
589
|
1
|
|
|
|
|
2
|
$l =~ s/defined\s*\(([^\)\s]+)\s*\)\s*/is_defined($1)/ge; # XXX a hack
|
|
0
|
|
|
|
|
0
|
|
590
|
1
|
50
|
|
|
|
4
|
parse_line( $v, $l . ( $do_ml ? "\n" : ''));
|
591
|
|
|
|
|
|
|
}
|
592
|
1
|
|
|
|
|
4
|
my $if = end_line($v);
|
593
|
1
|
|
|
|
|
73
|
my $ret = eval $if;
|
594
|
1
|
50
|
|
|
|
5
|
die $@ if $@;
|
595
|
1
|
50
|
|
|
|
1
|
push @{$context->{ifdef}}, {
|
|
1
|
50
|
|
|
|
8
|
|
596
|
|
|
|
|
|
|
state => $ret ? 1 : 0,
|
597
|
|
|
|
|
|
|
flipsleft => 1,
|
598
|
|
|
|
|
|
|
passive => [],
|
599
|
|
|
|
|
|
|
do_else => ( $ret ? 0 : 1),
|
600
|
|
|
|
|
|
|
};
|
601
|
1
|
|
|
|
|
4
|
$eatline = 0;
|
602
|
|
|
|
|
|
|
} elsif ( $what eq 'elif') {
|
603
|
0
|
|
|
|
|
0
|
die "Runaway #elif\n" if
|
604
|
0
|
|
|
|
|
0
|
0 == $#{$context->{ifdef}} or
|
605
|
0
|
0
|
0
|
|
|
0
|
@{$context->{ifdef}->[-1]->{passive}};
|
606
|
0
|
|
|
|
|
0
|
my $do_ml = 1;
|
607
|
0
|
|
|
|
|
0
|
my $v = begin_line;
|
608
|
0
|
|
|
|
|
0
|
while ( $do_ml) {
|
609
|
0
|
|
|
|
|
0
|
my $l = getline;
|
610
|
0
|
|
|
|
|
0
|
chomp $l;
|
611
|
0
|
|
|
|
|
0
|
$do_ml = $l =~ s/\\\s*$//;
|
612
|
0
|
|
|
|
|
0
|
$l =~ s/defined\s*\(([^\)\s]+)\s*\)\s*/is_defined($1)/ge; # XXX a hack
|
|
0
|
|
|
|
|
0
|
|
613
|
0
|
0
|
|
|
|
0
|
parse_line( $v, $l . ( $do_ml ? "\n" : ''));
|
614
|
|
|
|
|
|
|
}
|
615
|
0
|
|
|
|
|
0
|
my $if = end_line($v);
|
616
|
0
|
0
|
|
|
|
0
|
if ( $context->{ifdef}->[-1]->{do_else}) {
|
617
|
0
|
|
|
|
|
0
|
my $ret = eval $if;
|
618
|
0
|
0
|
|
|
|
0
|
die $@ if $@;
|
619
|
0
|
0
|
|
|
|
0
|
$context->{ifdef}->[-1]->{state} = ($ret ? 1 : 0);
|
620
|
0
|
0
|
|
|
|
0
|
$context->{ifdef}->[-1]->{do_else} = 0 if $ret;
|
621
|
|
|
|
|
|
|
} else {
|
622
|
0
|
|
|
|
|
0
|
$context->{ifdef}->[-1]->{state} = 0;
|
623
|
|
|
|
|
|
|
}
|
624
|
0
|
|
|
|
|
0
|
$eatline = 0;
|
625
|
|
|
|
|
|
|
} elsif ( $what eq 'else') {
|
626
|
6
|
|
|
|
|
18
|
die "Runaway #else\n" if
|
627
|
6
|
|
|
|
|
22
|
0 == $#{$context->{ifdef}} or
|
628
|
6
|
50
|
33
|
|
|
8
|
@{$context->{ifdef}->[-1]->{passive}};
|
629
|
6
|
50
|
|
|
|
16
|
die "Too many #else\n" unless $context->{ifdef}->[-1]->{flipsleft}--;
|
630
|
6
|
100
|
|
|
|
19
|
$context->{ifdef}->[-1]->{state} = $context->{ifdef}->[-1]->{state} ?
|
631
|
|
|
|
|
|
|
0 :
|
632
|
|
|
|
|
|
|
$context->{ifdef}->[-1]->{do_else};
|
633
|
|
|
|
|
|
|
} elsif ( $what eq 'endif') {
|
634
|
7
|
|
|
|
|
52
|
die "Runaway #endif\n" if
|
635
|
7
|
|
|
|
|
29
|
0 == $#{$context->{ifdef}} or
|
636
|
7
|
50
|
33
|
|
|
7
|
@{$context->{ifdef}->[-1]->{passive}};
|
637
|
7
|
|
|
|
|
9
|
pop @{$context->{ifdef}};
|
|
7
|
|
|
|
|
11
|
|
638
|
|
|
|
|
|
|
} elsif ( $what eq 'error') {
|
639
|
0
|
|
|
|
|
0
|
die getline;
|
640
|
|
|
|
|
|
|
} elsif ( $what eq 'include') {
|
641
|
0
|
|
|
|
|
0
|
my $bracket = gettok();
|
642
|
0
|
0
|
|
|
|
0
|
die "format #include or #include \"file\"\n"
|
643
|
|
|
|
|
|
|
unless $bracket =~ /^["<]$/;
|
644
|
0
|
|
|
|
|
0
|
my $file;
|
645
|
|
|
|
|
|
|
my @local_inc;
|
646
|
0
|
0
|
|
|
|
0
|
if ( $bracket eq '<') {
|
647
|
0
|
|
|
|
|
0
|
@local_inc = ( @inc, '.');
|
648
|
0
|
0
|
|
|
|
0
|
die "format #include \n" unless $context->{buf} =~ s/([^>]*)>//;
|
649
|
0
|
|
|
|
|
0
|
$file = $1;
|
650
|
|
|
|
|
|
|
} else {
|
651
|
0
|
|
|
|
|
0
|
@local_inc = ( '.');
|
652
|
0
|
0
|
|
|
|
0
|
die "format #include \"file\"\n" unless $context->{buf} =~ s/([^"]*)"//;
|
653
|
0
|
|
|
|
|
0
|
$file = $1;
|
654
|
|
|
|
|
|
|
}
|
655
|
0
|
|
|
|
|
0
|
my $found;
|
656
|
0
|
|
|
|
|
0
|
for my $inc ( @local_inc) {
|
657
|
0
|
0
|
|
|
|
0
|
next unless -f "$inc/$file";
|
658
|
0
|
|
|
|
|
0
|
$found = "$inc/$file";
|
659
|
0
|
|
|
|
|
0
|
last;
|
660
|
|
|
|
|
|
|
}
|
661
|
0
|
0
|
|
|
|
0
|
die "Cannot find file `$file' in path [@local_inc]\n" unless $found;
|
662
|
0
|
|
|
|
|
0
|
$file = $found;
|
663
|
|
|
|
|
|
|
|
664
|
0
|
|
|
|
|
0
|
local $input;
|
665
|
0
|
0
|
|
|
|
0
|
open $input, "< $file" or die "Cannot open $file\n";
|
666
|
0
|
|
|
|
|
0
|
push @context, $context;
|
667
|
0
|
|
|
|
|
0
|
$context = new_context( file => $file);
|
668
|
0
|
|
|
|
|
0
|
parse_file(1);
|
669
|
0
|
|
|
|
|
0
|
$context = pop @context;
|
670
|
0
|
|
|
|
|
0
|
close $input;
|
671
|
|
|
|
|
|
|
} elsif ( $what eq 'pragma') {
|
672
|
0
|
|
|
|
|
0
|
my $pragma = gettok();
|
673
|
0
|
0
|
|
|
|
0
|
my $param = length($context->{buf}) ? getline() : '';
|
674
|
0
|
|
|
|
|
0
|
$param =~ s/^[\s\(]*(\w+)[\s\)\#]*$/$1/m;
|
675
|
|
|
|
|
|
|
|
676
|
0
|
|
|
|
|
0
|
parse_pragma( $pragma, $param);
|
677
|
|
|
|
|
|
|
} elsif ( $what eq 'perldef') {
|
678
|
5
|
|
|
|
|
5
|
$eatline = 0;
|
679
|
5
|
|
|
|
|
13
|
my $heredoc = $context->{buf} =~ s/^</;
|
680
|
5
|
|
|
|
|
11
|
my $def = getid();
|
681
|
|
|
|
|
|
|
|
682
|
5
|
|
|
|
|
7
|
my ( $ellipsis, @params);
|
683
|
5
|
|
|
|
|
7
|
my $parametric = 0;
|
684
|
5
|
100
|
|
|
|
20
|
if ( $context->{buf} =~ s/^\(([^\)]*)\)//) {
|
685
|
2
|
100
|
|
|
|
7
|
if ( $1 eq '...') {
|
686
|
1
|
|
|
|
|
2
|
$ellipsis = 1;
|
687
|
|
|
|
|
|
|
} else {
|
688
|
2
|
|
|
|
|
6
|
@params = map {
|
689
|
1
|
|
|
|
|
5
|
s/^\s*//;
|
690
|
2
|
|
|
|
|
6
|
s/\s*$//;
|
691
|
2
|
50
|
|
|
|
7
|
die "`$_' is not a valid Perl scalar declaration (must begin with \$)\n"
|
692
|
|
|
|
|
|
|
unless m/^\$\w+$/;
|
693
|
2
|
|
|
|
|
5
|
$_
|
694
|
|
|
|
|
|
|
} split ',', $1;
|
695
|
|
|
|
|
|
|
}
|
696
|
2
|
|
|
|
|
4
|
$parametric = 1;
|
697
|
|
|
|
|
|
|
}
|
698
|
5
|
|
|
|
|
18
|
$context->{buf} =~ s/^\s*//;
|
699
|
5
|
50
|
33
|
|
|
30
|
die "Empty #perldef declaration `$def'\n"
|
700
|
|
|
|
|
|
|
unless $heredoc or length $context->{buf};
|
701
|
|
|
|
|
|
|
|
702
|
5
|
|
|
|
|
9
|
my $perlcode = "sub {\n";
|
703
|
5
|
100
|
100
|
|
|
21
|
$perlcode .= "my (" . join( ', ', @params) . ") = \@_;\n"
|
704
|
|
|
|
|
|
|
if !$ellipsis and @params;
|
705
|
|
|
|
|
|
|
|
706
|
5
|
|
|
|
|
8
|
my $do_ml = 1;
|
707
|
5
|
|
|
|
|
13
|
while ( $do_ml) {
|
708
|
10
|
|
|
|
|
14
|
my $l = getline;
|
709
|
10
|
|
|
|
|
13
|
chomp $l;
|
710
|
10
|
50
|
|
|
|
15
|
if ( $heredoc) {
|
711
|
0
|
0
|
|
|
|
0
|
last if $l eq $def;
|
712
|
|
|
|
|
|
|
} else {
|
713
|
10
|
|
|
|
|
38
|
$do_ml = $l =~ s/\\\s*$//;
|
714
|
|
|
|
|
|
|
}
|
715
|
10
|
100
|
|
|
|
31
|
$perlcode .= $l . ( $do_ml ? "\n" : '');
|
716
|
|
|
|
|
|
|
}
|
717
|
5
|
|
|
|
|
6
|
$perlcode .= "\n}";
|
718
|
5
|
|
|
|
|
540
|
my $p = eval $perlcode;
|
719
|
5
|
50
|
|
|
|
17
|
unless ( defined $p) {
|
720
|
0
|
|
|
|
|
0
|
$@ =~ s/at \(eval \d+\) line (\d+), //gs;
|
721
|
0
|
|
|
|
|
0
|
$@ =~ s/<\$ih>\s+//gs;
|
722
|
0
|
|
|
|
|
0
|
die "$@\n";
|
723
|
|
|
|
|
|
|
}
|
724
|
5
|
100
|
|
|
|
40
|
( $parametric ? $macros{$def} : $defines{$def} ) = {
|
725
|
|
|
|
|
|
|
name => $def,
|
726
|
|
|
|
|
|
|
num => scalar(@params),
|
727
|
|
|
|
|
|
|
storage => [],
|
728
|
|
|
|
|
|
|
ellipsis => $ellipsis,
|
729
|
|
|
|
|
|
|
code => $p,
|
730
|
|
|
|
|
|
|
};
|
731
|
|
|
|
|
|
|
} elsif ( $what =~ /^([\w\d_]+)/) {
|
732
|
0
|
|
|
|
|
0
|
die "Invalid preprocessor directive '$1'\n";
|
733
|
|
|
|
|
|
|
} else {
|
734
|
|
|
|
|
|
|
# a true comment
|
735
|
|
|
|
|
|
|
}
|
736
|
|
|
|
|
|
|
|
737
|
41
|
100
|
|
|
|
139
|
eatline if $eatline;
|
738
|
|
|
|
|
|
|
}
|
739
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
sub parse_file
|
741
|
|
|
|
|
|
|
{
|
742
|
1
|
|
|
1
|
|
3
|
my $do_output = $_[0];
|
743
|
1
|
|
|
|
|
1
|
my $l;
|
744
|
1
|
|
|
|
|
6
|
my $h = begin_line;
|
745
|
1
|
|
|
|
|
5
|
while ( defined ( $l = getline(1))) {
|
746
|
102
|
100
|
66
|
|
|
725
|
if ( !$context->{multiline_comment} and $l =~ s/^#//) {
|
|
|
100
|
66
|
|
|
|
|
747
|
63
|
|
|
|
|
105
|
$context->{buf} = $l;
|
748
|
63
|
|
|
|
|
142
|
parse_comment( $l);
|
749
|
|
|
|
|
|
|
} elsif ( $context->{ifdef}->[-1]->{state} and parse_line( $h, $l)) {
|
750
|
33
|
|
|
|
|
70
|
$l = end_line($h);
|
751
|
33
|
50
|
|
|
|
102
|
print $l if $do_output;
|
752
|
33
|
|
|
|
|
56
|
begin_line($h);
|
753
|
|
|
|
|
|
|
}
|
754
|
|
|
|
|
|
|
}
|
755
|
0
|
|
|
|
|
0
|
end_line($h);
|
756
|
0
|
0
|
|
|
|
0
|
die "Runaway #ifdef\n" if $#{$context->{ifdef}};
|
|
0
|
|
|
|
|
0
|
|
757
|
|
|
|
|
|
|
}
|
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
sub parse_input
|
760
|
|
|
|
|
|
|
{
|
761
|
1
|
|
|
1
|
|
1
|
my $ih;
|
762
|
|
|
|
|
|
|
|
763
|
1
|
50
|
|
|
|
57
|
if ( $input eq '-') {
|
|
|
50
|
|
|
|
|
|
764
|
0
|
|
|
|
|
0
|
$input = \*STDIN;
|
765
|
0
|
|
|
|
|
0
|
$context->{file} = 'stdin';
|
766
|
|
|
|
|
|
|
} elsif ( ! open $ih, "< $input") {
|
767
|
0
|
|
|
|
|
0
|
die "Cannot open $input:$!\n";
|
768
|
|
|
|
|
|
|
} else {
|
769
|
1
|
|
|
|
|
3
|
$context->{file} = $input;
|
770
|
1
|
|
|
|
|
3
|
$input = $ih;
|
771
|
|
|
|
|
|
|
}
|
772
|
|
|
|
|
|
|
|
773
|
1
|
50
|
|
|
|
5
|
if ( defined $output) {
|
774
|
0
|
0
|
|
|
|
0
|
open OUT, "> $output" or die "Cannot open $output:$!\n";
|
775
|
0
|
|
|
|
|
0
|
select OUT;
|
776
|
|
|
|
|
|
|
}
|
777
|
|
|
|
|
|
|
}
|
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
sub parse_argv
|
780
|
|
|
|
|
|
|
{
|
781
|
1
|
|
|
1
|
|
2
|
my $dominus = 1;
|
782
|
1
|
|
|
|
|
7
|
for ( my $i = 0; $i < @ARGV; $i++) {
|
783
|
|
|
|
|
|
|
|
784
|
1
|
50
|
|
|
|
3
|
die "Too many arguments\n" if $input;
|
785
|
|
|
|
|
|
|
|
786
|
1
|
|
|
|
|
3
|
my $d = $ARGV[$i];
|
787
|
1
|
50
|
33
|
|
|
11
|
if ( $dominus and $d =~ s/^-//) {
|
788
|
0
|
0
|
0
|
|
|
0
|
if ( $d =~ /^I(.+)/ or
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
789
|
|
|
|
|
|
|
( $d eq 'I' and
|
790
|
|
|
|
|
|
|
( defined $ARGV[$i+1] or die "Argument required\n") and
|
791
|
|
|
|
|
|
|
$ARGV[++$i] =~ /(.*)/
|
792
|
|
|
|
|
|
|
)) {
|
793
|
0
|
|
|
|
|
0
|
push @inc, $1;
|
794
|
|
|
|
|
|
|
} elsif ( $d =~ /^D(.+)/ or
|
795
|
|
|
|
|
|
|
( $d eq 'D' and
|
796
|
|
|
|
|
|
|
( defined $ARGV[$i+1] or die "Argument required\n") and
|
797
|
|
|
|
|
|
|
$ARGV[++$i] =~ /(.*)/
|
798
|
|
|
|
|
|
|
)) {
|
799
|
0
|
|
|
|
|
0
|
$d = $1;
|
800
|
0
|
0
|
|
|
|
0
|
die "Invalid define $d\n" unless $d =~ m/^([^\=]+)(?:\=(.*))?$/;
|
801
|
0
|
|
|
|
|
0
|
my ( $def, $body) = ( $1, $2);
|
802
|
0
|
|
|
|
|
0
|
my $v = begin_macro( $def );
|
803
|
0
|
0
|
|
|
|
0
|
parse_line( $v, defined($2) ? $2 : '');
|
804
|
0
|
|
|
|
|
0
|
end_macro( $v);
|
805
|
|
|
|
|
|
|
} elsif ( $d =~ /^o(.+)/ or
|
806
|
|
|
|
|
|
|
( $d eq 'o' and
|
807
|
|
|
|
|
|
|
( defined $ARGV[$i+1] or die "Argument required\n") and
|
808
|
|
|
|
|
|
|
$ARGV[++$i] =~ /(.*)/
|
809
|
|
|
|
|
|
|
)) {
|
810
|
0
|
0
|
|
|
|
0
|
die "Output is already defined\n" if defined $output;
|
811
|
0
|
|
|
|
|
0
|
$output = $1;
|
812
|
|
|
|
|
|
|
} elsif ( $d eq '?' or $d eq 'h' or $d eq '-help') {
|
813
|
0
|
|
|
|
|
0
|
print <
|
814
|
|
|
|
|
|
|
sqlpp - simple SQL preprocessor v$VERSION
|
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
sqlpp [options] filename
|
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
options:
|
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
-I path - include path
|
821
|
|
|
|
|
|
|
-D var[=value] - define variable
|
822
|
|
|
|
|
|
|
-o output - output to file ( default to stdout )
|
823
|
|
|
|
|
|
|
-h,--help - display this text
|
824
|
|
|
|
|
|
|
-hh - display man page
|
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
USAGE
|
827
|
0
|
|
|
|
|
0
|
exit;
|
828
|
|
|
|
|
|
|
} elsif ( $d eq 'hh') {
|
829
|
0
|
|
|
|
|
0
|
system 'perldoc', $0;
|
830
|
0
|
|
|
|
|
0
|
exit;
|
831
|
|
|
|
|
|
|
} elsif ( $d eq '-') {
|
832
|
0
|
|
|
|
|
0
|
$dominus = 0;
|
833
|
|
|
|
|
|
|
} elsif ( $d eq '') {
|
834
|
0
|
|
|
|
|
0
|
$input = '-';
|
835
|
|
|
|
|
|
|
} else {
|
836
|
0
|
|
|
|
|
0
|
die "Unknown or invalid argument -$d\n";
|
837
|
|
|
|
|
|
|
}
|
838
|
|
|
|
|
|
|
} else {
|
839
|
1
|
|
|
|
|
5
|
$input = $d;
|
840
|
|
|
|
|
|
|
}
|
841
|
|
|
|
|
|
|
}
|
842
|
|
|
|
|
|
|
|
843
|
1
|
50
|
|
|
|
6
|
die "No input file\n" unless defined $input;
|
844
|
|
|
|
|
|
|
}
|
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
__DATA__
|