| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#define PERL_NO_GET_CONTEXT |
|
2
|
|
|
|
|
|
|
#include "EXTERN.h" |
|
3
|
|
|
|
|
|
|
#include "perl.h" |
|
4
|
|
|
|
|
|
|
#include "XSUB.h" |
|
5
|
|
|
|
|
|
|
#include "ppport.h" |
|
6
|
|
|
|
|
|
|
#include "lex_read_unichar.inc.c" |
|
7
|
|
|
|
|
|
|
#include "wrap_keyword_plugin.inc.c" |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
STATIC SV *hint_key_sv; |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
#define is_syntax_enabled() SvTRUE( cop_hints_fetch_sv( PL_curcop, hint_key_sv, 0, 0 ) ) |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
5
|
|
|
|
|
|
STATIC void croak_missing_terminator( pTHX_ I32 edelim ) { |
|
17
|
|
|
|
|
|
|
#define croak_missing_terminator( a ) croak_missing_terminator( aTHX_ a ) |
|
18
|
|
|
|
|
|
|
char buf[ 3 ]; |
|
19
|
|
|
|
|
|
|
char quote; |
|
20
|
|
|
|
|
|
|
|
|
21
|
5
|
50
|
|
|
|
|
if ( edelim == -1 ) |
|
22
|
0
|
|
|
|
|
|
Perl_croak( aTHX_ "qw not terminated anywhere before EOF" ); |
|
23
|
|
|
|
|
|
|
|
|
24
|
5
|
50
|
|
|
|
|
if ( edelim >= 0x80 ) |
|
25
|
|
|
|
|
|
|
/* Suboptimal output format */ |
|
26
|
0
|
|
|
|
|
|
Perl_croak( aTHX_ "Can't find qw terminator U+%"UVXf" anywhere before EOF", (UV)edelim ); |
|
27
|
|
|
|
|
|
|
|
|
28
|
5
|
50
|
|
|
|
|
if ( isCNTRL( edelim ) ) { |
|
|
|
100
|
|
|
|
|
|
|
29
|
1
|
|
|
|
|
|
buf[ 0 ] = '^'; |
|
30
|
1
|
50
|
|
|
|
|
buf[ 1 ] = (char)toCTRL( edelim ); |
|
31
|
1
|
|
|
|
|
|
buf[ 2 ] = '\0'; |
|
32
|
1
|
|
|
|
|
|
quote = '"'; |
|
33
|
|
|
|
|
|
|
} else { |
|
34
|
4
|
|
|
|
|
|
buf[ 0 ] = (char)edelim; |
|
35
|
4
|
|
|
|
|
|
buf[ 1 ] = '\0'; |
|
36
|
4
|
50
|
|
|
|
|
quote = edelim == '"' ? '\'' : '"'; |
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
|
|
39
|
5
|
|
|
|
|
|
Perl_croak( aTHX_ "Can't find qw terminator %c%s%c anywhere before EOF", quote, buf, quote ); |
|
40
|
|
|
|
|
|
|
} |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
/* sv is assumed to contain a string (and nothing else). */ |
|
44
|
|
|
|
|
|
|
/* sv is assumed to have no magic. */ |
|
45
|
328
|
|
|
|
|
|
STATIC void append_char_to_word( pTHX_ SV *word_sv, UV c ) { |
|
46
|
|
|
|
|
|
|
#define append_char_to_word( a, b ) append_char_to_word( aTHX_ a, b ) |
|
47
|
|
|
|
|
|
|
char buf[ UTF8_MAXBYTES + 1 ]; /* I wonder why the "+ 1". */ |
|
48
|
|
|
|
|
|
|
STRLEN len; |
|
49
|
328
|
50
|
|
|
|
|
if ( SvUTF8( word_sv ) || c > 255 ) { |
|
|
|
100
|
|
|
|
|
|
|
50
|
1
|
|
|
|
|
|
len = (char*)uvchr_to_utf8( (U8*)buf, c ) - buf; |
|
51
|
1
|
|
|
|
|
|
sv_utf8_upgrade_flags_grow( word_sv, 0, len+1 ); |
|
52
|
|
|
|
|
|
|
} else { |
|
53
|
327
|
|
|
|
|
|
len = 1; |
|
54
|
327
|
|
|
|
|
|
buf[ 0 ] = (char)c; |
|
55
|
|
|
|
|
|
|
} |
|
56
|
|
|
|
|
|
|
|
|
57
|
328
|
|
|
|
|
|
sv_catpvn_nomg( word_sv, buf, len ); |
|
58
|
328
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
/* sv is assumed to contain a string (and nothing else). */ |
|
62
|
|
|
|
|
|
|
/* sv is assumed to have no magic. */ |
|
63
|
|
|
|
|
|
|
/* The sv's length is reduced to zero length and the UTF8 flag is turned off. */ |
|
64
|
203
|
|
|
|
|
|
STATIC void append_word_to_list( pTHX_ OP **list_op_ptr, SV *word_sv ) { |
|
65
|
|
|
|
|
|
|
#define append_word_to_list( a, b ) append_word_to_list( aTHX_ a, b ) |
|
66
|
203
|
|
|
|
|
|
STRLEN len = SvCUR( word_sv ); |
|
67
|
203
|
100
|
|
|
|
|
if ( len ) { |
|
68
|
86
|
|
|
|
|
|
SV* sv_copy = newSV( len ); |
|
69
|
86
|
|
|
|
|
|
sv_copypv( sv_copy, word_sv ); |
|
70
|
86
|
|
|
|
|
|
*list_op_ptr = op_append_elem( OP_LIST, *list_op_ptr, newSVOP( OP_CONST, 0, sv_copy ) ); |
|
71
|
|
|
|
|
|
|
|
|
72
|
86
|
|
|
|
|
|
SvCUR_set( word_sv, 0 ); |
|
73
|
86
|
|
|
|
|
|
SvUTF8_off( word_sv ); |
|
74
|
|
|
|
|
|
|
} |
|
75
|
203
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
|
78
|
63
|
|
|
|
|
|
STATIC OP* parse_qw( pTHX ) { |
|
79
|
|
|
|
|
|
|
#define parse_qw() parse_qw( aTHX ) |
|
80
|
|
|
|
|
|
|
I32 sdelim; |
|
81
|
|
|
|
|
|
|
I32 edelim; |
|
82
|
|
|
|
|
|
|
IV depth; |
|
83
|
63
|
|
|
|
|
|
OP *list_op = NULL; |
|
84
|
63
|
|
|
|
|
|
SV *word_sv = newSVpvn( "", 0 ); |
|
85
|
63
|
|
|
|
|
|
int warned_comma = !ckWARN( WARN_QW ); |
|
86
|
|
|
|
|
|
|
|
|
87
|
63
|
|
|
|
|
|
lex_read_space( 0 ); |
|
88
|
|
|
|
|
|
|
|
|
89
|
63
|
|
|
|
|
|
sdelim = lex_read_unichar( 0 ); |
|
90
|
63
|
50
|
|
|
|
|
if ( sdelim == -1 ) |
|
91
|
0
|
|
|
|
|
|
croak_missing_terminator( -1 ); |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
{ // Find corresponding closing delimiter. |
|
94
|
|
|
|
|
|
|
char *p; |
|
95
|
63
|
50
|
|
|
|
|
if ( sdelim && ( p = strchr( "([{< )]}> )]}>", sdelim ) ) ) |
|
|
|
100
|
|
|
|
|
|
|
96
|
56
|
|
|
|
|
|
edelim = *( p + 5 ); |
|
97
|
|
|
|
|
|
|
else |
|
98
|
7
|
|
|
|
|
|
edelim = sdelim; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
63
|
|
|
|
|
|
depth = 1; |
|
102
|
471
|
|
|
|
|
|
for (;;) { |
|
103
|
534
|
|
|
|
|
|
I32 c = lex_peek_unichar( 0 ); |
|
104
|
|
|
|
|
|
|
|
|
105
|
536
|
|
|
|
|
|
REDO: |
|
106
|
536
|
100
|
|
|
|
|
if ( c == -1 ) |
|
107
|
5
|
|
|
|
|
|
croak_missing_terminator( edelim ); |
|
108
|
|
|
|
|
|
|
|
|
109
|
531
|
100
|
|
|
|
|
if ( c == edelim ) { |
|
110
|
63
|
|
|
|
|
|
lex_read_unichar( 0 ); |
|
111
|
63
|
100
|
|
|
|
|
if ( --depth ) { |
|
112
|
5
|
|
|
|
|
|
append_char_to_word( word_sv, c ); |
|
113
|
|
|
|
|
|
|
} else { |
|
114
|
58
|
|
|
|
|
|
append_word_to_list( &list_op, word_sv ); |
|
115
|
58
|
|
|
|
|
|
break; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
} |
|
118
|
468
|
100
|
|
|
|
|
else if ( c == sdelim ) { |
|
119
|
5
|
|
|
|
|
|
lex_read_unichar( 0 ); |
|
120
|
5
|
|
|
|
|
|
++depth; |
|
121
|
5
|
|
|
|
|
|
append_char_to_word( word_sv, c ); |
|
122
|
|
|
|
|
|
|
} |
|
123
|
463
|
100
|
|
|
|
|
else if ( c == '\\' ) { |
|
124
|
7
|
|
|
|
|
|
lex_read_unichar( 0 ); |
|
125
|
7
|
|
|
|
|
|
c = lex_peek_unichar( 0 ); |
|
126
|
7
|
100
|
|
|
|
|
if ( c != sdelim && c != edelim && c != '\\' && c != '#' ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
127
|
2
|
|
|
|
|
|
append_char_to_word( word_sv, '\\' ); |
|
128
|
2
|
|
|
|
|
|
goto REDO; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
5
|
|
|
|
|
|
lex_read_unichar( 0 ); |
|
132
|
5
|
|
|
|
|
|
append_char_to_word( word_sv, c ); |
|
133
|
|
|
|
|
|
|
} |
|
134
|
456
|
50
|
|
|
|
|
else if ( c == '#' || isSPACE( c ) ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
135
|
145
|
|
|
|
|
|
append_word_to_list( &list_op, word_sv ); |
|
136
|
145
|
|
|
|
|
|
lex_read_space( 0 ); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
else { |
|
139
|
311
|
100
|
|
|
|
|
if ( c == ',' && !warned_comma ) { |
|
|
|
100
|
|
|
|
|
|
|
140
|
2
|
|
|
|
|
|
Perl_warner( aTHX_ packWARN( WARN_QW ), "Possible attempt to separate words with commas" ); |
|
141
|
2
|
|
|
|
|
|
++warned_comma; |
|
142
|
|
|
|
|
|
|
} |
|
143
|
|
|
|
|
|
|
|
|
144
|
311
|
|
|
|
|
|
lex_read_unichar( 0 ); |
|
145
|
311
|
|
|
|
|
|
append_char_to_word( word_sv, c ); |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
58
|
|
|
|
|
|
SvREFCNT_dec( word_sv ); |
|
150
|
|
|
|
|
|
|
|
|
151
|
58
|
100
|
|
|
|
|
if ( !list_op ) |
|
152
|
3
|
|
|
|
|
|
list_op = newNULLLIST(); |
|
153
|
|
|
|
|
|
|
|
|
154
|
58
|
|
|
|
|
|
list_op->op_flags |= OPf_PARENS; |
|
155
|
58
|
|
|
|
|
|
return list_op; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
STATIC Perl_keyword_plugin_t next_keyword_plugin = NULL; |
|
160
|
|
|
|
|
|
|
#define next_keyword_plugin( a, b, c ) next_keyword_plugin( aTHX_ a, b, c ) |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
|
|
163
|
37724
|
|
|
|
|
|
STATIC int my_keyword_plugin( pTHX_ char *keyword_ptr, STRLEN keyword_len, OP **op_ptr ) { |
|
164
|
37724
|
100
|
|
|
|
|
if ( is_syntax_enabled() ) { |
|
165
|
258
|
100
|
|
|
|
|
if ( memEQs( keyword_ptr, keyword_len, "qw" ) ) { |
|
|
|
100
|
|
|
|
|
|
|
166
|
63
|
|
|
|
|
|
*op_ptr = parse_qw(); |
|
167
|
58
|
|
|
|
|
|
return KEYWORD_PLUGIN_EXPR; |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
37661
|
|
|
|
|
|
return next_keyword_plugin( keyword_ptr, keyword_len, op_ptr ); |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
/* ======================================== */ |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
MODULE = Syntax::Feature::QwComments PACKAGE = Syntax::Feature::QwComments |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
void |
|
181
|
|
|
|
|
|
|
hint_key() |
|
182
|
|
|
|
|
|
|
PPCODE: |
|
183
|
28
|
|
|
|
|
|
SvREFCNT_inc( hint_key_sv ); |
|
184
|
28
|
50
|
|
|
|
|
XPUSHs( hint_key_sv ); |
|
185
|
28
|
|
|
|
|
|
XSRETURN( 1 ); |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
BOOT: |
|
189
|
|
|
|
|
|
|
{ |
|
190
|
7
|
|
|
|
|
|
wrap_keyword_plugin( my_keyword_plugin, &next_keyword_plugin ); |
|
191
|
|
|
|
|
|
|
|
|
192
|
7
|
|
|
|
|
|
hint_key_sv = newSVpvs( "Syntax::Feature::QwComments::qw" ); |
|
193
|
7
|
|
|
|
|
|
SvREADONLY_on( hint_key_sv ); |
|
194
|
|
|
|
|
|
|
} |