File Coverage

blib/lib/SGML/DTDParse/Catalog.pm
Criterion Covered Total %
statement 6 222 2.7
branch 0 102 0.0
condition 0 15 0.0
subroutine 2 14 14.2
pod 0 11 0.0
total 8 364 2.2


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2              
3             package SGML::DTDParse::Catalog;
4              
5 1     1   5 use strict;
  1         1  
  1         36  
6 1     1   5 use vars qw($VERSION $CVS);
  1         2  
  1         3418  
7              
8             $VERSION = do { my @r=(q$Revision: 2.1 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r };
9             $CVS = '$Id: Catalog.pm,v 2.1 2005/07/02 23:51:18 ehood Exp $ ';
10              
11             sub new {
12 0     0 0   my $type = shift;
13 0           my %param = @_;
14 0   0       my $class = ref($type) || $type;
15 0           my $self = bless {}, $class;
16              
17 0           $self->{'DIRECTIVE'} = [];
18 0           $self->{'FILES'} = {};
19 0   0       $self->{'VERBOSE'} = $param{'Verbose'} || $param{'Debug'};
20 0           $self->{'DEBUG'} = $param{'Debug'};
21              
22 0           my $catfiles = $main::ENV{'SGML_CATALOG_FILES'};
23 0           my @files = ();
24              
25 0 0         if ($catfiles =~ /;/) {
26 0           @files = split(/;/, $catfiles);
27             } else {
28 0           @files = split(/:/, $catfiles);
29             }
30              
31 0           foreach my $file (@files) {
32 0           $self->parse($file);
33             }
34              
35 0           return $self;
36             }
37              
38             sub verbose {
39 0     0 0   my $self = shift;
40 0           my $val = shift;
41 0           my $verb = $self->{'VERBOSE'};
42              
43 0 0         $self->{'VERBOSE'} = $val if defined($val);
44              
45 0           return $verb;
46             }
47              
48             sub debug {
49 0     0 0   my $self = shift;
50 0           my $val = shift;
51 0           my $dbg = $self->{'DEBUG'};
52              
53 0 0         $self->{'DEBUG'} = $val if defined($val);
54              
55 0           return $dbg;
56             }
57              
58             sub parse {
59 0     0 0   my $self = shift;
60 0           my $file = shift;
61              
62 0 0         return 2 if $self->{'FILES'}->{$file};
63              
64 0           $self->{'FILES'}->{$file} = 1;
65              
66 0           return $self->load_catalog($file);
67             }
68              
69             sub _find {
70 0     0     my $self = shift;
71 0           my $type = shift;
72 0           my $key = shift;
73              
74 0           foreach my $dir (@{$self->{'DIRECTIVE'}}) {
  0            
75 0           my %hash = %{$dir};
  0            
76 0 0 0       return $hash{'FILE'} if $hash{'TYPE'} = $type && $hash{$type} eq $key;
77             }
78              
79 0           return undef;
80             }
81              
82             sub system_map {
83 0     0 0   my($self, $sysid) = @_;
84              
85 0   0       return $self->_find('SYSID', $sysid) || $sysid;
86             }
87              
88             sub public_map {
89 0     0 0   my($self, $pubid) = @_;
90              
91 0           $pubid =~ s/\s+/ /g;
92 0           return $self->_find('PUBID', $pubid);
93             }
94              
95             sub reverse_public_map {
96 0     0 0   my($self, $filename) = @_;
97              
98 0           $filename =~ s/\\/\//g; # canonical path separator
99              
100 0           foreach my $dir (@{$self->{'DIRECTIVE'}}) {
  0            
101 0           my %hash = %{$dir};
  0            
102 0           my $key = $hash{'TYPE'};
103 0 0         next if $key ne 'PUBID';
104              
105             # print "$key\n";
106             # print $hash{$key}, "\n";
107             # print $hash{'FILE'}, "\n";
108             # print "\t$filename\n\n";
109              
110 0 0         return $hash{$key} if $hash{'FILE'} eq $filename;
111             }
112              
113 0           return undef;
114             }
115              
116             sub declaration {
117 0     0 0   my($self, $pubid) = @_;
118              
119 0           $pubid =~ s/\s+/ /g;
120 0           foreach my $dir (@{$self->{'DIRECTIVE'}}) {
  0            
121 0           my %hash = %{$dir};
  0            
122              
123 0 0 0       return $hash{'FILE'}
124             if $hash{'TYPE'} eq 'DTDDECL' && $hash{'DTDDECL'} eq $pubid;
125              
126 0 0         return $hash{'FILE'}
127             if $hash{'TYPE'} eq 'SGMLDECL';
128             }
129              
130 0           return undef;
131             }
132              
133             sub load_catalog {
134 0     0 0   my $self = shift;
135 0           my $catalog = shift;
136 0           my $drive = "";
137 0           my $dir = "";
138 0           my @directives = ();
139 0           my $count = 0;
140 0           local (*F, $_);
141              
142 0 0         print "Reading $catalog...\n" if $self->verbose();
143              
144 0           $catalog =~ s/\\/\//g; # canonical path separators
145 0 0         $dir = $1 if $catalog =~ /^(.*)\/[^\/]+$/;
146 0 0         $drive = substr($dir, 0, 2) if substr($dir, 1, 1) eq ':';
147              
148 0 0         if (!open(F, $catalog)) {
149 0 0         print "Failed to open $catalog...\n" if $self->verbose();
150 0           return;
151             }
152              
153 0           read (F, $_, -s $catalog);
154 0           close (F);
155              
156 0           while (/^\s*(\S+)/s) {
157 0           my $keyword = uc($1);
158 0           $_ = $';
159              
160 0 0         if ($keyword eq 'OVERRIDE') {
161 0           $_ =~ /^\s*\S+/s;
162 0           $_ = $';
163 0           next;
164             }
165              
166 0 0         if ($keyword eq 'PUBLIC') {
167 0           my($pubid, $filename);
168 0 0         if (/^\s*[\"\']/s) {
169 0           ($pubid, $_) = &parse_quoted_string("CATALOG", $_);
170             } else {
171 0           /^\s*(\S+)/s;
172 0           $pubid = $1;
173 0           $_ = $';
174             }
175              
176 0 0         if (/^\s*[\"\']/s) {
177 0           ($filename, $_) = &parse_quoted_string("CATALOG", $_);
178             } else {
179 0           /^\s*(\S+)/s;
180 0           $filename = $1;
181 0           $_ = $';
182             }
183              
184 0 0         if ($filename =~ /^[a-z]:/s) {
    0          
185             # nop
186             } elsif ($filename =~ /^[\\\/]/) {
187 0           $filename = $drive . $filename;
188             } else {
189 0 0         $filename = $dir . "/" . $filename if $dir ne "";
190             }
191              
192 0           $directives[$count] = {};
193 0           $directives[$count]->{'TYPE'} = 'PUBID';
194 0           $directives[$count]->{'PUBID'} = $pubid;
195 0           $directives[$count]->{'FILE'} = $filename;
196 0           $count++;
197              
198             # print "\"$pubid\" = \"$filename\"\n";
199              
200 0           next;
201             }
202              
203 0 0         if ($keyword eq 'SYSTEM') {
204 0           my($sysid, $filename);
205 0 0         if (/^\s*[\"\']/s) {
206 0           ($sysid, $_) = &parse_quoted_string("CATALOG", $_);
207             } else {
208 0           /^\s*(\S+)/s;
209 0           $sysid = $1;
210 0           $_ = $';
211             }
212              
213 0 0         if (/^\s*[\"\']/s) {
214 0           ($filename, $_) = &parse_quoted_string("CATALOG", $_);
215             } else {
216 0           /^\s*(\S+)/s;
217 0           $filename = $1;
218 0           $_ = $';
219             }
220              
221 0 0         if ($filename =~ /^[a-z]:/s) {
    0          
222             # nop
223             } elsif ($filename =~ /^[\\\/]/) {
224 0           $filename = $drive . $filename;
225             } else {
226 0 0         $filename = $dir . "/" . $filename if $dir ne "";
227             }
228              
229 0           $directives[$count] = {};
230 0           $directives[$count]->{'TYPE'} = 'SYSID';
231 0           $directives[$count]->{'SYSID'} = $sysid;
232 0           $directives[$count]->{'FILE'} = $filename;
233 0           $count++;
234              
235 0           next;
236             }
237              
238 0 0         if ($keyword eq 'DTDDECL') {
239 0           my($pubid, $filename);
240 0 0         if (/^\s*[\"\']/s) {
241 0           ($pubid, $_) = &parse_quoted_string("CATALOG", $_);
242             } else {
243 0           /^\s*(\S+)/s;
244 0           $pubid = $1;
245 0           $_ = $';
246             }
247              
248 0 0         if (/^\s*[\"\']/s) {
249 0           ($filename, $_) = &parse_quoted_string("CATALOG", $_);
250             } else {
251 0           /^\s*(\S+)/s;
252 0           $filename = $1;
253 0           $_ = $';
254             }
255              
256 0 0         if ($filename =~ /^[a-z]:/s) {
    0          
257             # nop
258             } elsif ($filename =~ /^[\\\/]/) {
259 0           $filename = $drive . $filename;
260             } else {
261 0 0         $filename = $dir . "/" . $filename if $dir ne "";
262             }
263              
264 0           $directives[$count] = {};
265 0           $directives[$count]->{'TYPE'} = 'DTDDECL';
266 0           $directives[$count]->{'DTDDECL'} = $pubid;
267 0           $directives[$count]->{'FILE'} = $filename;
268 0           $count++;
269              
270 0           next;
271             }
272              
273 0 0         if ($keyword eq 'SGMLDECL') {
274 0           my($filename);
275              
276 0 0         if (/^\s*[\"\']/s) {
277 0           ($filename, $_) = &parse_quoted_string("CATALOG", $_);
278             } else {
279 0           /^\s*(\S+)/s;
280 0           $filename = $1;
281 0           $_ = $';
282             }
283              
284 0 0         if ($filename =~ /^[a-z]:/s) {
    0          
285             # nop
286             } elsif ($filename =~ /^[\\\/]/) {
287 0           $filename = $drive . $filename;
288             } else {
289 0 0         $filename = $dir . "/" . $filename if $dir ne "";
290             }
291              
292 0           $directives[$count] = {};
293 0           $directives[$count]->{'TYPE'} = 'SGMLDECL';
294 0           $directives[$count]->{'SGMLDECL'} = 'SGMLDECL';
295 0           $directives[$count]->{'FILE'} = $filename;
296 0           $count++;
297              
298 0           next;
299             }
300              
301 0 0         if ($keyword eq 'DOCTYPE') {
302 0           my($tag, $filename);
303 0 0         if (/^\s*[\"\']/s) {
304 0           ($tag, $_) = &parse_quoted_string("CATALOG", $_);
305             } else {
306 0           /^\s*(\S+)/s;
307 0           $tag = $1;
308 0           $_ = $';
309             }
310              
311 0 0         if (/^\s*[\"\']/s) {
312 0           ($filename, $_) = &parse_quoted_string("CATALOG", $_);
313             } else {
314 0           /^\s*(\S+)/s;
315 0           $filename = $1;
316 0           $_ = $';
317             }
318              
319 0 0         if ($filename =~ /^[a-z]:/s) {
    0          
320             # nop
321             } elsif ($filename =~ /^[\\\/]/) {
322 0           $filename = $drive . $filename;
323             } else {
324 0 0         $filename = $dir . "/" . $filename if $dir ne "";
325             }
326              
327             # nop...
328 0           next;
329             }
330              
331 0 0         if ($keyword =~ /^\-\-/) {
332 0           $_ = $keyword . $_;
333 0           /^--.*?--/s;
334 0           $_ = $';
335 0           next;
336             }
337              
338 0           die "Don't know how to parse CATALOG keyword: $keyword\n";
339             }
340              
341             # now populate the real array; making sure that SGMLDECL goes to
342             # the end of the array
343              
344 0           foreach my $dir (@directives) {
345 0           my %hash = %{$dir};
  0            
346 0 0         next if $hash{'TYPE'} eq 'SGMLDECL';
347 0           push(@{$self->{'DIRECTIVE'}}, $dir);
  0            
348             }
349              
350 0           foreach my $dir (@directives) {
351 0           my %hash = %{$dir};
  0            
352 0 0         next if $hash{'TYPE'} ne 'SGMLDECL';
353 0           push(@{$self->{'DIRECTIVE'}}, $dir);
  0            
354             }
355              
356 0           return 1;
357             }
358              
359             sub strip_comment {
360 0     0 0   my($text) = shift;
361 0           while ($text =~ /^\s*--.*?--/s) {
362 0           $text = $';
363             }
364 0           return $text;
365             }
366              
367             sub parse_quoted_string {
368 0     0 0   my($decl, $entity) = @_;
369 0           my($text);
370              
371 0 0         if ($entity =~ /^\s*\"/s) {
    0          
372 0 0         die "Unparseable text: $decl\n" if $entity !~ /^\s*\"(.*?)\"/s;
373 0           $text = $1;
374 0           $entity = &strip_comment($');
375             } elsif ($entity =~ /^\s*\'/s) {
376 0 0         die "Unparseable text: $decl\n" if $entity !~ /^\s*\'(.*?)\'/s;
377 0           $text = $1;
378 0           $entity = &strip_comment($');
379             } else {
380 0           die "Unexpected text: $decl\n";
381             }
382              
383 0           return ($text, $entity);
384             }
385              
386             1;