line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*- mode: perl; coding: utf-8 -*- |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package YATT::Registry; |
4
|
5
|
|
|
5
|
|
2801
|
use strict; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
148
|
|
5
|
5
|
|
|
5
|
|
17
|
use warnings FATAL => qw(all); |
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
160
|
|
6
|
5
|
|
|
5
|
|
17
|
use Carp; |
|
5
|
|
|
|
|
5
|
|
|
5
|
|
|
|
|
169
|
|
7
|
5
|
|
|
5
|
|
1392
|
use UNIVERSAL; |
|
5
|
|
|
|
|
35
|
|
|
5
|
|
|
|
|
47
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# Debugging aid. |
10
|
|
|
|
|
|
|
require YATT; |
11
|
5
|
|
|
5
|
|
1114
|
use YATT::Exception; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
234
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
{ |
14
|
5
|
|
|
5
|
|
19
|
package YATT::Registry::NS; use YATT::Inc; |
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
27
|
|
15
|
4
|
|
|
4
|
|
13
|
BEGIN {require Exporter; *import = \&Exporter::import} |
|
4
|
|
|
|
|
52
|
|
16
|
4
|
|
|
4
|
|
9
|
use base qw(YATT::Class::Configurable); |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
272
|
|
17
|
4
|
|
|
|
|
22
|
use YATT::Fields qw(Widget |
18
|
|
|
|
|
|
|
cf_nsid cf_parent_nsid cf_base_nsid |
19
|
|
|
|
|
|
|
cf_pkg cf_special_entities |
20
|
|
|
|
|
|
|
cf_name cf_vpath cf_loadkey |
21
|
|
|
|
|
|
|
cf_mtime cf_age |
22
|
|
|
|
|
|
|
^is_loaded |
23
|
4
|
|
|
4
|
|
13
|
); |
|
4
|
|
|
|
|
5
|
|
24
|
|
|
|
|
|
|
# When fields is empty, %FIELDS doesn't blessed. |
25
|
|
|
|
|
|
|
# This causes "Pseudo-hashes are deprecated" |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
use YATT::Types |
28
|
4
|
|
|
|
|
45
|
([Dir => [qw(cf_base_template)] |
29
|
|
|
|
|
|
|
, 'Dir' |
30
|
|
|
|
|
|
|
, [Template => [qw(tree cf_base_template ^widget_list |
31
|
|
|
|
|
|
|
^cf_metainfo)]] |
32
|
|
|
|
|
|
|
] |
33
|
|
|
|
|
|
|
, -base => [NS => __PACKAGE__] |
34
|
|
|
|
|
|
|
, -alias => [Root => 'YATT::Registry' |
35
|
|
|
|
|
|
|
, Registry => 'YATT::Registry'] |
36
|
|
|
|
|
|
|
, -default => [loader => 'YATT::Registry::Loader'] |
37
|
|
|
|
|
|
|
, -debug => $ENV{YATT_DEBUG_TYPES} |
38
|
|
|
|
|
|
|
, qw(:type_name :export_alias) |
39
|
4
|
|
|
4
|
|
289
|
); |
|
4
|
|
|
|
|
4
|
|
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
4
|
|
|
4
|
|
16
|
use YATT::Util qw(checked_eval checked lsearch); |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
160
|
|
43
|
4
|
|
|
4
|
|
13
|
use YATT::Util::Taint; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
306
|
|
44
|
4
|
|
|
4
|
|
12
|
use YATT::Registry::NS; |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
174
|
|
45
|
4
|
|
|
4
|
|
13
|
use YATT::Util::Symbol; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
257
|
|
46
|
|
|
|
|
|
|
|
47
|
4
|
|
|
4
|
|
14
|
use base Dir; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
470
|
|
48
|
4
|
|
|
|
|
17
|
use YATT::Fields qw(^Loader NS last_nsid |
49
|
|
|
|
|
|
|
cf_auto_reload |
50
|
|
|
|
|
|
|
cf_type_map |
51
|
|
|
|
|
|
|
cf_debug_registry |
52
|
|
|
|
|
|
|
cf_rc_global |
53
|
|
|
|
|
|
|
cf_template_global |
54
|
|
|
|
|
|
|
cf_no_lineinfo |
55
|
|
|
|
|
|
|
current_parser |
56
|
|
|
|
|
|
|
cf_default_base_class |
57
|
|
|
|
|
|
|
cf_use |
58
|
|
|
|
|
|
|
loading |
59
|
|
|
|
|
|
|
nspattern |
60
|
|
|
|
|
|
|
) |
61
|
|
|
|
|
|
|
, ['^cf_namespace' => qw(yatt perl)] |
62
|
|
|
|
|
|
|
, ['^cf_app_prefix' => "::"] |
63
|
4
|
|
|
4
|
|
16
|
; |
|
4
|
|
|
|
|
5
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub new { |
66
|
20
|
|
|
20
|
0
|
99
|
my $nsid = 0; |
67
|
20
|
|
|
|
|
113
|
my Root $root = shift->SUPER::new(@_, vpath => '/', nsid => $nsid); |
68
|
|
|
|
|
|
|
|
69
|
20
|
50
|
|
|
|
68
|
if (defined $ENV{YATT_CF_LINEINFO}) { |
70
|
0
|
|
|
|
|
0
|
$root->{cf_no_lineinfo} = not $ENV{YATT_CF_LINEINFO}; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# $root->{NS}{$nsid} = $root; # ← サイクルするってば。 |
74
|
|
|
|
|
|
|
# 一回、空呼び出し。 |
75
|
20
|
|
|
|
|
41
|
$root->get_package($root); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# root は new 時に強制 refresh. |
78
|
|
|
|
|
|
|
# after_configure だと、configure の度なので、new のみに。 |
79
|
20
|
|
|
|
|
68
|
$root->refresh($root); |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# Now safe to lift @ISA. |
82
|
20
|
|
|
|
|
40
|
$root->{is_loaded} = 1; |
83
|
|
|
|
|
|
|
|
84
|
20
|
|
|
|
|
91
|
$root; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub configure_loader { |
88
|
20
|
|
|
20
|
0
|
35
|
(my Root $root, my ($desc)) = @_; |
89
|
20
|
|
|
|
|
45
|
my ($type, $loadkey, @args) = @$desc; |
90
|
20
|
|
|
|
|
611
|
$root->{Loader} = $root->default_loader->$type->new($loadkey, @args); |
91
|
20
|
|
|
|
|
70
|
$root->{cf_loadkey} = $loadkey; |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub configure_DIR { |
95
|
0
|
|
|
0
|
0
|
0
|
(my Root $root, my ($dir)) = @_; |
96
|
0
|
|
|
|
|
0
|
$root->{Loader} = $root->default_loader->DIR->new($dir); |
97
|
0
|
|
|
|
|
0
|
$root->{cf_loadkey} = $dir; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub after_configure { |
101
|
20
|
|
|
20
|
0
|
27
|
(my Root $root) = @_; |
102
|
20
|
|
|
|
|
33
|
my $nspat = join("|" , @{$root->namespace}); |
|
20
|
|
|
|
|
70
|
|
103
|
20
|
|
|
|
|
198
|
$root->{nspattern} = qr{^(?:$nspat)$}; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
#======================================== |
107
|
|
|
|
|
|
|
# use YATT::Registry ** => ** 系. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
{ |
110
|
|
|
|
|
|
|
our Root $ROOT; |
111
|
|
|
|
|
|
|
our NS $CURRENT; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub eval_in_dir { |
114
|
|
|
|
|
|
|
# XXX: should take care for variable capture. |
115
|
17
|
|
|
17
|
0
|
39
|
(my Root $root, my NS $target, my ($script, @args)) = @_; |
116
|
17
|
50
|
|
|
|
59
|
if (is_tainted($script)) { |
117
|
0
|
|
|
|
|
0
|
confess "script is tainted: $script\n"; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
17
|
|
|
|
|
34
|
my $targetClass = $root->get_package($target); |
121
|
|
|
|
|
|
|
|
122
|
17
|
|
|
|
|
72
|
my $prog = "package $targetClass;" |
123
|
|
|
|
|
|
|
. " use strict;" |
124
|
|
|
|
|
|
|
. " use warnings FATAL => qw(all);" |
125
|
|
|
|
|
|
|
. " $script"; |
126
|
17
|
|
|
|
|
37
|
local @_ = (@args); |
127
|
17
|
|
|
|
|
37
|
local ($ROOT, $CURRENT) = ($root, $target); |
128
|
17
|
|
|
|
|
37
|
&YATT::break_eval; |
129
|
17
|
|
|
|
|
17
|
my @result; |
130
|
17
|
50
|
|
|
|
40
|
if (wantarray) { |
131
|
0
|
|
|
|
|
0
|
@result = eval $prog; |
132
|
|
|
|
|
|
|
} else { |
133
|
17
|
|
|
2
|
|
1106
|
$result[0] = eval $prog; |
|
2
|
|
|
2
|
|
11
|
|
|
2
|
|
|
2
|
|
3
|
|
|
2
|
|
|
2
|
|
71
|
|
|
2
|
|
|
2
|
|
10
|
|
|
2
|
|
|
2
|
|
3
|
|
|
2
|
|
|
2
|
|
420
|
|
|
2
|
|
|
2
|
|
9
|
|
|
2
|
|
|
2
|
|
2
|
|
|
2
|
|
|
2
|
|
34
|
|
|
2
|
|
|
2
|
|
10
|
|
|
2
|
|
|
2
|
|
3
|
|
|
2
|
|
|
2
|
|
365
|
|
|
2
|
|
|
2
|
|
10
|
|
|
2
|
|
|
2
|
|
2
|
|
|
2
|
|
|
2
|
|
63
|
|
|
2
|
|
|
2
|
|
6
|
|
|
2
|
|
|
2
|
|
2
|
|
|
2
|
|
|
2
|
|
387
|
|
|
2
|
|
|
2
|
|
8
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
35
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
1
|
|
|
2
|
|
|
|
|
702
|
|
|
2
|
|
|
|
|
12
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
73
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
484
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
55
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
773
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
70
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
59
|
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
68
|
|
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
72
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
57
|
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
68
|
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
68
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
51
|
|
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
# XXX: $prog をどう見せたいかが、状況で色々変化する。 |
136
|
17
|
50
|
|
|
|
54
|
die $@ if $@; |
137
|
17
|
50
|
|
|
|
79
|
wantarray ? @result : $result[0]; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub import { |
141
|
16
|
|
|
16
|
|
35
|
my $modpack = shift; |
142
|
16
|
|
|
|
|
42
|
my $callpack = caller; |
143
|
16
|
|
|
|
|
56
|
$modpack->install_builtins($callpack); |
144
|
|
|
|
|
|
|
|
145
|
16
|
100
|
|
|
|
48
|
return unless @_; |
146
|
|
|
|
|
|
|
|
147
|
16
|
50
|
|
|
|
56
|
croak "Odd number of arguments for 'use $modpack @_'" if @_ % 2; |
148
|
|
|
|
|
|
|
|
149
|
17
|
|
|
|
|
67
|
my $fields = $CURRENT->fields_hash; |
150
|
17
|
|
|
|
|
70
|
while (my ($name, $value) = splice @_, 0, 2) { |
151
|
17
|
100
|
|
|
|
109
|
if (my $sub = $modpack->can("import_$name")) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
152
|
16
|
|
|
|
|
50
|
$sub->($modpack, $callpack, $value); |
153
|
|
|
|
|
|
|
} elsif ($sub = $CURRENT->can("configure_$name")) { |
154
|
4
|
|
|
|
|
29
|
$sub->($CURRENT, $value); |
155
|
|
|
|
|
|
|
} elsif ($fields->{"cf_$name"}) { |
156
|
5
|
|
|
|
|
199
|
$CURRENT->{"cf_$name"} = $value; |
157
|
|
|
|
|
|
|
} else { |
158
|
1
|
|
|
|
|
2
|
croak "Unknown YATT::Registry parameter: $name"; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# Root 以外の Dir では、こちらが呼ばれる(はず) |
164
|
|
|
|
|
|
|
sub import_base { |
165
|
13
|
50
|
|
15
|
0
|
48
|
croak "Can't find current registry" unless defined $ROOT; |
166
|
15
|
|
|
|
|
27
|
my ($modpack, $targetClass, $vpath) = @_; |
167
|
15
|
50
|
|
|
|
65
|
my Dir $dir = $CURRENT->lookup_dir($ROOT, split '/', $vpath) |
168
|
|
|
|
|
|
|
or croak "Can't find directory: $vpath"; |
169
|
15
|
|
|
|
|
46
|
$CURRENT->{cf_base_nsid} = $dir->{cf_nsid}; |
170
|
15
|
|
|
|
|
42
|
lift_isa_to($ROOT->get_package($dir), $targetClass); |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# これが呼ばれるのは Root の時だけ。 |
175
|
|
|
|
|
|
|
sub configure_base { |
176
|
3
|
|
|
1
|
0
|
103
|
(my MY $root, my $realdir) = @_; |
177
|
3
|
0
|
|
|
|
7
|
unless (-d $realdir) { |
178
|
8
|
|
|
|
|
22
|
croak "No such directory for base='$realdir'"; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
1
|
|
|
|
|
2
|
my $base_nsid = $root->createNS |
182
|
|
|
|
|
|
|
(Dir => loadkey => untaint_any($realdir)); |
183
|
|
|
|
|
|
|
|
184
|
1
|
|
|
|
|
5
|
$root->{cf_base_nsid} = $base_nsid; |
185
|
1
|
|
|
|
|
2
|
lift_isa_to($root->get_package(my $base = $root->nsobj($base_nsid)) |
186
|
|
|
|
|
|
|
, $root->get_package($root)); |
187
|
|
|
|
|
|
|
|
188
|
1
|
|
|
|
|
1
|
$root->refresh($base); |
189
|
|
|
|
|
|
|
|
190
|
1
|
|
|
|
|
6
|
$root; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
#---------------------------------------- |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
{ |
196
|
|
|
|
|
|
|
our $IS_RELOADING; |
197
|
7
|
|
|
4
|
0
|
18
|
sub is_reloading { $IS_RELOADING } |
198
|
|
|
|
|
|
|
sub with_reloading_flag { |
199
|
18
|
|
|
17
|
0
|
37
|
(my Root $root, my ($flag, $sub)) = @_; |
200
|
17
|
|
|
|
|
31
|
local $IS_RELOADING = $flag; |
201
|
17
|
|
|
|
|
32
|
$sub->(); |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
#---------------------------------------- |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub Entity (*$) { |
208
|
3
|
|
|
3
|
0
|
5
|
my ($name, $sub) = @_; |
209
|
3
|
|
|
|
|
6
|
my ($instClass) = caller; |
210
|
3
|
|
|
|
|
11
|
my $glob = globref($instClass, "entity_$name"); |
211
|
3
|
50
|
33
|
|
|
11
|
if (MY->is_reloading and defined *{$glob}{CODE}) { |
|
0
|
|
|
|
|
0
|
|
212
|
|
|
|
|
|
|
# To avoid 'Subroutine MyApp5::entity_bar redefined'. |
213
|
0
|
|
|
|
|
0
|
undef *$glob; |
214
|
|
|
|
|
|
|
} |
215
|
3
|
|
|
|
|
33
|
*$glob = $sub; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub ElementMacro (*$) { |
219
|
0
|
|
|
0
|
0
|
0
|
my ($name, $sub) = @_; |
220
|
0
|
|
|
|
|
0
|
my ($instClass) = caller; |
221
|
0
|
|
|
|
|
0
|
*{globref($instClass, "macro_$name")} = $sub; |
|
0
|
|
|
|
|
0
|
|
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
13
|
|
|
13
|
0
|
37
|
sub list_builtins { qw(Entity ElementMacro) } |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub install_builtins { |
227
|
13
|
|
|
13
|
0
|
18
|
my ($modpack, $destpack) = @_; |
228
|
13
|
|
|
|
|
38
|
foreach my $name ($modpack->list_builtins) { |
229
|
26
|
50
|
|
|
|
134
|
my $sub = $modpack->can($name) |
230
|
|
|
|
|
|
|
or die "Can't find builtin: $name"; |
231
|
26
|
|
|
|
|
28
|
*{globref($destpack, $name)} = $sub; |
|
26
|
|
|
|
|
62
|
|
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
#======================================== |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub next_nsid { |
238
|
255
|
|
|
255
|
0
|
262
|
my Root $root = shift; |
239
|
255
|
|
|
|
|
401
|
++$root->{last_nsid}; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub createNS { |
243
|
255
|
|
|
255
|
0
|
425
|
(my Root $root, my ($type)) = splice @_, 0, 2; |
244
|
|
|
|
|
|
|
# class_id は? |
245
|
255
|
|
|
|
|
431
|
my $nsid = $root->next_nsid; |
246
|
255
|
|
|
|
|
1160
|
my NS $nsobj = $root->{NS}{$nsid} = $root->$type->new(nsid => $nsid, @_); |
247
|
255
|
|
|
|
|
448
|
my $pkg = $root->get_package($nsobj); |
248
|
255
|
100
|
|
|
|
437
|
foreach my $name (map {defined $_ ? @$_ : ()} $root->{cf_rc_global}) { |
|
255
|
|
|
|
|
608
|
|
249
|
14
|
|
|
|
|
10
|
*{globref($pkg, $name)} = *{globref($root->{cf_app_prefix}, $name)}; |
|
14
|
|
|
|
|
19
|
|
|
14
|
|
|
|
|
21
|
|
250
|
|
|
|
|
|
|
} |
251
|
255
|
|
|
|
|
1562
|
$nsid; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub nsobj { |
255
|
2277
|
|
|
2277
|
0
|
2450
|
(my Root $root, my ($nsid)) = @_; |
256
|
2277
|
50
|
|
|
|
3409
|
unless (defined $nsid) { |
257
|
0
|
|
|
|
|
0
|
croak "nsobj: undefined nsid!"; |
258
|
|
|
|
|
|
|
} |
259
|
2277
|
100
|
|
|
|
3373
|
return $root if $nsid == 0; |
260
|
1804
|
|
|
|
|
4872
|
$root->{NS}{$nsid}; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
sub get_package { |
264
|
1523
|
|
|
1523
|
0
|
1701
|
(my Root $root, my NS $nsobj, my ($sep)) = @_; |
265
|
|
|
|
|
|
|
# nsid のまま渡しても良いように。 |
266
|
1523
|
100
|
|
|
|
2669
|
$nsobj = $root->nsobj($nsobj) unless ref $nsobj; |
267
|
|
|
|
|
|
|
|
268
|
1523
|
|
66
|
|
|
5879
|
$nsobj->{cf_pkg} ||= do { |
269
|
275
|
|
|
|
|
174
|
my $pkg = do { |
270
|
275
|
100
|
|
|
|
466
|
if ($root == $nsobj) { |
271
|
20
|
100
|
|
|
|
62
|
$root->{cf_app_prefix} || '::' |
272
|
|
|
|
|
|
|
} else { |
273
|
255
|
|
50
|
|
|
1568
|
join $sep || "::" |
|
|
|
100
|
|
|
|
|
274
|
|
|
|
|
|
|
, $root->{cf_app_prefix} || '::' |
275
|
|
|
|
|
|
|
, sprintf '%.1s%d', $nsobj->type_name |
276
|
|
|
|
|
|
|
, $nsobj->{cf_nsid}; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
}; |
279
|
275
|
|
|
|
|
705
|
$root->checked_eval(qq{package $pkg}); |
280
|
275
|
|
|
|
|
790
|
$pkg; |
281
|
|
|
|
|
|
|
}; |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub refresh { |
285
|
551
|
|
|
551
|
0
|
685
|
(my Root $root, my NS $node) = @_; |
286
|
551
|
|
33
|
|
|
936
|
$node ||= $root; |
287
|
551
|
50
|
|
|
|
1100
|
return unless $node->{cf_loadkey}; |
288
|
551
|
100
|
100
|
|
|
1961
|
return if $node->{cf_age} and not $root->{cf_auto_reload}; |
289
|
229
|
50
|
|
|
|
484
|
return unless $root->{Loader}; |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# age があるのに、 is_loaded に達してない == まだ構築の途中。 |
292
|
229
|
100
|
100
|
|
|
577
|
return if $node->{cf_age} and not $node->{is_loaded}; |
293
|
222
|
|
|
|
|
619
|
$root->{loading}{$node->{cf_nsid}} = 1; |
294
|
|
|
|
|
|
|
|
295
|
222
|
50
|
|
|
|
474
|
print STDERR "Referesh: $node->{cf_loadkey}\n" |
296
|
|
|
|
|
|
|
if $root->{cf_debug_registry}; |
297
|
|
|
|
|
|
|
|
298
|
222
|
|
|
|
|
579
|
$root->{Loader}->handle_refresh($root, $node); |
299
|
216
|
|
|
|
|
665
|
$node->{is_loaded} = 1; |
300
|
216
|
|
|
|
|
787
|
delete $root->{loading}{$node->{cf_nsid}}; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
sub mark_load_failure { |
304
|
1
|
|
|
1
|
0
|
2
|
my Root $root = shift; |
305
|
1
|
|
|
|
|
3
|
while ((my $nsid, undef) = each %{$root->{loading}}) { |
|
2
|
|
|
|
|
12
|
|
306
|
1
|
|
|
|
|
4
|
my NS $ns = $root->nsobj($nsid); |
307
|
|
|
|
|
|
|
# 仮に、一度は load 済みだとする。 |
308
|
1
|
|
|
|
|
2
|
$ns->{is_loaded} = 1; |
309
|
1
|
|
|
|
|
3
|
delete $root->{loading}{$nsid}; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
sub get_ns { |
314
|
6
|
|
|
6
|
0
|
15
|
(my Root $root, my ($elempath)) = @_; |
315
|
6
|
|
|
|
|
21
|
$root->vivify_ns($root, @$elempath); |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub get_package_from_node { |
319
|
21
|
|
|
21
|
0
|
32
|
(my Root $root, my ($node)) = @_; |
320
|
21
|
|
|
|
|
65
|
my Dir $dir = $root->get_dir_from_node($node); |
321
|
21
|
|
|
|
|
54
|
$root->get_package($dir); |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
sub get_dir_from_node { |
325
|
21
|
|
|
21
|
0
|
22
|
(my Root $root, my ($node)) = @_; |
326
|
21
|
|
|
|
|
57
|
my Template $tmpl = $root->get_template_from_node($node); |
327
|
21
|
|
|
|
|
57
|
$root->nsobj($tmpl->{cf_parent_nsid}); |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
sub get_template_from_node { |
331
|
284
|
|
|
284
|
0
|
348
|
(my Root $root, my ($node)) = @_; |
332
|
284
|
|
|
|
|
775
|
$root->nsobj($node->metainfo->cget('nsid')); |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub get_widget { |
336
|
161
|
|
|
161
|
0
|
221
|
my Root $root = shift; |
337
|
161
|
|
|
|
|
414
|
$root->get_widget_from_dir($root, @_); |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub get_widget_from_template { |
341
|
101
|
|
|
101
|
0
|
311
|
(my Root $root, my Template $tmpl, my ($nsname)) = splice @_, 0, 3; |
342
|
101
|
|
|
|
|
101
|
my $widget; |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
# Relative lookup. ($nsname case is for [delegate]) |
345
|
101
|
100
|
|
|
|
441
|
$widget = $tmpl->lookup_widget($root, @_ ? @_ : $nsname) |
|
|
100
|
|
|
|
|
|
346
|
|
|
|
|
|
|
and return $widget; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# Absolute, ns-specific lookup. |
349
|
2
|
50
|
|
|
|
12
|
if ($root->has_ns($root, $nsname)) { |
350
|
0
|
0
|
|
|
|
0
|
$widget = $root->get_widget_from_dir($root, $nsname, @_) |
351
|
|
|
|
|
|
|
and return $widget; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# Absolute, general lookup. |
355
|
2
|
|
|
|
|
7
|
return $root->get_widget_from_dir($root, @_); |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub get_widget_from_dir { |
359
|
164
|
|
|
164
|
0
|
378
|
(my Root $root, my Dir $dir) = splice @_, 0, 2; |
360
|
164
|
|
|
|
|
222
|
my @elempath = @_; |
361
|
164
|
|
|
|
|
561
|
$dir = $dir->vivify_ns($root, splice @elempath, 0, @elempath - 2); |
362
|
164
|
50
|
|
|
|
405
|
unless ($dir) { |
363
|
0
|
|
|
|
|
0
|
croak "Can't find widget: ", join(":", @_); |
364
|
|
|
|
|
|
|
} |
365
|
164
|
100
|
|
|
|
487
|
if (@elempath == 2) { |
|
|
50
|
|
|
|
|
|
366
|
19
|
|
|
|
|
84
|
$dir->widget_by_nsname($root, @elempath); |
367
|
|
|
|
|
|
|
} elsif (@elempath == 1) { |
368
|
145
|
|
|
|
|
363
|
$dir->widget_by_name($root, @elempath); |
369
|
|
|
|
|
|
|
} else { |
370
|
0
|
|
|
|
|
0
|
return; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
{ |
375
|
|
|
|
|
|
|
sub YATT::Registry::NS::list_declared_widget_names { |
376
|
0
|
|
|
0
|
0
|
0
|
(my NS $tmpl) = @_; |
377
|
0
|
|
|
|
|
0
|
my @result; |
378
|
0
|
|
|
|
|
0
|
foreach my $name (keys %{$tmpl->{Widget}}) { |
|
0
|
|
|
|
|
0
|
|
379
|
0
|
|
|
|
|
0
|
my $w = $tmpl->{Widget}{$name}; |
380
|
0
|
0
|
|
|
|
0
|
next unless $w->declared; |
381
|
0
|
|
|
|
|
0
|
push @result, $name; |
382
|
|
|
|
|
|
|
} |
383
|
0
|
|
|
|
|
0
|
@result; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
# For relative lookup. |
387
|
|
|
|
|
|
|
sub YATT::Registry::NS::Template::lookup_widget { |
388
|
101
|
|
|
101
|
0
|
318
|
(my Template $tmpl, my Root $root) = splice @_, 0, 2; |
389
|
101
|
50
|
33
|
|
|
1051
|
croak "lookup_widget: argument type mismatch for \$root." |
|
|
|
33
|
|
|
|
|
390
|
|
|
|
|
|
|
unless defined $root and ref $root and $root->isa(Root); |
391
|
101
|
50
|
|
|
|
213
|
return unless @_; |
392
|
|
|
|
|
|
|
|
393
|
101
|
|
|
|
|
321
|
foreach my NS $start ($tmpl, $root->nsobj($tmpl->{cf_parent_nsid})) { |
394
|
103
|
|
|
|
|
213
|
my @elempath = @_; |
395
|
|
|
|
|
|
|
|
396
|
103
|
|
|
|
|
156
|
my NS $ns = do { |
397
|
103
|
50
|
|
|
|
255
|
if (@elempath <= 2) { |
398
|
103
|
|
|
|
|
141
|
$start; |
399
|
|
|
|
|
|
|
} else { |
400
|
0
|
|
|
|
|
0
|
$start->lookup_dir($root, splice @elempath, 0, @elempath - 2); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
}; |
403
|
|
|
|
|
|
|
|
404
|
103
|
|
|
|
|
150
|
my $found = do { |
405
|
103
|
100
|
|
|
|
232
|
if (@elempath == 2) { |
406
|
1
|
|
|
|
|
3
|
$ns->widget_by_nsname($root, @elempath); |
407
|
|
|
|
|
|
|
} else { |
408
|
102
|
|
|
|
|
359
|
$ns->widget_by_name($root, @elempath); |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
}; |
411
|
102
|
100
|
|
|
|
619
|
return $found if $found; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
sub YATT::Registry::NS::Template::lookup_template { |
416
|
4
|
|
|
4
|
0
|
5
|
(my Template $tmpl, my Root $root, my ($name)) = @_; |
417
|
4
|
|
|
|
|
11
|
$root->nsobj($tmpl->{cf_parent_nsid})->lookup_template($root, $name) |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
sub YATT::Registry::NS::Template::lookup_dir { |
421
|
0
|
|
|
0
|
0
|
0
|
(my Template $tmpl, my Root $root) = splice @_, 0, 2; |
422
|
0
|
|
|
|
|
0
|
$root->nsobj($tmpl->{cf_parent_nsid})->lookup_dir($root, @_); |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::has_ns { |
426
|
2
|
|
|
2
|
0
|
4
|
(my Dir $dir, my Root $root, my ($nsname)) = @_; |
427
|
2
|
|
|
|
|
1
|
my $nsid; |
428
|
|
|
|
|
|
|
|
429
|
2
|
50
|
33
|
|
|
15
|
$nsid = $dir->{Dir}{$nsname} || $dir->{Template}{$nsname} |
430
|
|
|
|
|
|
|
and return $root->nsobj($nsid); |
431
|
|
|
|
|
|
|
|
432
|
2
|
50
|
|
|
|
10
|
return unless $dir->{cf_base_nsid}; |
433
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
0
|
$root->nsobj($dir->{cf_base_nsid})->has_ns($root, $nsname); |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::lookup_template { |
438
|
4
|
|
|
4
|
0
|
8
|
(my Dir $dir, my Root $root, my ($name)) = @_; |
439
|
4
|
|
|
|
|
7
|
my $nsid; |
440
|
4
|
|
66
|
|
|
23
|
while (not($nsid = $dir->{Template}{$name}) |
441
|
|
|
|
|
|
|
and $dir->{cf_base_nsid}) { |
442
|
2
|
|
|
|
|
5
|
$dir = $root->nsobj($dir->{cf_base_nsid}); |
443
|
2
|
|
|
|
|
6
|
$root->refresh($dir); |
444
|
|
|
|
|
|
|
} |
445
|
4
|
50
|
|
|
|
12
|
return unless $nsid; |
446
|
4
|
|
|
|
|
9
|
$root->nsobj($nsid); |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
|
449
|
4
|
|
|
4
|
|
18
|
use Carp; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
3673
|
|
450
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::lookup_dir { |
451
|
12
|
|
|
12
|
0
|
27
|
(my Dir $dir, my Root $root, my (@nspath)) = @_; |
452
|
12
|
50
|
|
|
|
58
|
croak "argtype mismatch! not a Root." unless UNIVERSAL::isa($root, Root); |
453
|
12
|
50
|
|
|
|
31
|
return $root unless @nspath; |
454
|
12
|
|
|
|
|
26
|
(my Dir $start, my (@orig)) = ($dir, @nspath); |
455
|
12
|
|
|
|
|
30
|
$root->refresh($dir); |
456
|
12
|
|
66
|
|
|
67
|
while ($dir and defined (my $ns = shift @nspath)) { |
457
|
19
|
100
|
50
|
|
|
74
|
$dir = $root and next if $ns eq ''; |
458
|
12
|
|
|
|
|
31
|
my $nsid = $dir->{Dir}{$ns}; |
459
|
12
|
50
|
|
|
|
30
|
unless ($nsid) { |
460
|
0
|
0
|
|
|
|
0
|
return $start->{cf_base_nsid} |
461
|
|
|
|
|
|
|
? $root->nsobj($start->{cf_base_nsid})->lookup_dir($root, @orig) |
462
|
|
|
|
|
|
|
: undef; |
463
|
|
|
|
|
|
|
} |
464
|
12
|
|
|
|
|
27
|
$dir = $root->nsobj($nsid); |
465
|
12
|
|
|
|
|
28
|
$root->refresh($dir); |
466
|
|
|
|
|
|
|
} |
467
|
12
|
|
|
|
|
42
|
$dir; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::list_ns { |
471
|
4
|
|
|
4
|
0
|
15
|
(my Dir $dir, my ($dict)) = @_; |
472
|
4
|
|
50
|
|
|
16
|
$dict ||= {}; |
473
|
4
|
|
|
|
|
5
|
my @list; |
474
|
4
|
|
|
|
|
7
|
foreach my $type (qw(Template Dir)) { |
475
|
8
|
|
|
|
|
7
|
foreach my $key (keys %{$dir->{$type}}) { |
|
8
|
|
|
|
|
21
|
|
476
|
9
|
100
|
|
|
|
30
|
push @list, $key unless $dict->{$key}++; |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
} |
479
|
4
|
50
|
|
|
|
38
|
wantarray ? @list : \@list; |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::vivify_ns { |
483
|
170
|
|
|
170
|
0
|
310
|
(my Dir $dir, my Root $root, my (@nspath)) = @_; |
484
|
170
|
|
|
|
|
261
|
my @orig = @nspath; |
485
|
170
|
|
|
|
|
387
|
while (@nspath) { |
486
|
7
|
|
|
|
|
17
|
$root->refresh($dir); |
487
|
7
|
|
|
|
|
8
|
$dir = do { |
488
|
7
|
|
|
|
|
13
|
my $ns = shift @nspath; |
489
|
7
|
|
|
|
|
8
|
my Dir $d = $dir; |
490
|
7
|
|
|
|
|
8
|
my $nsid; |
491
|
7
|
|
100
|
|
|
58
|
while (not($nsid = $d->{Dir}{$ns}) |
|
|
|
66
|
|
|
|
|
492
|
|
|
|
|
|
|
and not($nsid = $d->{Template}{$ns}) |
493
|
|
|
|
|
|
|
and $d->{cf_base_nsid}) { |
494
|
2
|
|
|
|
|
7
|
$d = $root->nsobj($d->{cf_base_nsid}); |
495
|
2
|
|
|
|
|
5
|
$root->refresh($d); |
496
|
|
|
|
|
|
|
} |
497
|
7
|
50
|
|
|
|
17
|
unless ($nsid) { |
498
|
0
|
|
|
|
|
0
|
croak "No such ns '$ns': " . join ":", @orig; |
499
|
|
|
|
|
|
|
} |
500
|
7
|
|
|
|
|
12
|
$root->nsobj($nsid); |
501
|
|
|
|
|
|
|
}; |
502
|
|
|
|
|
|
|
} |
503
|
170
|
|
|
|
|
300
|
$dir; |
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::after_rc_loaded { |
507
|
17
|
|
|
17
|
0
|
28
|
(my Dir $dir, my Root $root) = @_; |
508
|
17
|
100
|
|
|
|
67
|
if (defined(my $base = $dir->{cf_base_nsid})) { |
509
|
12
|
|
|
|
|
18
|
foreach my Template $tmpl (map {$root->nsobj($_)} |
|
13
|
|
|
|
|
30
|
|
|
12
|
|
|
|
|
41
|
|
510
|
|
|
|
|
|
|
values %{$dir->{Template}}) { |
511
|
13
|
|
|
|
|
36
|
$tmpl->{cf_base_nsid} = $base; |
512
|
|
|
|
|
|
|
} |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::widget_by_nsname { |
517
|
22
|
|
|
22
|
0
|
79
|
(my Dir $dir, my Root $root, my ($ns, $name)) = @_; |
518
|
22
|
|
|
|
|
75
|
$root->refresh($dir); |
519
|
22
|
50
|
66
|
|
|
335
|
if (defined $dir->{cf_name} and $dir->{cf_name} eq $ns) { |
520
|
0
|
|
|
|
|
0
|
my $widget = $dir->widget_by_name($root, $name); |
521
|
0
|
0
|
|
|
|
0
|
return $widget if $widget; |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
# [1] dir:template |
524
|
|
|
|
|
|
|
# [2] template:widget |
525
|
22
|
|
|
|
|
45
|
foreach my $type (qw(Dir Template)) { |
526
|
23
|
100
|
|
|
|
101
|
next unless my $nsid = $dir->{$type}{$ns}; |
527
|
21
|
50
|
|
|
|
65
|
next unless my $widget = $root->nsobj($nsid) |
528
|
|
|
|
|
|
|
->widget_by_name($root, $name); |
529
|
21
|
|
|
|
|
200
|
return $widget; |
530
|
|
|
|
|
|
|
} |
531
|
1
|
50
|
|
|
|
3
|
return unless $dir->{cf_base_nsid}; |
532
|
1
|
|
|
|
|
2
|
$root->nsobj($dir->{cf_base_nsid})->widget_by_nsname($root, $ns, $name); |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
sub YATT::Registry::NS::Dir::widget_by_name { |
536
|
192
|
|
|
192
|
0
|
276
|
(my Dir $dir, my Root $root, my ($name)) = @_; |
537
|
192
|
|
|
|
|
1148
|
$root->refresh($dir); |
538
|
192
|
100
|
|
|
|
635
|
if (my $nsid = $dir->{Template}{$name}) { |
539
|
175
|
|
|
|
|
326
|
$root->refresh($root->nsobj($nsid)); |
540
|
|
|
|
|
|
|
} |
541
|
186
|
100
|
100
|
|
|
1520
|
$dir->{Widget}{$name} |
542
|
|
|
|
|
|
|
|| $dir->{cf_base_nsid} |
543
|
|
|
|
|
|
|
&& $root->nsobj($dir->{cf_base_nsid})->widget_by_name($root, $name); |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
sub YATT::Registry::NS::Template::widget_by_nsname { |
547
|
1
|
|
|
1
|
0
|
2
|
(my Template $tmpl, my Root $root, my ($ns, $name)) = @_; |
548
|
1
|
50
|
|
|
|
3
|
if ($tmpl->{cf_name} eq $ns) { |
549
|
0
|
|
|
|
|
0
|
my $widget = $tmpl->widget_by_name($root, $name); |
550
|
0
|
0
|
|
|
|
0
|
return $widget if $widget; |
551
|
|
|
|
|
|
|
} |
552
|
1
|
|
|
|
|
3
|
my Dir $parent = $root->nsobj($tmpl->{cf_parent_nsid}); |
553
|
1
|
50
|
33
|
|
|
4
|
if (defined $parent->{cf_name} and $parent->{cf_name} eq $ns) { |
554
|
0
|
|
|
|
|
0
|
my $widget = $tmpl->widget_by_name($root, $name); |
555
|
0
|
0
|
|
|
|
0
|
return $widget if $widget; |
556
|
|
|
|
|
|
|
} |
557
|
1
|
|
|
|
|
2
|
$parent->widget_by_nsname($root, $ns, $name); |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
sub YATT::Registry::NS::Template::widget_by_name { |
561
|
103
|
|
|
103
|
0
|
166
|
(my Template $tmpl, my Root $root, my ($name)) = @_; |
562
|
103
|
|
|
|
|
284
|
$root->refresh($tmpl); |
563
|
103
|
|
|
|
|
111
|
my $widget; |
564
|
103
|
100
|
|
|
|
408
|
$widget = $tmpl->{Widget}{$name} |
565
|
|
|
|
|
|
|
and return $widget; |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
# 同一ディレクトリのテンプレートを先に検索するため。 |
568
|
|
|
|
|
|
|
# XXX: しかし、継承順序に問題が出ているはず。 |
569
|
16
|
100
|
|
|
|
40
|
$widget = $root->nsobj($tmpl->{cf_parent_nsid}) |
570
|
|
|
|
|
|
|
->widget_by_name($root, $name) |
571
|
|
|
|
|
|
|
and return $widget; |
572
|
|
|
|
|
|
|
|
573
|
5
|
100
|
|
|
|
17
|
if ($tmpl->{cf_base_template}) { |
574
|
3
|
50
|
|
|
|
8
|
$widget = $root->nsobj($tmpl->{cf_base_template}) |
575
|
|
|
|
|
|
|
->widget_by_name($root, $name) |
576
|
|
|
|
|
|
|
and return $widget; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
2
|
50
|
|
|
|
7
|
if ($tmpl->{cf_base_nsid}) { |
580
|
0
|
0
|
|
|
|
0
|
$widget = $root->nsobj($tmpl->{cf_base_nsid}) |
581
|
|
|
|
|
|
|
->widget_by_name($root, $name) |
582
|
|
|
|
|
|
|
and return $widget; |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
2
|
|
|
|
|
4
|
return; |
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
} |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
sub node_error { |
590
|
18
|
|
|
18
|
0
|
55
|
(my Root $root, my ($node, $fmt)) = splice @_, 0, 3; |
591
|
18
|
50
|
|
|
|
140
|
$root->node_error_obj($node |
592
|
|
|
|
|
|
|
, error_fmt => ref $fmt ? join(" ", $fmt) : $fmt |
593
|
|
|
|
|
|
|
, error_param => [@_] |
594
|
|
|
|
|
|
|
, caller => [caller]); |
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
sub node_error_obj { |
598
|
18
|
|
|
18
|
0
|
49
|
(my Root $root, my ($node, @param)) = @_; |
599
|
|
|
|
|
|
|
# XXX: $root->{cf_backtrace} なら longmess も append, とか。 |
600
|
|
|
|
|
|
|
# XXX: Error オブジェクトにするべきかもね。でも依存は嫌。 |
601
|
|
|
|
|
|
|
# ← die を $root->raise で wrap すれば良い? |
602
|
18
|
|
|
|
|
75
|
my $stringify = $root->checked(stringify => "(Can't stringify: %s)", $node); |
603
|
18
|
|
|
|
|
58
|
my $filename = $root->checked(filename => "(Can't get filename %s)", $node); |
604
|
18
|
|
|
|
|
81
|
my $linenum = $root->checked(linenum => "(Can't get linenum %s)", $node); |
605
|
18
|
|
|
|
|
159
|
$root->Exception->new(@param |
606
|
|
|
|
|
|
|
, node_obj => $node |
607
|
|
|
|
|
|
|
, node => $stringify, file => $filename |
608
|
|
|
|
|
|
|
, line => $linenum); |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
sub node_nimpl { |
612
|
0
|
|
|
0
|
0
|
0
|
(my Root $root, my ($node, $msg)) = @_; |
613
|
0
|
|
|
|
|
0
|
my $caller = [my ($pack, $file, $line) = caller]; |
614
|
0
|
|
0
|
|
|
0
|
$root->node_error_obj($node |
615
|
|
|
|
|
|
|
, error_fmt => join(' ' |
616
|
|
|
|
|
|
|
, ($msg || "Not yet implemented") |
617
|
|
|
|
|
|
|
, "(perl file $file line $line)") |
618
|
|
|
|
|
|
|
, caller => $caller); |
619
|
|
|
|
|
|
|
} |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
sub strip_ns { |
622
|
811
|
|
|
811
|
0
|
799
|
(my Root $root, my ($list)) = @_; |
623
|
811
|
|
|
|
|
1602
|
$root->shift_ns_by($root->{nspattern}, $list); |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
sub shift_ns_by { |
627
|
862
|
|
|
862
|
0
|
1095
|
(my Root $root, my ($pattern, $list)) = @_; |
628
|
862
|
100
|
|
|
|
1420
|
return unless @$list; |
629
|
854
|
50
|
|
|
|
1285
|
return unless defined $pattern; |
630
|
854
|
100
|
|
|
|
1278
|
if (ref $pattern) { |
631
|
809
|
100
|
|
|
|
4397
|
return unless $list->[0] =~ $pattern |
632
|
|
|
|
|
|
|
} else { |
633
|
45
|
100
|
|
|
|
150
|
return unless $list->[0] eq $pattern; |
634
|
|
|
|
|
|
|
} |
635
|
818
|
|
|
|
|
1635
|
shift @$list; |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
#======================================== |
639
|
|
|
|
|
|
|
|
640
|
4
|
|
|
4
|
|
18
|
use YATT::LRXML::Node qw(DECLARATOR_TYPE node_path create_node); |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
219
|
|
641
|
|
|
|
|
|
|
sub DEFAULT_WIDGET () {''} |
642
|
|
|
|
|
|
|
|
643
|
4
|
|
|
4
|
|
1765
|
use YATT::LRXML::MetaInfo; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
155
|
|
644
|
4
|
|
|
4
|
|
1304
|
use YATT::Widget; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
149
|
|
645
|
|
|
|
|
|
|
|
646
|
4
|
|
|
4
|
|
1261
|
use YATT::LRXML; # for Builder. |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
32
|
|
647
|
|
|
|
|
|
|
use YATT::Types |
648
|
4
|
|
|
|
|
24
|
([WidgetBuilder => [qw(cf_widget ^cf_template cf_root_builder)]] |
649
|
|
|
|
|
|
|
, -base => qw(YATT::LRXML::Builder) |
650
|
|
|
|
|
|
|
, -alias => [Builder => __PACKAGE__ . '::WidgetBuilder' |
651
|
|
|
|
|
|
|
, Scanner => 'YATT::LRXML::Scanner'] |
652
|
4
|
|
|
4
|
|
144
|
); |
|
4
|
|
|
|
|
5
|
|
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
# XXX: 名前が紛らわしい。lrxml tree の root か、Registry の root か、と。 |
655
|
|
|
|
|
|
|
sub new_root_builder { |
656
|
156
|
|
|
156
|
0
|
268
|
(my Root $root, my $parser, my Scanner $scan) = @_; |
657
|
156
|
|
|
|
|
494
|
my MetaInfo $meta = $parser->metainfo; |
658
|
156
|
|
|
|
|
541
|
my Template $tmpl = $root->nsobj($meta->{cf_nsid}); |
659
|
|
|
|
|
|
|
|
660
|
156
|
|
|
|
|
448
|
my $widget = $root->create_widget_in |
661
|
|
|
|
|
|
|
($tmpl, DEFAULT_WIDGET |
662
|
|
|
|
|
|
|
, filename => $meta->cget('filename') |
663
|
|
|
|
|
|
|
, decl_start => $scan->{cf_linenum} |
664
|
|
|
|
|
|
|
, body_start => $scan->{cf_linenum} + $scan->number_of_lines); |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
# 親ディレクトリに登録。 |
667
|
156
|
|
|
|
|
460
|
my Dir $parent = $root->nsobj($tmpl->{cf_parent_nsid}); |
668
|
|
|
|
|
|
|
|
669
|
156
|
|
|
|
|
505
|
$parent->{Widget}{$tmpl->{cf_name}} = $widget; |
670
|
|
|
|
|
|
|
|
671
|
156
|
|
|
|
|
521
|
$parser->configure(tree => my $sink = $widget->cget('root')); |
672
|
|
|
|
|
|
|
|
673
|
156
|
|
|
|
|
1870
|
$root->Builder->new($sink, undef |
674
|
|
|
|
|
|
|
, widget => $widget |
675
|
|
|
|
|
|
|
, template => $tmpl |
676
|
|
|
|
|
|
|
, startpos => 0 |
677
|
|
|
|
|
|
|
, startline => $scan->{cf_linenum} |
678
|
|
|
|
|
|
|
, linenum => $scan->{cf_linenum}); |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
sub fake_cursor_from { |
682
|
19
|
|
|
19
|
0
|
42
|
(my MY $trans, my ($cursor, $node, $is_opened)) = @_; |
683
|
19
|
|
|
|
|
82
|
my $parent = $cursor->Path->new($node, $cursor->cget('path')); |
684
|
19
|
100
|
|
|
|
98
|
my $path = $is_opened ? $parent |
685
|
|
|
|
|
|
|
: $cursor->Path->new($trans->create_node(unknown => undef, $node) |
686
|
|
|
|
|
|
|
, $parent); |
687
|
19
|
|
|
|
|
59
|
$cursor->clone($path); |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
sub fake_cursor { |
691
|
194
|
|
|
194
|
0
|
413
|
(my MY $gen, my Widget $widget, my ($metainfo)) = splice @_, 0, 3; |
692
|
194
|
|
|
|
|
554
|
my $cursor = $widget->cursor(metainfo => $metainfo); |
693
|
194
|
|
|
|
|
744
|
my $node = $gen->create_node(unknown => undef, @_); |
694
|
194
|
|
|
|
|
857
|
$cursor->clone($cursor->Path->new($node, $cursor->cget('path'))); |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
sub fake_cursor_to_build { |
698
|
184
|
|
|
184
|
0
|
273
|
(my MY $root, my Builder $builder, my Scanner $scan |
699
|
|
|
|
|
|
|
, my ($elem)) = @_; |
700
|
184
|
|
|
|
|
818
|
$root->fake_cursor($builder->{cf_widget} |
701
|
|
|
|
|
|
|
, $builder->{cf_template}->metainfo |
702
|
|
|
|
|
|
|
->clone(startline => $scan->{cf_linenum}) |
703
|
|
|
|
|
|
|
, $elem); |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
sub new_decl_builder { |
707
|
183
|
|
|
183
|
0
|
369
|
(my MY $root, my Builder $builder, my Scanner $scan |
708
|
|
|
|
|
|
|
, my ($elem, $parser)) = @_; |
709
|
183
|
|
|
|
|
342
|
foreach my $shift (0, 1) { |
710
|
366
|
|
|
|
|
826
|
my $path = [node_path($elem)]; |
711
|
366
|
100
|
|
|
|
923
|
$root->strip_ns($path) if $shift; |
712
|
366
|
|
|
|
|
677
|
my $handler_name = join("_", declare => @$path); |
713
|
|
|
|
|
|
|
|
714
|
366
|
100
|
|
|
|
1511
|
if (my $handler = $root->can($handler_name)) { |
715
|
181
|
|
|
|
|
523
|
my $nc = $root->fake_cursor_to_build($builder, $scan, $elem)->open; |
716
|
181
|
|
|
|
|
1079
|
return $handler->($root, $builder, $scan, $nc, $parser); |
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
2
|
|
|
|
|
10
|
die $root->node_error($root->fake_cursor_to_build($builder, $scan, $elem) |
721
|
|
|
|
|
|
|
, "Unknown declarator"); |
722
|
|
|
|
|
|
|
} |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
sub declare_base { |
725
|
4
|
|
|
4
|
0
|
9
|
(my Root $root, my Builder $builder, my ($scan, $args, $parser)) = @_; |
726
|
4
|
50
|
|
|
|
15
|
if ($builder->{parent}) { |
727
|
0
|
|
|
|
|
0
|
die $scan->token_error("Misplaced yatt:base"); |
728
|
|
|
|
|
|
|
} |
729
|
4
|
|
|
|
|
14
|
my $path = $args->node_body; |
730
|
4
|
|
|
|
|
8
|
my Template $this = $builder->{cf_template}; |
731
|
4
|
50
|
|
|
|
16
|
my Template $base = $this->lookup_template($root, $path) |
732
|
|
|
|
|
|
|
or die $scan->token_error("Can't find template $path"); |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
# XXX: refresh は lookup_template の中ですべきか? |
735
|
4
|
|
|
|
|
13
|
$root->refresh($base); |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
# 名前は保存しなくていいの? |
738
|
4
|
|
|
|
|
12
|
$this->{cf_base_template} = $base->{cf_nsid}; |
739
|
|
|
|
|
|
|
|
740
|
4
|
|
|
|
|
14
|
$root->add_isa($root->get_package($this) |
741
|
|
|
|
|
|
|
, $root->get_package($base)); |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
# builder を返すことを忘れずに。 |
744
|
4
|
|
|
|
|
62
|
$builder; |
745
|
|
|
|
|
|
|
} |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
sub declare_args { |
748
|
87
|
|
|
87
|
0
|
287
|
(my Root $root, my Builder $builder |
749
|
|
|
|
|
|
|
, my ($scan, $nc, $parser, @configs)) = @_; |
750
|
87
|
50
|
|
|
|
324
|
if ($builder->{parent}) { |
751
|
0
|
|
|
|
|
0
|
die $scan->token_error("Misplaced yatt:args"); |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
# widget -> args の順番で出現する場合もある。 |
754
|
|
|
|
|
|
|
# root 用の builder を取り出し直す |
755
|
87
|
100
|
|
|
|
246
|
if ($builder->{cf_root_builder}) { |
756
|
2
|
|
|
|
|
5
|
$builder = $builder->{cf_root_builder}; |
757
|
|
|
|
|
|
|
} |
758
|
87
|
|
|
|
|
137
|
my Widget $widget = $builder->{cf_widget}; |
759
|
87
|
|
|
|
|
174
|
$widget->{cf_declared} = 1; |
760
|
87
|
|
|
|
|
131
|
$widget->{cf_decl_start} = $scan->{cf_last_linenum}; |
761
|
87
|
|
|
|
|
226
|
$widget->{cf_body_start} = $scan->{cf_last_linenum} + $scan->{cf_last_nol}; |
762
|
87
|
50
|
|
|
|
170
|
$widget->configure(@configs) if @configs; |
763
|
87
|
|
|
|
|
274
|
$root->define_args($widget, $nc); |
764
|
87
|
|
|
|
|
364
|
$root->after_define_args($widget); |
765
|
87
|
|
|
|
|
1117
|
$builder; |
766
|
|
|
|
|
|
|
} |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
sub declare_params { |
769
|
0
|
|
|
0
|
0
|
0
|
shift->declare_args(@_, public => 1); |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
sub declare_widget { |
773
|
90
|
|
|
90
|
0
|
219
|
(my Root $root, my Builder $builder, my Scanner $scan |
774
|
|
|
|
|
|
|
, my ($args, $parser)) = @_; |
775
|
|
|
|
|
|
|
|
776
|
90
|
100
|
|
|
|
240
|
if ($builder->{parent}) { |
777
|
1
|
|
|
|
|
11
|
die $root->node_error($root->fake_cursor_to_build($builder, $scan |
778
|
|
|
|
|
|
|
, $builder->product) |
779
|
|
|
|
|
|
|
, "Misplaced yatt:widget in:"); |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
89
|
50
|
|
|
|
282
|
defined (my $name = $args->node_name) |
783
|
|
|
|
|
|
|
or die $root->node_error($args, "widget name is missing"); |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# XXX: filename, lineno |
786
|
89
|
|
|
|
|
386
|
my Widget $widget = $root->create_widget_in |
787
|
|
|
|
|
|
|
($builder->{cf_template}, $name |
788
|
|
|
|
|
|
|
, declared => 1 |
789
|
|
|
|
|
|
|
, filename => $builder->{cf_template}->metainfo->cget('filename') |
790
|
|
|
|
|
|
|
, decl_start => $scan->{cf_last_linenum} |
791
|
|
|
|
|
|
|
, body_start => $scan->{cf_last_linenum} + $scan->{cf_last_nol}); |
792
|
|
|
|
|
|
|
|
793
|
89
|
|
|
|
|
315
|
$root->define_args($widget, $args->go_next); |
794
|
88
|
|
|
|
|
324
|
$root->after_define_args($widget); |
795
|
|
|
|
|
|
|
|
796
|
88
|
|
66
|
|
|
442
|
$root->Builder->new($widget->cget('root'), undef |
797
|
|
|
|
|
|
|
, widget => $widget |
798
|
|
|
|
|
|
|
, template => $builder->{cf_template} |
799
|
|
|
|
|
|
|
, startpos => $scan->{cf_index} |
800
|
|
|
|
|
|
|
, startline => $scan->{cf_linenum} |
801
|
|
|
|
|
|
|
, linenum => $scan->{cf_linenum} |
802
|
|
|
|
|
|
|
# widget -> args に戻るためには root_builder を |
803
|
|
|
|
|
|
|
# 渡さねばならぬ |
804
|
|
|
|
|
|
|
, root_builder => |
805
|
|
|
|
|
|
|
$builder->{cf_root_builder} || $builder |
806
|
|
|
|
|
|
|
); |
807
|
|
|
|
|
|
|
} |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
sub create_widget_in { |
810
|
245
|
|
|
245
|
0
|
516
|
(my Root $root, my Template $tmpl, my ($name)) = splice @_, 0, 3; |
811
|
245
|
|
|
|
|
1279
|
my $widget = YATT::Widget->new |
812
|
|
|
|
|
|
|
(name => $name, template_nsid => $tmpl->{cf_nsid} |
813
|
|
|
|
|
|
|
, @_); |
814
|
245
|
|
|
|
|
690
|
$tmpl->{Widget}{$name} = $widget; |
815
|
245
|
|
|
|
|
252
|
push @{$tmpl->{widget_list}}, $widget; |
|
245
|
|
|
|
|
509
|
|
816
|
245
|
|
|
|
|
371
|
$widget; |
817
|
|
|
|
|
|
|
} |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
sub current_parser { |
820
|
0
|
|
|
0
|
0
|
0
|
my Root $root = shift; |
821
|
0
|
|
|
|
|
0
|
$root->{current_parser}[0]; |
822
|
|
|
|
|
|
|
} |
823
|
|
|
|
|
|
|
|
824
|
2
|
|
|
2
|
0
|
2
|
sub after_define_args {shift; shift} |
|
2
|
|
|
|
|
2
|
|
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
sub define_args { |
827
|
194
|
|
|
194
|
0
|
330
|
(my Root $root, my ($target, $args)) = @_; |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
# $target は has_arg($name) と add_arg($name, $arg) を実装しているもの。 |
830
|
|
|
|
|
|
|
# *: widget |
831
|
|
|
|
|
|
|
# *: codevar |
832
|
|
|
|
|
|
|
|
833
|
194
|
|
|
|
|
644
|
for (; $args->readable; $args->next) { |
834
|
|
|
|
|
|
|
# マクロ引数呼び出し %name(); がここで出現 |
835
|
|
|
|
|
|
|
# comment も現れうる。 |
836
|
|
|
|
|
|
|
# body = [code title=html] みたいなグループ引数もここで。 |
837
|
|
|
|
|
|
|
|
838
|
309
|
100
|
|
|
|
748
|
my $sub = $root->can("add_decl_" . $args->node_type_name) |
839
|
|
|
|
|
|
|
or next; |
840
|
|
|
|
|
|
|
|
841
|
290
|
|
|
|
|
624
|
$sub->($root, $target, $args); |
842
|
|
|
|
|
|
|
} |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
# おまけ。使わないけど、デバッグ時に少し幸せ。 |
845
|
193
|
|
|
|
|
327
|
$root; |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
sub add_decl_attribute { |
849
|
239
|
|
|
239
|
0
|
348
|
(my Root $root, my ($target, $args)) = @_; |
850
|
239
|
|
|
|
|
529
|
my $argname = $args->node_name; |
851
|
239
|
50
|
|
|
|
473
|
unless (defined $argname) { |
852
|
0
|
|
|
|
|
0
|
die $root->node_error($args, "Undefined att name!"); |
853
|
|
|
|
|
|
|
} |
854
|
239
|
50
|
|
|
|
570
|
if ($target->has_arg($argname)) { |
855
|
0
|
|
|
|
|
0
|
die $root->node_error($args, "Duplicate argname: $argname"); |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
|
858
|
239
|
|
|
|
|
601
|
my ($type, @param) = $args->parse_typespec; |
859
|
239
|
|
|
|
|
291
|
my ($typename, $subtype) = do { |
860
|
239
|
100
|
|
|
|
434
|
if (ref $type) { |
861
|
3
|
|
|
|
|
9
|
($type->[0], [@{$type}[1 .. $#$type]]) |
|
3
|
|
|
|
|
7
|
|
862
|
|
|
|
|
|
|
} else { |
863
|
236
|
|
|
|
|
366
|
($type, undef); |
864
|
|
|
|
|
|
|
} |
865
|
|
|
|
|
|
|
}; |
866
|
239
|
100
|
100
|
|
|
1311
|
if (defined $typename and my $sub = $root->can("attr_declare_$typename")) { |
867
|
7
|
|
|
|
|
38
|
$sub->($root, $target, $args, $argname, $subtype, @param); |
868
|
|
|
|
|
|
|
} else { |
869
|
232
|
|
|
|
|
499
|
$target->add_arg($argname, $root->create_var($type, $args, @param)); |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
} |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
sub create_var { |
874
|
427
|
|
|
427
|
0
|
953
|
(my Root $root, my ($type, $args, @param)) = @_; |
875
|
427
|
100
|
|
|
|
819
|
$type = '' unless defined $type; |
876
|
427
|
100
|
|
|
|
739
|
my ($primary, @subtype) = ref $type ? @$type : $type; |
877
|
427
|
50
|
|
|
|
1300
|
defined (my $class = $root->{cf_type_map}{$primary}) |
878
|
|
|
|
|
|
|
or croak $root->node_error($args, "No such type: %s", $primary); |
879
|
427
|
50
|
|
|
|
736
|
unshift @param, subtype => @subtype >= 2 ? \@subtype : $subtype[0] |
|
|
100
|
|
|
|
|
|
880
|
|
|
|
|
|
|
if @subtype; |
881
|
427
|
100
|
|
|
|
1687
|
if (my $sub = $root->can("create_var_$primary")) { |
882
|
172
|
|
|
|
|
450
|
$sub->($root, $args, @param); |
883
|
|
|
|
|
|
|
} else { |
884
|
255
|
|
|
|
|
1251
|
$class->new(@param); |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
#======================================== |
889
|
|
|
|
|
|
|
{ |
890
|
4
|
|
|
4
|
|
17
|
package YATT::Registry::Loader; use YATT::Inc; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
17
|
|
891
|
4
|
|
|
4
|
|
12
|
use base qw(YATT::Class::Configurable); |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
227
|
|
892
|
4
|
|
|
4
|
|
16
|
use YATT::Fields qw(Cache); |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
12
|
|
893
|
4
|
|
|
4
|
|
16
|
use Carp; |
|
4
|
|
|
|
|
3
|
|
|
4
|
|
|
|
|
164
|
|
894
|
4
|
|
|
4
|
|
15
|
use YATT::Registry::NS; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
685
|
|
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub DIR () { 'YATT::Registry::Loader::DIR' } |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
sub handle_refresh { |
899
|
222
|
|
|
222
|
0
|
268
|
(my MY $loader, my Root $root, my NS $node) = @_; |
900
|
222
|
|
|
|
|
641
|
my $type = $node->type_name; |
901
|
222
|
50
|
|
|
|
994
|
if (my $sub = $loader->can("refresh_$type")) { |
902
|
222
|
|
|
|
|
518
|
$sub->($loader, $root, $node); |
903
|
|
|
|
|
|
|
} else { |
904
|
0
|
|
|
|
|
0
|
confess "Can't refresh type: $type"; |
905
|
|
|
|
|
|
|
} |
906
|
|
|
|
|
|
|
} |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
sub is_modified { |
909
|
222
|
|
|
222
|
0
|
270
|
my MY $loader = shift; |
910
|
222
|
|
|
|
|
393
|
my ($item, $old) = @_; |
911
|
222
|
|
|
|
|
540
|
my $mtime = $loader->mtime($item); |
912
|
222
|
100
|
100
|
|
|
750
|
return if defined $old and $old >= $mtime; |
913
|
199
|
|
|
|
|
542
|
$_[1] = $mtime; |
914
|
199
|
|
|
|
|
563
|
return 1; |
915
|
|
|
|
|
|
|
} |
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
package YATT::Registry::Loader::DIR; |
918
|
|
|
|
|
|
|
|
919
|
4
|
|
|
4
|
|
15
|
use base qw(YATT::Registry::Loader File::Spec); |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
388
|
|
920
|
4
|
|
|
4
|
|
14
|
use YATT::Fields qw(cf_DIR cf_LIB); |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
14
|
|
921
|
20
|
|
|
20
|
|
64
|
sub initargs { qw(cf_DIR) } |
922
|
|
|
|
|
|
|
sub init { |
923
|
20
|
|
|
20
|
|
45
|
my ($self, $dir) = splice @_, 0, 2; |
924
|
20
|
|
|
|
|
93
|
$self->SUPER::init($dir, @_); |
925
|
20
|
100
|
|
|
|
383
|
if (-d (my $libdir = "$dir/lib")) { |
926
|
1
|
|
|
|
|
5
|
require lib; import lib $libdir |
|
1
|
|
|
|
|
8
|
|
927
|
|
|
|
|
|
|
} |
928
|
20
|
|
|
|
|
159
|
$self; |
929
|
|
|
|
|
|
|
} |
930
|
|
|
|
|
|
|
|
931
|
4
|
|
|
4
|
|
15
|
use YATT::Registry::NS; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
190
|
|
932
|
4
|
|
|
4
|
|
21
|
use YATT::Util; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
401
|
|
933
|
4
|
|
|
4
|
|
17
|
use YATT::Util::Taint; |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
442
|
|
934
|
|
|
|
|
|
|
|
935
|
222
|
|
|
222
|
|
212
|
sub mtime { shift; (stat(shift))[9]; } |
|
222
|
|
|
|
|
6311
|
|
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
sub RCFILE () {'.htyattrc'} |
938
|
|
|
|
|
|
|
sub Parser () {'YATT::LRXML::Parser'} |
939
|
|
|
|
|
|
|
|
940
|
4
|
|
|
4
|
|
16
|
use Carp; |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
3488
|
|
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
sub checked_read_file { |
943
|
17
|
|
|
17
|
|
40
|
(my MY $loader, my ($fn, $layer)) = @_; |
944
|
17
|
50
|
|
|
|
60
|
croak "Given path is tainted! $fn" if is_tainted($fn); |
945
|
17
|
50
|
50
|
|
|
590
|
open my $fh, '<' . ($layer || ''), $fn |
946
|
|
|
|
|
|
|
or die "Can't open $fn! $!"; |
947
|
17
|
|
|
|
|
63
|
local $/; |
948
|
17
|
|
|
|
|
367
|
scalar <$fh>; |
949
|
|
|
|
|
|
|
} |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
sub refresh_Dir { |
952
|
64
|
|
|
64
|
|
118
|
(my MY $loader, my Root $root, my Dir $dir) = @_; |
953
|
64
|
|
|
|
|
92
|
my $dirname = $dir->{cf_loadkey}; |
954
|
|
|
|
|
|
|
# ファイルリストの処理. |
955
|
64
|
100
|
|
|
|
210
|
return unless $loader->is_modified($dirname, $dir->{cf_mtime}{$dirname}); |
956
|
|
|
|
|
|
|
|
957
|
43
|
|
|
|
|
97
|
my $is_reload = $dir->{cf_age}++; |
958
|
43
|
|
|
|
|
66
|
undef $dir->{is_loaded}; |
959
|
|
|
|
|
|
|
|
960
|
43
|
50
|
|
|
|
122
|
if (is_tainted($dirname)) { |
961
|
0
|
|
|
|
|
0
|
croak "Directory $dirname is tainted" |
962
|
|
|
|
|
|
|
} |
963
|
|
|
|
|
|
|
|
964
|
43
|
100
|
|
|
|
92
|
if ($root == $dir) { |
965
|
21
|
50
|
|
|
|
44
|
foreach my $d ($dirname, map {!defined $_ ? () : ref $_ ? @$_ : $_} |
|
21
|
100
|
|
|
|
95
|
|
966
|
|
|
|
|
|
|
$loader->{cf_LIB}) { |
967
|
38
|
|
|
|
|
105
|
$loader->load_dir($root, $dir, $d); |
968
|
|
|
|
|
|
|
} |
969
|
|
|
|
|
|
|
} else { |
970
|
22
|
|
|
|
|
106
|
$loader->load_dir($root, $dir, $dirname); |
971
|
|
|
|
|
|
|
} |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
# RC 読み込みの前に、 default_base_class を設定。 |
974
|
43
|
100
|
100
|
|
|
161
|
if ($root->{cf_default_base_class} |
|
|
|
66
|
|
|
|
|
975
|
|
|
|
|
|
|
and ($root->{cf_default_base_class} ne $root->{cf_pkg} |
976
|
|
|
|
|
|
|
or $root->{is_loaded})) { |
977
|
|
|
|
|
|
|
# XXX: add_isa じゃなくて ensure_isa だね。 |
978
|
|
|
|
|
|
|
#print STDERR "loading default_base_class $root->{cf_default_base_class}" |
979
|
|
|
|
|
|
|
# . " for dir $dirname\n"; |
980
|
4
|
|
|
|
|
577
|
$root->checked_eval(qq{require $root->{cf_default_base_class}}); |
981
|
4
|
|
|
|
|
11
|
$root->add_isa(my $pkg = $root->get_package($dir) |
982
|
|
|
|
|
|
|
, $root->{cf_default_base_class}); |
983
|
|
|
|
|
|
|
} |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
# RC 読み込みは、最後に |
986
|
43
|
|
|
|
|
386
|
my $rcfile = $loader->catfile($dirname, $loader->RCFILE); |
987
|
43
|
100
|
|
|
|
803
|
if (-r $rcfile) { |
988
|
17
|
|
|
|
|
32
|
my $script = ""; |
989
|
17
|
100
|
|
|
|
50
|
$script .= ";no warnings 'redefine';" if $is_reload; |
990
|
17
|
100
|
|
|
|
74
|
$script .= sprintf(qq{\n#line 1 "%s"\n}, $rcfile) |
991
|
|
|
|
|
|
|
unless $root->{cf_no_lineinfo}; |
992
|
17
|
|
|
|
|
54
|
$script .= untaint_any($loader->checked_read_file($rcfile)); |
993
|
17
|
|
|
|
|
55
|
&YATT::break_rc; |
994
|
|
|
|
|
|
|
$root->with_reloading_flag |
995
|
|
|
|
|
|
|
($is_reload, sub { |
996
|
17
|
|
|
17
|
|
57
|
$root->eval_in_dir($dir, $script); |
997
|
17
|
|
|
|
|
122
|
}); |
998
|
17
|
|
|
|
|
74
|
&YATT::break_after_rc; |
999
|
|
|
|
|
|
|
|
1000
|
17
|
|
|
|
|
63
|
$dir->after_rc_loaded($root); |
1001
|
|
|
|
|
|
|
} |
1002
|
|
|
|
|
|
|
|
1003
|
43
|
|
|
|
|
93
|
$dir; |
1004
|
|
|
|
|
|
|
} |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
sub load_dir { |
1007
|
60
|
|
|
60
|
|
85
|
(my MY $loader, my Root $root, my Dir $dir, my ($dirname)) = @_; |
1008
|
60
|
|
|
|
|
110
|
local *DIR; |
1009
|
60
|
50
|
|
|
|
1321
|
opendir DIR, $dirname or die "Can't open dir '$dirname': $!"; |
1010
|
60
|
|
|
|
|
1207
|
while (my $name = readdir(DIR)) { |
1011
|
542
|
100
|
|
|
|
1404
|
next if $name =~ /^\./; |
1012
|
391
|
|
|
|
|
2227
|
my $path = $loader->catfile($dirname, $name); |
1013
|
|
|
|
|
|
|
# entry を作るだけ。load はしない。→ mtime も、子供側で。 |
1014
|
391
|
100
|
|
|
|
5694
|
if (-d $path) { |
|
|
100
|
|
|
|
|
|
1015
|
96
|
50
|
|
|
|
474
|
next unless $name =~ /^(?:\w|-)+$/; # Not CC for future widechar. |
1016
|
96
|
|
33
|
|
|
679
|
$dir->{Dir}{$name} ||= $loader->{Cache}{$path} |
|
|
|
66
|
|
|
|
|
1017
|
|
|
|
|
|
|
||= $root->createNS(Dir => name => $name |
1018
|
|
|
|
|
|
|
, loadkey => untaint_any($path) |
1019
|
|
|
|
|
|
|
, parent_nsid => $dir->{cf_nsid} |
1020
|
|
|
|
|
|
|
, base_nsid => $dir->{cf_base_nsid} |
1021
|
|
|
|
|
|
|
); |
1022
|
|
|
|
|
|
|
} elsif ($name =~ /^(\w+)\.html?$/) { # XXX: Should allow '-'. |
1023
|
163
|
|
33
|
|
|
1238
|
$dir->{Template}{$1} ||= $loader->{Cache}{$path} |
|
|
|
66
|
|
|
|
|
1024
|
|
|
|
|
|
|
||= $root->createNS(Template => name => $1 |
1025
|
|
|
|
|
|
|
, loadkey => untaint_any($path) |
1026
|
|
|
|
|
|
|
, parent_nsid => $dir->{cf_nsid} |
1027
|
|
|
|
|
|
|
, base_nsid => $dir->{cf_base_nsid} |
1028
|
|
|
|
|
|
|
); |
1029
|
|
|
|
|
|
|
} |
1030
|
|
|
|
|
|
|
} |
1031
|
|
|
|
|
|
|
# XXX: 無くなったファイルの開放は? |
1032
|
60
|
|
|
|
|
1687
|
closedir DIR; |
1033
|
|
|
|
|
|
|
} |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
sub refresh_Template { |
1036
|
158
|
|
|
158
|
|
206
|
(my MY $loader, my Root $root, my Template $tmpl) = @_; |
1037
|
158
|
|
|
|
|
254
|
my $path = $tmpl->{cf_loadkey}; |
1038
|
158
|
100
|
|
|
|
815
|
unless ($loader->is_modified($path, $tmpl->{cf_mtime}{$path})) { |
1039
|
2
|
50
|
|
|
|
8
|
print STDERR "refresh_Template: not modified: $path\n" |
1040
|
|
|
|
|
|
|
if $root->{cf_debug_registry}; |
1041
|
2
|
|
|
|
|
4
|
return; |
1042
|
|
|
|
|
|
|
} |
1043
|
|
|
|
|
|
|
|
1044
|
156
|
50
|
|
|
|
621
|
if (is_tainted($path)) { |
1045
|
0
|
|
|
|
|
0
|
croak "template path $path is tainted"; |
1046
|
|
|
|
|
|
|
} |
1047
|
|
|
|
|
|
|
|
1048
|
156
|
100
|
|
|
|
707
|
if (my $cleaner = $root->can("forget_template")) { |
1049
|
146
|
|
|
|
|
424
|
$cleaner->($root, $tmpl); |
1050
|
|
|
|
|
|
|
} |
1051
|
|
|
|
|
|
|
|
1052
|
156
|
|
|
|
|
361
|
my $is_reload = $tmpl->{cf_age}++; |
1053
|
156
|
|
|
|
|
267
|
undef $tmpl->{is_loaded}; |
1054
|
|
|
|
|
|
|
|
1055
|
156
|
|
|
|
|
372
|
$root->add_isa(my $pkg = $root->get_package($tmpl) |
1056
|
|
|
|
|
|
|
, $root->get_package($tmpl->{cf_parent_nsid})); |
1057
|
156
|
50
|
|
|
|
360
|
foreach my $name (map {defined $_ ? @$_ : ()} |
|
156
|
|
|
|
|
580
|
|
1058
|
|
|
|
|
|
|
$root->{cf_template_global}) { |
1059
|
0
|
|
|
|
|
0
|
*{globref($pkg, $name)} = *{globref($root->{cf_app_prefix}, $name)}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1060
|
|
|
|
|
|
|
} |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
# XXX: There can be a race. (mtime vs open) |
1063
|
156
|
|
|
|
|
666
|
my $parser = $loader->call_type |
1064
|
|
|
|
|
|
|
(Parser => new => untaint => 1 |
1065
|
|
|
|
|
|
|
, registry => $root |
1066
|
|
|
|
|
|
|
, special_entities => $root->{cf_special_entities}); |
1067
|
156
|
|
|
|
|
515
|
local $root->{current_parser}[0] = $parser; |
1068
|
|
|
|
|
|
|
|
1069
|
156
|
50
|
|
|
|
6857
|
open my $fh, '<', $path or die "Can't open $path"; |
1070
|
|
|
|
|
|
|
|
1071
|
156
|
|
|
|
|
917
|
$tmpl->{cf_metainfo} = $parser->configure_metainfo |
1072
|
|
|
|
|
|
|
(nsid => $tmpl->{cf_nsid} |
1073
|
|
|
|
|
|
|
, namespace => $root->namespace |
1074
|
|
|
|
|
|
|
, filename => $path); |
1075
|
|
|
|
|
|
|
|
1076
|
156
|
|
|
|
|
608
|
$tmpl->{tree} = $parser->parse_handle($fh); |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
# XXX: ついでに を解釈. ← parser に前倒し。 |
1079
|
|
|
|
|
|
|
# $root->process_declarations($tmpl); |
1080
|
|
|
|
|
|
|
} |
1081
|
|
|
|
|
|
|
} |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
#======================================== |
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
sub _lined { |
1086
|
0
|
|
|
0
|
|
0
|
my $i = 1; |
1087
|
0
|
|
|
|
|
0
|
my $result; |
1088
|
0
|
|
|
|
|
0
|
foreach my $line (split /\n/, $_[0]) { |
1089
|
0
|
0
|
|
|
|
0
|
if ($line =~ /^\#line (\d+)/) { |
1090
|
0
|
|
|
|
|
0
|
$i = $1; |
1091
|
0
|
|
|
|
|
0
|
$result .= $line . "\n"; |
1092
|
|
|
|
|
|
|
} else { |
1093
|
0
|
|
|
|
|
0
|
$result .= sprintf "% 3d %s\n", $i++, $line; |
1094
|
|
|
|
|
|
|
} |
1095
|
|
|
|
|
|
|
} |
1096
|
|
|
|
|
|
|
$result |
1097
|
0
|
|
|
|
|
0
|
} |
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
1; |