Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java
32287 views
1
/*
2
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package build.tools.dtdbuilder;
27
28
import javax.swing.text.html.parser.*;
29
import java.net.URL;
30
import java.io.IOException;
31
import java.io.InputStream;
32
import java.util.Enumeration;
33
import java.util.Vector;
34
import java.util.Hashtable;
35
import java.util.BitSet;
36
import java.text.MessageFormat;
37
38
import sun.misc.MessageUtils;
39
40
/**
41
* A parser for DTDs. This parser roughly corresponds to the
42
* rules specified in "The SGML Handbook" by Charles F. Goldfarb.
43
* The end result of parsing the stream is a DTD object.
44
*
45
*
46
* @see DTD
47
* @see DTDInputStream
48
* @author Arthur van Hoff
49
*/
50
final
51
class DTDParser implements DTDConstants {
52
DTDBuilder dtd;
53
DTDInputStream in;
54
int ch;
55
char str[] = new char[128];
56
int strpos = 0;
57
int nerrors = 0;
58
59
/**
60
* Report an error.
61
*/
62
void error(String err, String arg1, String arg2, String arg3) {
63
nerrors++;
64
65
String msgParams[] = {arg1, arg2, arg3};
66
67
String str = getSubstProp("dtderr." + err, msgParams);
68
if (str == null) {
69
str = err + "[" + arg1 + "," + arg2 + "," + arg3 + "]";
70
}
71
System.err.println("line " + in.ln + ", dtd " + dtd + ": " + str);
72
}
73
void error(String err, String arg1, String arg2) {
74
error(err, arg1, arg2, "?");
75
}
76
void error(String err, String arg1) {
77
error(err, arg1, "?", "?");
78
}
79
void error(String err) {
80
error(err, "?", "?", "?");
81
}
82
83
private String getSubstProp(String propName, String args[]) {
84
String prop = System.getProperty(propName);
85
86
if (prop == null) {
87
return null;
88
}
89
90
return MessageFormat.format(prop, (Object[])args);
91
}
92
93
/**
94
* Expect a character.
95
*/
96
boolean expect(int c) throws IOException {
97
if (ch != c) {
98
char str[] = {(char)c};
99
error("expected", "'" + new String(str) + "'");
100
return false;
101
}
102
ch = in.read();
103
return true;
104
}
105
106
/**
107
* Add a char to the string buffer.
108
*/
109
void addString(int c) {
110
if (strpos == str.length) {
111
char newstr[] = new char[str.length * 2];
112
System.arraycopy(str, 0, newstr, 0, str.length);
113
str = newstr;
114
}
115
str[strpos++] = (char)c;
116
}
117
118
/**
119
* Get the string which was accumulated in the buffer.
120
* Pos is the starting position of the string.
121
*/
122
String getString(int pos) {
123
char newstr[] = new char[strpos - pos];
124
System.arraycopy(str, pos, newstr, 0, strpos - pos);
125
strpos = pos;
126
return new String(newstr);
127
}
128
129
/**
130
* Get the chars which were accumulated in the buffer.
131
* Pos is the starting position of the string.
132
*/
133
char[] getChars(int pos) {
134
char newstr[] = new char[strpos - pos];
135
System.arraycopy(str, pos, newstr, 0, strpos - pos);
136
strpos = pos;
137
return newstr;
138
}
139
140
/**
141
* Skip spaces. [5] 297:23
142
*/
143
void skipSpace() throws IOException {
144
while (true) {
145
switch (ch) {
146
case '\n':
147
case ' ':
148
case '\t':
149
ch = in.read();
150
break;
151
152
default:
153
return;
154
}
155
}
156
}
157
158
/**
159
* Skip tag spaces (includes comments). [65] 372:1
160
*/
161
void skipParameterSpace() throws IOException {
162
while (true) {
163
switch (ch) {
164
case '\n':
165
case ' ':
166
case '\t':
167
ch = in.read();
168
break;
169
case '-':
170
if ((ch = in.read()) != '-') {
171
in.push(ch);
172
ch = '-';
173
return;
174
}
175
176
in.replace++;
177
while (true) {
178
switch (ch = in.read()) {
179
case '-':
180
if ((ch = in.read()) == '-') {
181
ch = in.read();
182
in.replace--;
183
skipParameterSpace();
184
return;
185
}
186
break;
187
188
case -1:
189
error("eof.arg", "comment");
190
in.replace--;
191
return;
192
}
193
}
194
default:
195
return;
196
}
197
}
198
}
199
200
/**
201
* Parse identifier. Uppercase characters are automatically
202
* folded to lowercase. Returns falsed if no identifier is found.
203
*/
204
@SuppressWarnings("fallthrough")
205
boolean parseIdentifier(boolean lower) throws IOException {
206
switch (ch) {
207
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
208
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
209
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
210
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
211
case 'Y': case 'Z':
212
if (lower) {
213
ch = 'a' + (ch - 'A');
214
}
215
/* fall through */
216
217
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
218
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
219
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
220
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
221
case 'y': case 'z':
222
break;
223
224
default:
225
return false;
226
}
227
228
addString(ch);
229
ch = in.read();
230
parseNameToken(lower);
231
return true;
232
}
233
234
/**
235
* Parses name token. If <code>lower</code> is true, upper case letters
236
* are folded to lower case. Returns falsed if no token is found.
237
*/
238
@SuppressWarnings("fallthrough")
239
boolean parseNameToken(boolean lower) throws IOException {
240
boolean first = true;
241
242
while (true) {
243
switch (ch) {
244
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
245
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
246
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
247
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
248
case 'Y': case 'Z':
249
if (lower) {
250
ch = 'a' + (ch - 'A');
251
}
252
/* fall through */
253
254
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
255
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
256
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
257
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
258
case 'y': case 'z':
259
260
case '0': case '1': case '2': case '3': case '4':
261
case '5': case '6': case '7': case '8': case '9':
262
263
case '.': case '-':
264
addString(ch);
265
ch = in.read();
266
first = false;
267
break;
268
269
default:
270
return !first;
271
}
272
}
273
}
274
275
/**
276
* Parse a list of identifiers.
277
*/
278
Vector<String> parseIdentifierList(boolean lower) throws IOException {
279
Vector<String> elems = new Vector<>();
280
skipSpace();
281
switch (ch) {
282
case '(':
283
ch = in.read();
284
skipParameterSpace();
285
while (parseNameToken(lower)) {
286
elems.addElement(getString(0));
287
skipParameterSpace();
288
if (ch == '|') {
289
ch = in.read();
290
skipParameterSpace();
291
}
292
}
293
expect(')');
294
skipParameterSpace();
295
break;
296
297
default:
298
if (!parseIdentifier(lower)) {
299
error("expected", "identifier");
300
break;
301
}
302
elems.addElement(getString(0));
303
skipParameterSpace();
304
break;
305
}
306
return elems;
307
}
308
309
/**
310
* Parse and Entity reference. Should be called when
311
* a &amp; is encountered. The data is put in the string buffer.
312
* [59] 350:17
313
*/
314
private void parseEntityReference() throws IOException {
315
int pos = strpos;
316
317
if ((ch = in.read()) == '#') {
318
int n = 0;
319
ch = in.read();
320
if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) {
321
addString('#');
322
} else {
323
while ((ch >= '0') && (ch <= '9')) {
324
n = (n * 10) + ch - '0';
325
ch = in.read();
326
}
327
if ((ch == ';') || (ch == '\n')) {
328
ch = in.read();
329
}
330
addString(n);
331
return;
332
}
333
}
334
335
while (true) {
336
switch (ch) {
337
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
338
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
339
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
340
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
341
case 'Y': case 'Z':
342
343
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
344
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
345
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
346
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
347
case 'y': case 'z':
348
349
case '0': case '1': case '2': case '3': case '4':
350
case '5': case '6': case '7': case '8': case '9':
351
352
case '.': case '-':
353
addString(ch);
354
ch = in.read();
355
break;
356
357
default:
358
if (strpos == pos) {
359
addString('&');
360
return;
361
}
362
String nm = getString(pos);
363
Entity ent = dtd.getEntity(nm);
364
if (ent == null) {
365
error("undef.entref" + nm);
366
return;
367
}
368
if ((ch == ';') || (ch == '\n')) {
369
ch = in.read();
370
}
371
char data[] = ent.getData();
372
for (int i = 0 ; i < data.length ; i++) {
373
addString(data[i]);
374
}
375
return;
376
}
377
}
378
}
379
380
/**
381
* Parse an entity declaration.
382
* [101] 394:18
383
* REMIND: external entity type
384
*/
385
private void parseEntityDeclaration() throws IOException {
386
int type = GENERAL;
387
388
skipSpace();
389
if (ch == '%') {
390
ch = in.read();
391
type = PARAMETER;
392
skipSpace();
393
}
394
if (ch == '#') {
395
addString('#');
396
ch = in.read();
397
}
398
if (!parseIdentifier(false)) {
399
error("expected", "identifier");
400
return;
401
}
402
String nm = getString(0);
403
skipParameterSpace();
404
if (parseIdentifier(false)) {
405
String tnm = getString(0);
406
int t = Entity.name2type(tnm);
407
if (t == 0) {
408
error("invalid.arg", "entity type", tnm);
409
} else {
410
type |= t;
411
}
412
skipParameterSpace();
413
}
414
415
if ((ch != '"') && (ch != '\'')) {
416
error("expected", "entity value");
417
skipParameterSpace();
418
if (ch == '>') {
419
ch = in.read();
420
}
421
return;
422
}
423
424
int term = ch;
425
ch = in.read();
426
while ((ch != -1) && (ch != term)) {
427
if (ch == '&') {
428
parseEntityReference();
429
} else {
430
addString(ch & 0xFF);
431
ch = in.read();
432
}
433
}
434
if (ch == term) {
435
ch = in.read();
436
}
437
if (in.replace == 0) {
438
char data[] = getChars(0);
439
dtd.defineEntity(nm, type, data);
440
} else {
441
strpos = 0;
442
}
443
skipParameterSpace();
444
expect('>');
445
}
446
447
/**
448
* Parse content model.
449
* [126] 410:1
450
* REMIND: data tag group
451
*/
452
ContentModel parseContentModel() throws IOException {
453
ContentModel m = null;
454
455
switch (ch) {
456
case '(':
457
ch = in.read();
458
skipParameterSpace();
459
ContentModel e = parseContentModel();
460
461
if (ch != ')') {
462
m = new ContentModel(ch, e);
463
do {
464
ch = in.read();
465
skipParameterSpace();
466
e.next = parseContentModel();
467
if (e.next.type == m.type) {
468
e.next = (ContentModel)e.next.content;
469
}
470
for (; e.next != null ; e = e.next);
471
} while (ch == m.type);
472
} else {
473
m = new ContentModel(',', e);
474
}
475
expect(')');
476
break;
477
478
case '#':
479
ch = in.read();
480
if (parseIdentifier(true)) {
481
m = new ContentModel('*', new ContentModel(dtd.getElement("#" + getString(0))));
482
} else {
483
error("invalid", "content model");
484
}
485
break;
486
487
default:
488
if (parseIdentifier(true)) {
489
m = new ContentModel(dtd.getElement(getString(0)));
490
} else {
491
error("invalid", "content model");
492
}
493
break;
494
}
495
496
switch (ch) {
497
case '?':
498
case '*':
499
case '+':
500
m = new ContentModel(ch, m);
501
ch = in.read();
502
break;
503
}
504
skipParameterSpace();
505
506
return m;
507
}
508
509
/**
510
* Parse element declaration.
511
* [116] 405:6
512
*/
513
void parseElementDeclaration() throws IOException {
514
Vector<String> elems = parseIdentifierList(true);
515
BitSet inclusions = null;
516
BitSet exclusions = null;
517
boolean omitStart = false;
518
boolean omitEnd = false;
519
520
if ((ch == '-') || (ch == 'O')) {
521
omitStart = ch == 'O';
522
ch = in.read();
523
skipParameterSpace();
524
525
if ((ch == '-') || (ch == 'O')) {
526
omitEnd = ch == 'O';
527
ch = in.read();
528
skipParameterSpace();
529
} else {
530
expect('-');
531
}
532
}
533
534
int type = MODEL;
535
ContentModel content = null;
536
if (parseIdentifier(false)) {
537
String nm = getString(0);
538
type = Element.name2type(nm);
539
if (type == 0) {
540
error("invalid.arg", "content type", nm);
541
type = EMPTY;
542
}
543
skipParameterSpace();
544
} else {
545
content = parseContentModel();
546
}
547
548
if ((type == MODEL) || (type == ANY)) {
549
if (ch == '-') {
550
ch = in.read();
551
Vector<String> v = parseIdentifierList(true);
552
exclusions = new BitSet();
553
for (Enumeration<String> e = v.elements() ; e.hasMoreElements() ;) {
554
exclusions.set(dtd.getElement(e.nextElement()).getIndex());
555
}
556
}
557
if (ch == '+') {
558
ch = in.read();
559
Vector<String> v = parseIdentifierList(true);
560
inclusions = new BitSet();
561
for (Enumeration<String> e = v.elements() ; e.hasMoreElements() ;) {
562
inclusions.set(dtd.getElement(e.nextElement()).getIndex());
563
}
564
}
565
}
566
expect('>');
567
568
if (in.replace == 0) {
569
for (Enumeration<String> e = elems.elements() ; e.hasMoreElements() ;) {
570
dtd.defineElement(e.nextElement(), type, omitStart, omitEnd, content, exclusions, inclusions, null);
571
}
572
}
573
}
574
575
/**
576
* Parse an attribute declared value.
577
* [145] 422:6
578
*/
579
void parseAttributeDeclaredValue(AttributeList atts) throws IOException {
580
if (ch == '(') {
581
atts.values = parseIdentifierList(true);
582
atts.type = NMTOKEN;
583
return;
584
}
585
if (!parseIdentifier(false)) {
586
error("invalid", "attribute value");
587
return;
588
}
589
atts.type = AttributeList.name2type(getString(0));
590
skipParameterSpace();
591
if (atts.type == NOTATION) {
592
atts.values = parseIdentifierList(true);
593
}
594
}
595
596
/**
597
* Parse an attribute value specification.
598
* [33] 331:1
599
*/
600
@SuppressWarnings("fallthrough")
601
String parseAttributeValueSpecification() throws IOException {
602
int delim = -1;
603
switch (ch) {
604
case '\'':
605
case '"':
606
delim = ch;
607
ch = in.read();
608
}
609
while (true) {
610
switch (ch) {
611
case -1:
612
error("eof.arg", "attribute value");
613
return getString(0);
614
615
case '&':
616
parseEntityReference();
617
break;
618
619
case ' ':
620
case '\t':
621
case '\n':
622
if (delim == -1) {
623
return getString(0);
624
}
625
addString(' ');
626
ch = in.read();
627
break;
628
629
case '\'':
630
case '"':
631
if (delim == ch) {
632
ch = in.read();
633
return getString(0);
634
}
635
/* fall through */
636
637
default:
638
addString(ch & 0xFF);
639
ch = in.read();
640
break;
641
}
642
}
643
}
644
645
/**
646
* Parse an attribute default value.
647
* [147] 425:1
648
*/
649
void parseAttributeDefaultValue(AttributeList atts) throws IOException {
650
if (ch == '#') {
651
ch = in.read();
652
if (!parseIdentifier(true)) {
653
error("invalid", "attribute value");
654
return;
655
}
656
skipParameterSpace();
657
atts.modifier = AttributeList.name2type(getString(0));
658
if (atts.modifier != FIXED) {
659
return;
660
}
661
}
662
atts.value = parseAttributeValueSpecification();
663
skipParameterSpace();
664
}
665
666
/**
667
* Parse an attribute definition list declaration.
668
* [141] 420:15
669
* REMIND: associated notation name
670
*/
671
void parseAttlistDeclaration() throws IOException {
672
Vector<String> elems = parseIdentifierList(true);
673
AttributeList attlist = null, atts = null;
674
675
while (parseIdentifier(true)) {
676
if (atts == null) {
677
attlist = atts = new AttributeList(getString(0));
678
} else {
679
atts.next = new AttributeList(getString(0));
680
atts = atts.next;
681
}
682
skipParameterSpace();
683
parseAttributeDeclaredValue(atts);
684
parseAttributeDefaultValue(atts);
685
686
if ((atts.modifier == IMPLIED) && (atts.values != null) && (atts.values.size() == 1)) {
687
atts.value = (String)atts.values.elementAt(0);
688
}
689
}
690
691
expect('>');
692
693
if (in.replace == 0) {
694
for (Enumeration<String> e = elems.elements() ; e.hasMoreElements() ;) {
695
dtd.defineAttributes(e.nextElement(), attlist);
696
}
697
}
698
}
699
700
/**
701
* Parse an ignored section until ]]> is encountered.
702
*/
703
void parseIgnoredSection() throws IOException {
704
int depth = 1;
705
in.replace++;
706
while (true) {
707
switch (ch) {
708
case '<':
709
if ((ch = in.read()) == '!') {
710
if ((ch = in.read()) == '[') {
711
ch = in.read();
712
depth++;
713
}
714
}
715
break;
716
case ']':
717
if ((ch = in.read()) == ']') {
718
if ((ch = in.read()) == '>') {
719
ch = in.read();
720
if (--depth == 0) {
721
in.replace--;
722
return;
723
}
724
}
725
}
726
break;
727
case -1:
728
error("eof");
729
in.replace--;
730
return;
731
732
default:
733
ch = in.read();
734
break;
735
}
736
}
737
}
738
739
/**
740
* Parse a marked section declaration.
741
* [93] 391:13
742
* REMIND: deal with all status keywords
743
*/
744
void parseMarkedSectionDeclaration() throws IOException {
745
ch = in.read();
746
skipSpace();
747
if (!parseIdentifier(true)) {
748
error("expected", "section status keyword");
749
return;
750
}
751
String str = getString(0);
752
skipSpace();
753
expect('[');
754
if ("ignore".equals(str)) {
755
parseIgnoredSection();
756
} else {
757
if (!"include".equals(str)) {
758
error("invalid.arg", "section status keyword", str);
759
}
760
parseSection();
761
expect(']');
762
expect(']');
763
expect('>');
764
}
765
}
766
767
/**
768
* Parse an external identifier
769
* [73] 379:1
770
*/
771
void parseExternalIdentifier() throws IOException {
772
if (parseIdentifier(false)) {
773
String id = getString(0);
774
skipParameterSpace();
775
776
if (id.equals("PUBLIC")) {
777
if ((ch == '\'') || (ch == '"')) {
778
parseAttributeValueSpecification();
779
} else {
780
error("expected", "public identifier");
781
}
782
skipParameterSpace();
783
} else if (!id.equals("SYSTEM")) {
784
error("invalid", "external identifier");
785
}
786
if ((ch == '\'') || (ch == '"')) {
787
parseAttributeValueSpecification();
788
}
789
skipParameterSpace();
790
}
791
}
792
793
/**
794
* Parse document type declaration.
795
* [110] 403:1
796
*/
797
void parseDocumentTypeDeclaration() throws IOException {
798
skipParameterSpace();
799
if (!parseIdentifier(true)) {
800
error("expected", "identifier");
801
} else {
802
skipParameterSpace();
803
}
804
strpos = 0;
805
parseExternalIdentifier();
806
807
if (ch == '[') {
808
ch = in.read();
809
parseSection();
810
expect(']');
811
skipParameterSpace();
812
}
813
expect('>');
814
}
815
816
/**
817
* Parse a section of the input upto EOF or ']'.
818
*/
819
@SuppressWarnings("fallthrough")
820
void parseSection() throws IOException {
821
while (true) {
822
switch (ch) {
823
case ']':
824
return;
825
826
case '<':
827
switch (ch = in.read()) {
828
case '!':
829
switch (ch = in.read()) {
830
case '[':
831
parseMarkedSectionDeclaration();
832
break;
833
834
case '-':
835
skipParameterSpace();
836
expect('>');
837
break;
838
839
default:
840
if (parseIdentifier(true)) {
841
String str = getString(0);
842
843
if (str.equals("element")) {
844
parseElementDeclaration();
845
846
} else if (str.equals("entity")) {
847
parseEntityDeclaration();
848
849
} else if (str.equals("attlist")) {
850
parseAttlistDeclaration();
851
852
} else if (str.equals("doctype")) {
853
parseDocumentTypeDeclaration();
854
855
} else if (str.equals("usemap")) {
856
error("ignoring", "usemap");
857
while ((ch != -1) && (ch != '>')) {
858
ch = in.read();
859
}
860
expect('>');
861
} else if (str.equals("shortref")) {
862
error("ignoring", "shortref");
863
while ((ch != -1) && (ch != '>')) {
864
ch = in.read();
865
}
866
expect('>');
867
} else if (str.equals("notation")) {
868
error("ignoring", "notation");
869
while ((ch != -1) && (ch != '>')) {
870
ch = in.read();
871
}
872
expect('>');
873
} else {
874
error("markup");
875
}
876
} else {
877
error("markup");
878
while ((ch != -1) && (ch != '>')) {
879
ch = in.read();
880
}
881
expect('>');
882
}
883
}
884
}
885
break;
886
887
case -1:
888
return;
889
890
default:
891
char str[] = {(char)ch};
892
error("invalid.arg", "character", "'" + new String(str) + "' / " + ch);
893
/* fall through */
894
895
case ' ':
896
case '\t':
897
case '\n':
898
ch = in.read();
899
break;
900
}
901
}
902
}
903
904
/**
905
* Parse a DTD.
906
* @return the dtd or null if an error occurred.
907
*/
908
DTD parse(InputStream in, DTDBuilder dtd) {
909
try {
910
this.dtd = dtd;
911
this.in = new DTDInputStream(in, dtd);
912
913
long tm = System.currentTimeMillis();
914
ch = this.in.read();
915
parseSection();
916
917
if (ch != -1) {
918
error("premature");
919
}
920
921
tm = System.currentTimeMillis() - tm;
922
System.err.println("[Parsed DTD " + dtd + " in " + tm + "ms]");
923
} catch (IOException e) {
924
error("ioexception");
925
} catch (Exception e) {
926
error("exception", e.getClass().getName(), e.getMessage());
927
e.printStackTrace();
928
} catch (ThreadDeath e) {
929
error("terminated");
930
}
931
return (nerrors > 0) ? null : dtd;
932
}
933
}
934
935