source: proto/parabix2/compiled/xmldecl.c @ 424

Last change on this file since 424 was 424, checked in by lindanl, 9 years ago

Files for compiled xmlwf prototype

File size: 8.2 KB
Line 
1/*  xmldecl.c - Parsing XML and Text Declarations.
2    Copyright (c) 2008, Robert D. Cameron.
3    Licensed to the public under the Open Software License 3.0.
4    Licensed to International Characters, Inc., under the Academic
5    Free License 3.0.
6
7*/
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/types.h>
12
13#include "xmldecl.h"
14#include "xml_error.h"
15#include "multiliteral.h"
16#include "bytelex.h"
17
18
19Entity_Info::Entity_Info() {
20        encoding = NULL;
21}
22Entity_Info::~Entity_Info() {
23        delete [] encoding;
24}
25
26/* Signature-based character set family detection in accord with
27   Appendix F of the XML 1.0 and 1.1 specifications. */
28
29/* These definitions use b2int16 to determine appropriate doublebyte
30   values based on endianness of the underlying architecture. */
31static const int x0000 = b2int16<0x00, 0x00>::value;
32static const int xFEFF = b2int16<0xFE, 0xFF>::value;
33static const int xFFFE = b2int16<0xFF, 0xFE>::value;
34static const int x003C = b2int16<0x00, 0x3C>::value;
35static const int x3C00 = b2int16<0x3C, 0x00>::value;
36static const int x4C6F = b2int16<0x4C, 0x6F>::value;
37static const int xA794 = b2int16<0xA7, 0x94>::value;
38static const int xEFBE = b2int16<0xEF, 0xBE>::value;
39
40void Entity_Info::AnalyzeSignature(unsigned char * signature) {
41        uint16_t * XML_dbl_byte = (uint16_t *) signature;
42        switch (XML_dbl_byte[0]) {
43                case x0000:
44                        switch (XML_dbl_byte[1]) {
45                                case xFEFF: set_charset_family(ASCII, QuadByte, BigEndian, 1);break;
46                                case xFFFE: set_charset_family(ASCII, QuadByte, Unusual_2143, 1);break;
47                                case x3C00: set_charset_family(ASCII, QuadByte, Unusual_2143, 0);break;
48                                default: set_charset_family(ASCII, QuadByte, BigEndian, 0);
49                        }
50                        break;
51                case xFEFF:
52                        if (XML_dbl_byte[1] == x0000)
53                                set_charset_family(ASCII, QuadByte, Unusual_3412, 1);
54                        else set_charset_family(ASCII, DoubleByte, BigEndian, 1);
55                        break;
56                case xFFFE:
57                        if (XML_dbl_byte[1] == x0000)
58                                set_charset_family(ASCII, QuadByte, LittleEndian, 1);
59                        else set_charset_family(ASCII, DoubleByte, LittleEndian, 1);
60                        break;
61                case x003C:
62                        if (XML_dbl_byte[1] == x0000)
63                                set_charset_family(ASCII, QuadByte, Unusual_3412, 0);
64                        else set_charset_family(ASCII, DoubleByte, BigEndian, 0);
65                        break;
66                case x3C00:
67                        if (XML_dbl_byte[1] == x0000)
68                                set_charset_family(ASCII, QuadByte, LittleEndian, 0);
69                        else set_charset_family(ASCII, DoubleByte, LittleEndian, 0);
70                        break;
71                case x4C6F:
72                        if (XML_dbl_byte[1] == xA794)
73                                set_charset_family(EBCDIC, SingleByte, BigEndian, 0);
74                        else set_charset_family(ASCII, SingleByte, BigEndian, 0);
75                        break;
76                case xEFBE:
77                        if (signature[2] == 0xBF)
78                                set_charset_family(ASCII, SingleByte, BigEndian, 3);
79                        else set_charset_family(ASCII, SingleByte, BigEndian, 0);
80                        break;
81                default:
82                        set_charset_family(ASCII, SingleByte, BigEndian, 0);
83        }
84}
85void Entity_Info::set_charset_family(CodeUnit_Base C, CodeUnit_Size S, CodeUnit_ByteOrder O, int B){
86                code_unit_base = C;
87                code_unit_size = S;
88                byte_order = O;
89                BOM_units = B;
90 }
91
92
93template <CodeUnit_Base C>
94XML_Decl_Parser<C>::XML_Decl_Parser(unsigned char * bytes){
95        buffer_base_pos = 0;
96        x8data = bytes;
97}
98
99template <CodeUnit_Base C>
100XML_Decl_Parser<C>::~XML_Decl_Parser(){
101}
102
103template <CodeUnit_Base C>
104inline void XML_Decl_Parser<C>::DeclError() {
105        DeclarationError(AbsPos());
106}
107
108template <CodeUnit_Base C>
109inline int XML_Decl_Parser<C>::AbsPos() const {
110        return  buffer_base_pos + buffer_rel_pos;
111}
112
113template <CodeUnit_Base C>
114inline unsigned char * XML_Decl_Parser<C>::cur() const {
115        return &x8data[buffer_rel_pos];
116}
117
118template <CodeUnit_Base C>
119inline void XML_Decl_Parser<C>::Advance(int n) {
120        buffer_rel_pos += n;
121}
122
123template <CodeUnit_Base C>
124inline void XML_Decl_Parser<C>::Scan_WS() {
125        while (at_WhiteSpace_10<C>(cur())) Advance(1);
126}
127
128template <CodeUnit_Base C>
129inline void XML_Decl_Parser<C>::ScanToQuote() {
130        while (!AtQuote<C>(cur())) buffer_rel_pos+=1;
131}
132
133template <CodeUnit_Base C>
134inline void XML_Decl_Parser<C>::ParseVersion(Entity_Info & e) {
135        /* Skip "version" */
136        Advance(7);
137        Scan_WS();
138        if (!AtChar<C,'='>(cur())) DeclError();
139        Advance(1);
140        Scan_WS();
141        if (at_1_0<C>(cur())) e.version = XML_1_0;
142        else if (at_1_1<C>(cur())) e.version = XML_1_1;
143        else DeclError();
144        Advance(5);
145}
146
147template <CodeUnit_Base C>
148inline void XML_Decl_Parser<C>::ParseEncoding(Entity_Info & e) {
149        /* Skip "encoding" */
150        Advance(8);
151        e.has_encoding_decl = true;
152        Scan_WS();
153        if (!AtChar<C,'='>(cur())) DeclError();
154        Advance(1);
155        Scan_WS();
156        if (AtQuote<C>(cur())) {
157                unsigned char quoteCh = cur()[0];
158                Advance(1);
159                int start_pos = AbsPos();
160                ScanToQuote();
161                if (cur()[0] != quoteCh) DeclError();
162                int lgth = AbsPos() - start_pos;
163                e.encoding = new unsigned char[lgth + 1];
164                memcpy(e.encoding, &x8data[start_pos-buffer_base_pos], lgth);
165                e.encoding[lgth] = '\0';
166        }
167        else DeclError();
168        Advance(1);
169}
170
171template <CodeUnit_Base C>
172inline void XML_Decl_Parser<C>::ParseStandalone(Entity_Info & e) {
173        /* Skip "standalone" */
174        Advance(10);
175        Scan_WS();
176        if (!AtChar<C,'='>(cur())) DeclError();
177        Advance(1);
178        Scan_WS();
179        if (at_yes<C>(cur())) {Advance(5); e.standalone = Standalone_yes;}
180        else if (at_no<C>(cur())) {Advance(4); e.standalone = Standalone_no;}
181        else DeclError();
182}
183
184template <CodeUnit_Base C>
185void XML_Decl_Parser<C>::ReadXMLInfo(Entity_Info & e) {
186        e.version = no_XML_version_value;
187        e.has_encoding_decl = false;
188        e.standalone = Standalone_no_value;
189        buffer_rel_pos = e.BOM_units;
190        // It is possible that there is no XML declaration.
191        if (!at_XmlDecl_start<C>(cur())) {
192                e.content_start = AbsPos();
193                return;
194        }
195        // Otherwise, the XML declaration exists and must have
196        // at least version information.
197        Advance(6);
198        Scan_WS();
199        if (!at_version<C>(cur())) DeclError();
200        ParseVersion(e);
201        if (at_PI_End<C>(cur())) {
202                e.content_start = AbsPos()+2;
203                return;
204        }
205        if (!at_WhiteSpace_10<C>(cur())) DeclError();
206        Scan_WS();
207        if (at_encoding<C>(cur())) {
208                ParseEncoding(e);
209                if (at_PI_End<C>(cur())) {
210                        e.content_start = AbsPos()+2;
211                        return;
212                }
213                if (!at_WhiteSpace_10<C>(cur())) DeclError();
214                Scan_WS();
215        }
216        if (at_standalone<C>(cur())) {
217                ParseStandalone(e);
218                Scan_WS();
219        }
220        if (!at_PI_End<C>(cur())) DeclError();
221        e.content_start = AbsPos()+2;
222}
223
224// Similar to reading the XML_declaration of the document entity,
225// ReadTextDeclaration reads the text declaration of an external
226// parsed entity.
227
228template <CodeUnit_Base C>
229void XML_Decl_Parser<C>::ReadTextDeclaration(Entity_Info & e) {
230        e.version = no_XML_version_value;
231        e.has_encoding_decl = false;
232        e.standalone = Standalone_no_value;
233        buffer_rel_pos = e.BOM_units;
234        // It is possible that there is no text declaration.
235        if (!at_XmlDecl_start<C>(cur())) {
236                e.content_start = AbsPos();
237                return;
238        }
239        // Otherwise, the text declaration exists and may have
240        // version information.
241        Advance(6);
242        Scan_WS();
243        if (at_version<C>(cur())) {
244                ParseVersion(e);
245                // Must have whitespace character before encoding declaration.
246                if (!at_WhiteSpace_10<C>(cur())) DeclError();
247                Scan_WS();
248        }
249        if (!at_encoding<C>(cur())) DeclError();
250        ParseEncoding(e);
251        Scan_WS();
252        if (!at_PI_End<C>(cur())) DeclError();
253        e.content_start = AbsPos()+2;
254}
255
256template <CodeUnit_Base C>
257void XML_Decl_Parser<C>::ReadXMLorTextDecl(Entity_Info & e) {
258        e.version = no_XML_version_value;
259        e.has_encoding_decl = false;
260        e.standalone = Standalone_no_value;
261        buffer_rel_pos = e.BOM_units;
262        // It is possible that there is no XML or text declaration.
263        if (!at_XmlDecl_start<C>(cur())) {
264                e.content_start = AbsPos();
265                return;
266        }
267        // Otherwise, the XML or text declaration exists and may have
268        // version information.
269        Advance(6);
270        Scan_WS();
271        if (at_version<C>(cur())) {
272                ParseVersion(e);
273                if (at_PI_End<C>(cur())) {
274                        e.content_start = AbsPos()+2;
275                        return;
276                }
277                if (!at_WhiteSpace_10<C>(cur())) DeclError();
278                Scan_WS();
279                if (at_encoding<C>(cur())) {
280                        ParseEncoding(e);
281                        if (at_PI_End<C>(cur())) {
282                                e.content_start = AbsPos()+2;
283                                return;
284                        }
285                        if (!at_WhiteSpace_10<C>(cur())) DeclError();
286                        Scan_WS();
287                }
288                if (at_standalone<C>(cur())) {
289                        ParseStandalone(e);
290                        Scan_WS();
291                }
292        }
293        else {  // Without version, we can only have a text declaration,
294                // in which case an encoding spec is required.
295                if (!at_encoding<C>(cur())) DeclError();
296                ParseEncoding(e);
297                Scan_WS();
298                // No standalone spec is allowed in a text declaration.
299        }
300        if (!at_PI_End<C>(cur())) DeclError(); 
301        e.content_start = AbsPos()+2;
302}
Note: See TracBrowser for help on using the repository browser.