line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* vi: set ft=c : */ |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
/* Perls before 5.18 lack isIDCONT_uni, but baring minor differences of weird |
4
|
|
|
|
|
|
|
* Unicode characters, isALNUM_uni is close enough |
5
|
|
|
|
|
|
|
*/ |
6
|
|
|
|
|
|
|
#ifndef isIDCONT_uni |
7
|
|
|
|
|
|
|
#define isIDCONT_uni(c) isALNUM_uni(c) |
8
|
|
|
|
|
|
|
#endif |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#define sv_cat_c(sv, c) MY_sv_cat_c(aTHX_ sv, c) |
11
|
18
|
|
|
|
|
|
static void MY_sv_cat_c(pTHX_ SV *sv, U32 c) |
12
|
|
|
|
|
|
|
{ |
13
|
|
|
|
|
|
|
char ds[UTF8_MAXBYTES + 1], *d; |
14
|
18
|
|
|
|
|
|
d = (char *)uvchr_to_utf8((U8 *)ds, c); |
15
|
18
|
50
|
|
|
|
|
if (d - ds > 1) { |
16
|
0
|
|
|
|
|
|
sv_utf8_upgrade(sv); |
17
|
|
|
|
|
|
|
} |
18
|
18
|
|
|
|
|
|
sv_catpvn(sv, ds, d - ds); |
19
|
18
|
|
|
|
|
|
} |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
#define lex_consume(s) MY_lex_consume(aTHX_ s) |
22
|
|
|
|
|
|
|
static int MY_lex_consume(pTHX_ char *s) |
23
|
|
|
|
|
|
|
{ |
24
|
|
|
|
|
|
|
/* I want strprefix() */ |
25
|
|
|
|
|
|
|
size_t i; |
26
|
|
|
|
|
|
|
for(i = 0; s[i]; i++) { |
27
|
|
|
|
|
|
|
if(s[i] != PL_parser->bufptr[i]) |
28
|
|
|
|
|
|
|
return 0; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
lex_read_to(PL_parser->bufptr + i); |
32
|
|
|
|
|
|
|
return i; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
enum { |
36
|
|
|
|
|
|
|
LEX_IDENT_PACKAGENAME = (1<<0), |
37
|
|
|
|
|
|
|
}; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
#define lex_scan_ident( ) MY_lex_scan_ident(aTHX_ 0) |
40
|
|
|
|
|
|
|
#define lex_scan_packagename() MY_lex_scan_ident(aTHX_ LEX_IDENT_PACKAGENAME) |
41
|
34
|
|
|
|
|
|
static SV *MY_lex_scan_ident(pTHX_ int flags) |
42
|
|
|
|
|
|
|
{ |
43
|
|
|
|
|
|
|
I32 c; |
44
|
|
|
|
|
|
|
bool at_start = TRUE; |
45
|
|
|
|
|
|
|
|
46
|
34
|
|
|
|
|
|
char *ident = PL_parser->bufptr; |
47
|
|
|
|
|
|
|
|
48
|
127
|
50
|
|
|
|
|
while((c = lex_peek_unichar(0))) { |
49
|
127
|
100
|
|
|
|
|
if(at_start ? isIDFIRST_uni(c) : isALNUM_uni(c)) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
50
|
|
|
|
|
|
|
at_start = FALSE; |
51
|
|
|
|
|
|
|
/* TODO: This sucks in the case of a false Foo:Bar match */ |
52
|
36
|
100
|
|
|
|
|
else if((flags & LEX_IDENT_PACKAGENAME) && (c == ':')) { |
|
|
100
|
|
|
|
|
|
53
|
2
|
|
|
|
|
|
lex_read_unichar(0); |
54
|
2
|
50
|
|
|
|
|
if(lex_read_unichar(0) != ':') |
55
|
0
|
|
|
|
|
|
croak("Expected colon to be followed by another in package name"); |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
else |
58
|
|
|
|
|
|
|
break; |
59
|
|
|
|
|
|
|
|
60
|
93
|
|
|
|
|
|
lex_read_unichar(0); |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
34
|
|
|
|
|
|
STRLEN len = PL_parser->bufptr - ident; |
64
|
34
|
100
|
|
|
|
|
if(!len) |
65
|
|
|
|
|
|
|
return NULL; |
66
|
|
|
|
|
|
|
|
67
|
25
|
|
|
|
|
|
SV *ret = newSVpvn(ident, len); |
68
|
25
|
50
|
|
|
|
|
if(lex_bufutf8()) |
69
|
0
|
|
|
|
|
|
SvUTF8_on(ret); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
return ret; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
#define lex_scan_attrval_into(name, val) MY_lex_scan_attrval_into(aTHX_ name, val) |
75
|
10
|
|
|
|
|
|
static bool MY_lex_scan_attrval_into(pTHX_ SV *name, SV *val) |
76
|
|
|
|
|
|
|
{ |
77
|
|
|
|
|
|
|
/* TODO: really want lex_scan_ident_into() */ |
78
|
10
|
|
|
|
|
|
SV *n = lex_scan_ident(); |
79
|
10
|
100
|
|
|
|
|
if(!n) |
80
|
|
|
|
|
|
|
return FALSE; |
81
|
|
|
|
|
|
|
|
82
|
7
|
|
|
|
|
|
sv_setsv(name, n); |
83
|
|
|
|
|
|
|
SvREFCNT_dec(n); |
84
|
|
|
|
|
|
|
|
85
|
7
|
50
|
|
|
|
|
if(name != val) |
86
|
7
|
|
|
|
|
|
SvPOK_off(val); |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
/* Do not read space here as space is not allowed between NAME(ARGS) */ |
89
|
|
|
|
|
|
|
|
90
|
7
|
100
|
|
|
|
|
if(lex_peek_unichar(0) != '(') |
91
|
|
|
|
|
|
|
return TRUE; |
92
|
|
|
|
|
|
|
|
93
|
2
|
|
|
|
|
|
lex_read_unichar(0); |
94
|
2
|
50
|
|
|
|
|
if(name == val) |
95
|
0
|
|
|
|
|
|
sv_cat_c(val, '('); |
96
|
|
|
|
|
|
|
else |
97
|
2
|
|
|
|
|
|
sv_setpvs(val, ""); |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
int count = 1; |
100
|
2
|
|
|
|
|
|
I32 c = lex_peek_unichar(0); |
101
|
6
|
100
|
|
|
|
|
while(count && c != -1) { |
102
|
4
|
50
|
|
|
|
|
if(c == '(') |
103
|
0
|
|
|
|
|
|
count++; |
104
|
4
|
100
|
|
|
|
|
if(c == ')') |
105
|
2
|
|
|
|
|
|
count--; |
106
|
4
|
50
|
|
|
|
|
if(c == '\\') { |
107
|
|
|
|
|
|
|
/* The next char does not bump count even if it is ( or ); |
108
|
|
|
|
|
|
|
* the \\ is still captured |
109
|
|
|
|
|
|
|
*/ |
110
|
0
|
|
|
|
|
|
sv_cat_c(val, lex_read_unichar(0)); |
111
|
0
|
|
|
|
|
|
c = lex_peek_unichar(0); |
112
|
0
|
0
|
|
|
|
|
if(c == -1) |
113
|
|
|
|
|
|
|
goto unterminated; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
/* Don't append final closing ')' on split name/val */ |
117
|
4
|
100
|
|
|
|
|
if(count || (name == val)) |
118
|
2
|
|
|
|
|
|
sv_cat_c(val, c); |
119
|
4
|
|
|
|
|
|
lex_read_unichar(0); |
120
|
|
|
|
|
|
|
|
121
|
4
|
|
|
|
|
|
c = lex_peek_unichar(0); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
2
|
50
|
|
|
|
|
if(c == -1) |
125
|
|
|
|
|
|
|
return FALSE; |
126
|
|
|
|
|
|
|
|
127
|
2
|
|
|
|
|
|
return TRUE; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
unterminated: |
130
|
0
|
|
|
|
|
|
croak("Unterminated attribute parameter in attribute list"); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
#define lex_scan_attr() MY_lex_scan_attr(aTHX) |
134
|
|
|
|
|
|
|
static SV *MY_lex_scan_attr(pTHX) |
135
|
|
|
|
|
|
|
{ |
136
|
|
|
|
|
|
|
SV *ret = newSV(0); |
137
|
|
|
|
|
|
|
if(MY_lex_scan_attrval_into(aTHX_ ret, ret)) |
138
|
|
|
|
|
|
|
return ret; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
SvREFCNT_dec(ret); |
141
|
|
|
|
|
|
|
return NULL; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
#define lex_scan_attrs(compcv) MY_lex_scan_attrs(aTHX_ compcv) |
145
|
|
|
|
|
|
|
static OP *MY_lex_scan_attrs(pTHX_ CV *compcv) |
146
|
|
|
|
|
|
|
{ |
147
|
|
|
|
|
|
|
/* Attributes are supplied to newATTRSUB() as an OP_LIST containing |
148
|
|
|
|
|
|
|
* OP_CONSTs, one attribute in each as a plain SV. Note that we don't have |
149
|
|
|
|
|
|
|
* to parse inside the contents of the parens; that is handled by the |
150
|
|
|
|
|
|
|
* attribute handlers themselves |
151
|
|
|
|
|
|
|
*/ |
152
|
|
|
|
|
|
|
OP *attrs = NULL; |
153
|
|
|
|
|
|
|
SV *attr; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
lex_read_space(0); |
156
|
|
|
|
|
|
|
while((attr = lex_scan_attr())) { |
157
|
|
|
|
|
|
|
lex_read_space(0); |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
if(compcv && strEQ(SvPV_nolen(attr), "lvalue")) { |
160
|
|
|
|
|
|
|
CvLVALUE_on(compcv); |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
if(!attrs) |
164
|
|
|
|
|
|
|
attrs = newLISTOP(OP_LIST, 0, NULL, NULL); |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
attrs = op_append_elem(OP_LIST, attrs, newSVOP(OP_CONST, 0, attr)); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
/* Accept additional colons to prefix additional attrs */ |
169
|
|
|
|
|
|
|
if(lex_peek_unichar(0) == ':') { |
170
|
|
|
|
|
|
|
lex_read_unichar(0); |
171
|
|
|
|
|
|
|
lex_read_space(0); |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
return attrs; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
#define lex_scan_lexvar() MY_lex_scan_lexvar(aTHX) |
179
|
5
|
|
|
|
|
|
static SV *MY_lex_scan_lexvar(pTHX) |
180
|
|
|
|
|
|
|
{ |
181
|
5
|
50
|
|
|
|
|
int sigil = lex_peek_unichar(0); |
|
|
50
|
|
|
|
|
|
182
|
|
|
|
|
|
|
switch(sigil) { |
183
|
|
|
|
|
|
|
case '$': |
184
|
|
|
|
|
|
|
case '@': |
185
|
|
|
|
|
|
|
case '%': |
186
|
5
|
|
|
|
|
|
lex_read_unichar(0); |
187
|
|
|
|
|
|
|
break; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
default: |
190
|
0
|
|
|
|
|
|
croak("Expected a lexical variable"); |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
5
|
|
|
|
|
|
SV *ret = lex_scan_ident(); |
194
|
5
|
50
|
|
|
|
|
if(!ret) |
195
|
|
|
|
|
|
|
return NULL; |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
/* prepend sigil - which we know to be a single byte */ |
198
|
5
|
50
|
|
|
|
|
SvGROW(ret, SvCUR(ret) + 1); |
|
|
50
|
|
|
|
|
|
199
|
5
|
|
|
|
|
|
Move(SvPVX(ret), SvPVX(ret) + 1, SvCUR(ret), char); |
200
|
5
|
|
|
|
|
|
SvPVX(ret)[0] = sigil; |
201
|
5
|
|
|
|
|
|
SvCUR(ret)++; |
202
|
|
|
|
|
|
|
|
203
|
5
|
|
|
|
|
|
SvPVX(ret)[SvCUR(ret)] = 0; |
204
|
|
|
|
|
|
|
|
205
|
5
|
|
|
|
|
|
return ret; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
#define lex_scan_parenthesized() MY_lex_scan_parenthesized(aTHX) |
209
|
|
|
|
|
|
|
static SV *MY_lex_scan_parenthesized(pTHX) |
210
|
|
|
|
|
|
|
{ |
211
|
|
|
|
|
|
|
I32 c; |
212
|
|
|
|
|
|
|
int parencount = 0; |
213
|
|
|
|
|
|
|
SV *ret = newSVpvs(""); |
214
|
|
|
|
|
|
|
if(lex_bufutf8()) |
215
|
|
|
|
|
|
|
SvUTF8_on(ret); |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
c = lex_peek_unichar(0); |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
while(c != -1) { |
220
|
|
|
|
|
|
|
sv_cat_c(ret, lex_read_unichar(0)); |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
switch(c) { |
223
|
|
|
|
|
|
|
case '(': parencount++; break; |
224
|
|
|
|
|
|
|
case ')': parencount--; break; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
if(!parencount) |
227
|
|
|
|
|
|
|
break; |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
c = lex_peek_unichar(0); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
if(SvCUR(ret)) |
233
|
|
|
|
|
|
|
return ret; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
SvREFCNT_dec(ret); |
236
|
|
|
|
|
|
|
return NULL; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
#define lex_scan_version(flags) MY_lex_scan_version(aTHX_ flags) |
240
|
5
|
|
|
|
|
|
static SV *MY_lex_scan_version(pTHX_ int flags) |
241
|
|
|
|
|
|
|
{ |
242
|
|
|
|
|
|
|
I32 c; |
243
|
5
|
|
|
|
|
|
SV *tmpsv = sv_2mortal(newSVpvs("")); |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
/* scan_version() expects a version to end in linefeed, semicolon or |
246
|
|
|
|
|
|
|
* openbrace; gets confused if other keywords are fine. We'll have to |
247
|
|
|
|
|
|
|
* extract it first. |
248
|
|
|
|
|
|
|
* https://rt.cpan.org/Ticket/Display.html?id=132903 |
249
|
|
|
|
|
|
|
*/ |
250
|
|
|
|
|
|
|
|
251
|
21
|
50
|
|
|
|
|
while((c = lex_peek_unichar(0))) { |
252
|
|
|
|
|
|
|
/* Allow a single leading v before accepting only digits, dot, underscore */ |
253
|
21
|
100
|
|
|
|
|
if((!SvCUR(tmpsv) && (c == 'v')) || strchr("0123456789._", c)) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
254
|
16
|
|
|
|
|
|
sv_cat_c(tmpsv, lex_read_unichar(0)); |
255
|
|
|
|
|
|
|
else |
256
|
|
|
|
|
|
|
break; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
5
|
100
|
|
|
|
|
if(!SvCUR(tmpsv) && (flags & PARSE_OPTIONAL)) |
|
|
50
|
|
|
|
|
|
260
|
|
|
|
|
|
|
return NULL; |
261
|
|
|
|
|
|
|
|
262
|
3
|
|
|
|
|
|
SV *ret = newSV(0); |
263
|
3
|
|
|
|
|
|
scan_version(SvPVX(tmpsv), ret, FALSE); |
264
|
|
|
|
|
|
|
|
265
|
3
|
|
|
|
|
|
return ret; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
#define parse_lexvar() MY_parse_lexvar(aTHX) |
269
|
|
|
|
|
|
|
static PADOFFSET MY_parse_lexvar(pTHX) |
270
|
|
|
|
|
|
|
{ |
271
|
|
|
|
|
|
|
/* TODO: Rewrite this in terms of using lex_scan_lexvar() |
272
|
|
|
|
|
|
|
*/ |
273
|
|
|
|
|
|
|
char *lexname = PL_parser->bufptr; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
if(lex_read_unichar(0) != '$') |
276
|
|
|
|
|
|
|
croak("Expected a lexical scalar at %s", lexname); |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
if(!isIDFIRST_uni(lex_peek_unichar(0))) |
279
|
|
|
|
|
|
|
croak("Expected a lexical scalar at %s", lexname); |
280
|
|
|
|
|
|
|
lex_read_unichar(0); |
281
|
|
|
|
|
|
|
while(isIDCONT_uni(lex_peek_unichar(0))) |
282
|
|
|
|
|
|
|
lex_read_unichar(0); |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
/* Forbid $_ */ |
285
|
|
|
|
|
|
|
if(PL_parser->bufptr - lexname == 2 && lexname[1] == '_') |
286
|
|
|
|
|
|
|
croak("Can't use global $_ in \"my\""); |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
return pad_add_name_pvn(lexname, PL_parser->bufptr - lexname, 0, NULL, NULL); |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
#define parse_scoped_block(flags) MY_parse_scoped_block(aTHX_ flags) |
292
|
|
|
|
|
|
|
static OP *MY_parse_scoped_block(pTHX_ int flags) |
293
|
|
|
|
|
|
|
{ |
294
|
|
|
|
|
|
|
OP *ret; |
295
|
|
|
|
|
|
|
I32 save_ix = block_start(TRUE); |
296
|
|
|
|
|
|
|
ret = parse_block(flags); |
297
|
|
|
|
|
|
|
return block_end(save_ix, ret); |
298
|
|
|
|
|
|
|
} |