summaryrefslogtreecommitdiff
path: root/messenger/XML_Parser
diff options
context:
space:
mode:
Diffstat (limited to 'messenger/XML_Parser')
-rw-r--r--messenger/XML_Parser/README15
-rw-r--r--messenger/XML_Parser/asm-xml.h162
-rw-r--r--messenger/XML_Parser/friends.xml10
-rw-r--r--messenger/XML_Parser/main.c160
-rw-r--r--messenger/XML_Parser/obj/elf/asm-xml.obin0 -> 19361 bytes
-rw-r--r--messenger/XML_Parser/obj/mach-o/asm-xml.obin0 -> 19326 bytes
-rw-r--r--messenger/XML_Parser/obj/ms-coff/asm-xml.objbin0 -> 19421 bytes
-rw-r--r--messenger/XML_Parser/src/asm-xml.asm5594
-rw-r--r--messenger/XML_Parser/src/elf.asm19
-rw-r--r--messenger/XML_Parser/src/win32.asm19
10 files changed, 5979 insertions, 0 deletions
diff --git a/messenger/XML_Parser/README b/messenger/XML_Parser/README
new file mode 100644
index 00000000..9ff914ed
--- /dev/null
+++ b/messenger/XML_Parser/README
@@ -0,0 +1,15 @@
1============================================================
2=============Adding the Library to Your Project=============
3============================================================
4
5Include the "asm-xml.h" file in your source file.
6
7Link your project with the AsmXml object file.
8 ~ ~ ~ ~
9Here are some tips to use it with various configurations:
10 MSVC 6: Add the \ms-coff\asm-xml.obj file to your project.
11 MinGW: Link your project with \ms-coff\asm-xml.obj.
12 Linux: Link your project with /elf/asm-xml.o.
13 Mac OS X: Link your project with /mach-o/asm-xml.o.
14
15============================================================
diff --git a/messenger/XML_Parser/asm-xml.h b/messenger/XML_Parser/asm-xml.h
new file mode 100644
index 00000000..38dcb639
--- /dev/null
+++ b/messenger/XML_Parser/asm-xml.h
@@ -0,0 +1,162 @@
1/****************************************************************************
2* *
3* asm-xml.h *
4* *
5* Copyright (C) 2007-08 Marc Kerbiquet *
6* *
7****************************************************************************/
8
9#ifdef WIN32
10 #define ACC __cdecl
11#else
12 #define ACC
13#endif
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
19//-----------------------------------------------------------------------------
20// Error Codes
21//-----------------------------------------------------------------------------
22#define RC_OK 0 // everything is ok
23#define RC_MEMORY 1 // out of memory
24
25#define RC_EMPTY_NAME 10 // name empty or not defined
26#define RC_ATTR_DEFINED 11 // attribute already defined
27#define RC_ELEM_DEFINED 12 // element already defined
28#define RC_SCHEMA_EMPTY 13 // schema does not contains a document
29#define RC_DOCUMENT_DEFINED 14 // schema contains more than one document
30#define RC_UNDEFINED_CLASS 15 // can't find collection in reference
31#define RC_UNDEFINED_GROUP 16 // can't find a group in include
32#define RC_INVALID_ID 17 // id is not a valid number
33#define RC_INVALID_IGNORE 18 // ignore is not 'yes' or 'no'
34
35#define RC_INVALID_ENTITY_REFERENCE 20 // must be amp, quot, lt, gt, or apos
36#define RC_UNEXPECTED_END 21 // found last char too early
37#define RC_INVALID_CHAR 22 // wrong char
38#define RC_OVERFLOW 23 // number to big in char reference
39#define RC_NO_START_TAG 24 // xml does not start with a tag
40#define RC_TAG_MISMATCH 25 // invalid close tag
41#define RC_INVALID_TAG 26 // invalid root element
42#define RC_INVALID_ATTRIBUTE 27 // unknown attribute
43#define RC_INVALID_PI 28 // invalid processing instruction (<?xml)
44#define RC_INVALID_DOCTYPE 29 // duplicate doctype or after main element
45#define RC_VERSION_EXPECTED 30 // version is missing in xml declaration
46
47//-----------------------------------------------------------------------------
48// Structures
49//-----------------------------------------------------------------------------
50typedef struct AXElement AXElement ;
51typedef struct AXAttribute AXAttribute ;
52typedef struct AXElementClass AXElementClass ;
53typedef struct AXParseContext AXParseContext ;
54typedef struct AXClassContext AXClassContext ;
55
56struct AXElementClass
57{
58 int offset ; // Offset of the element in attribute list
59 char* name ; // Name of the element (not zero terminated)
60 char* nameLimit ; // End of the name of the element
61 unsigned int size ; // size in bytes of an element of this class
62 unsigned int id ; // container, text or mixed
63 unsigned int type ; // container, text or mixed
64 unsigned int propertyCount ; // number of attributes and text elements
65 unsigned int childCount ; // number of child classes
66 int* attributes ; // (internal) attribute map
67 int* elements ; // (internal) element map
68 AXElementClass** children ; // The list of child classes.
69 // The order is the one defined in the class
70 // definition file.
71 int reserved ;
72 void* reserved2 ;
73};
74
75struct AXClassContext
76{
77 void* base ;
78 void* limit ;
79 void* chunks ;
80 int chunkSize ;
81 int errorCode ;
82 int line ;
83 int column ;
84 AXElementClass** classes ; // all global classes
85 AXElementClass* rootClass ; // the root class
86 AXElement* rootElement ;
87};
88
89struct AXAttribute
90{
91 const char* begin ; // the value (not zero terminated)
92 // This slot can also contain an element if
93 // a <element> has been defined in schema;
94 // use ax_getElement() to retrieve it.
95 const char* limit ; // the end of the value
96};
97
98struct AXElement
99{
100 int id ; // the class of the element
101 AXElement* nextSibling ; // the next sibling element
102 AXElement* firstChild ; // the first child element
103 AXElement* lastChild ; // the last child element
104 AXAttribute reserved ; // do not use
105 AXAttribute attributes[1] ; // the array of attributes - there is
106 // no bound checking in C
107};
108
109struct AXParseContext
110{
111 void* base ;
112 void* limit ;
113 void* chunks ;
114 int chunkSize ;
115 int errorCode ;
116 const char* source ;
117 const char* current ;
118 int line ;
119 int column ;
120 AXElement* root ;
121 AXAttribute version ;
122 AXAttribute encoding ;
123 int strict ;
124 int reserved1 ;
125 AXElement reserved2 ;
126};
127
128//-----------------------------------------------------------------------------
129// Functions
130//-----------------------------------------------------------------------------
131
132extern
133void ACC ax_initialize (void* mallocFun,
134 void* freeFun);
135extern
136int ACC ax_initializeParser (AXParseContext* context,
137 unsigned int chunkSize);
138extern
139int ACC ax_releaseParser (AXParseContext* context);
140extern
141AXElement* ACC ax_parse (AXParseContext* context,
142 const char* source,
143 AXElementClass* type,
144 int strict);
145extern
146int ACC ax_initializeClassParser (AXClassContext* context);
147extern
148int ACC ax_releaseClassParser (AXClassContext* context);
149extern
150AXElementClass* ACC ax_classFromElement (AXElement* e,
151 AXClassContext* context);
152extern
153AXElementClass* ACC ax_classFromString (const char* source,
154 AXClassContext* context);
155
156#define ax_getElement(element, index) ((AXElement*)element->attributes[index].begin)
157#define ax_getAttribute(element, index) (&element->attributes[index])
158
159
160#ifdef __cplusplus
161}
162#endif
diff --git a/messenger/XML_Parser/friends.xml b/messenger/XML_Parser/friends.xml
new file mode 100644
index 00000000..edcb1407
--- /dev/null
+++ b/messenger/XML_Parser/friends.xml
@@ -0,0 +1,10 @@
1<?xml version="1.0" encoding="UTF-8"?>
2
3<!-- List of friends -->
4
5<friends>
6 <friend id="001">
7 <name>Senator Herpies</name>
8 <userID>12341241251</userID>
9 </friend>
10</friends> \ No newline at end of file
diff --git a/messenger/XML_Parser/main.c b/messenger/XML_Parser/main.c
new file mode 100644
index 00000000..28e8ba60
--- /dev/null
+++ b/messenger/XML_Parser/main.c
@@ -0,0 +1,160 @@
1///////////////////////////////////////////////////////////////////////////////
2//
3// Friend List Parser
4//
5///////////////////////////////////////////////////////////////////////////////
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include "asm-xml.h"
11
12static const int chunkSize = 16*1024*1024; // 16Mk
13static const char schemaFilename[] = "schema.xml";
14static const char xmlFilename[] = "friends.xml";
15
16char buffer[65536];
17
18///////////////////////////////////////////////////////////////////////////////
19// Print an attribute / text value
20///////////////////////////////////////////////////////////////////////////////
21const char* asString(AXAttribute* attr)
22{
23 const char* start = attr->begin;
24 const char* limit = attr->limit;
25 size_t size = limit - start;
26 memcpy(buffer, start, size);
27 buffer[size] = 0;
28 return buffer;
29}
30
31///////////////////////////////////////////////////////////////////////////////
32// Print an error code from the parser
33///////////////////////////////////////////////////////////////////////////////
34void printAsmXmlError(AXParseContext* context)
35{
36 fprintf(stderr, "Error (%d,%d): %d\n", context->line, context->column, context->errorCode);
37}
38
39///////////////////////////////////////////////////////////////////////////////
40// Read Schema Definition
41///////////////////////////////////////////////////////////////////////////////
42AXElementClass* readClass(const char* filename, AXClassContext* classContext)
43{
44 FILE* f;
45 size_t size;
46
47 f = fopen(filename, "rb");
48 if( f == NULL )
49 {
50 fprintf(stderr, "can't open schema '%s'\n", filename);
51 return NULL;
52 }
53 size = fread(buffer, 1, 65535, f);
54 buffer[size] = 0;
55 fclose(f);
56
57 // Parse the string and build the class
58 return ax_classFromString(buffer, classContext);
59}
60
61///////////////////////////////////////////////////////////////////////////////
62// Read Document
63///////////////////////////////////////////////////////////////////////////////
64AXElement* readDocument(const char* filename,
65 AXParseContext* parseContext,
66 AXElementClass* clazz)
67{
68 FILE* f;
69 size_t size;
70
71 f = fopen(filename, "rb");
72 if( f == NULL )
73 {
74 fprintf(stderr, "can't open file '%s'\n", filename);
75 return NULL;
76 }
77 size = fread(buffer, 1, 65535, f);
78 buffer[size] = 0;
79 fclose(f);
80
81 // Parse the string and build the class
82 return ax_parse(parseContext, buffer, clazz, 1);
83}
84
85///////////////////////////////////////////////////////////////////////////////
86// main
87///////////////////////////////////////////////////////////////////////////////
88int main(int argc, char *argv[])
89{
90 int res;
91 AXClassContext classContext;
92 AXParseContext parseContext;
93 AXElementClass* friendClass;
94 AXElement* friends;
95 AXElement* friend;
96
97 // Initialize the AsmXml library
98 //
99 // Pass the malloc() and free() functions
100 //
101 ax_initialize(malloc, free);
102
103 // Initialize the class context
104 //
105 // It can store one or more classes. Classes read with this
106 // context are kept in memory as long as it is not released.
107 //
108 res = ax_initializeClassParser(&classContext);
109 // An error while initialization means that allocation failed.
110 // It should never happen since it allocates only 4K.
111 if( res != 0 )
112 return 1;
113
114 // Read the schema and compile it
115 //
116 friendClass = readClass(schemaFilename, &classContext);
117 if( friendClass == NULL )
118 return 1;
119
120 // Initialize the parser
121 //
122 // Documents read with this parser will stay in memory as long as
123 // the parser is not released.
124 //
125 // The choice of the chunk size is very important since the
126 // performance can be affected by this value. The parser allocates
127 // memory by chunks to reduce calls to malloc that can be very slow.
128 // The ideal value is around 50% of the source XML to process.
129 //
130 res = ax_initializeParser(&parseContext, chunkSize);
131 // An error while initialization means that initial allocation failed.
132 if( res != 0 )
133 return 1;
134
135 // Read the file and parse it
136 //
137 friends = readDocument(xmlFilename, &parseContext, friendClass);
138 if( friends == NULL )
139 {
140 printAsmXmlError(&parseContext);
141 return 1;
142 }
143
144 // Enumerate child elements
145 friend = friends->firstChild;
146 while( friend )
147 {
148 printf("================================\n");
149 printf("Friend ID: %s\n", asString(&friend->attributes[0]));
150 printf("Name: %s\n", asString(&friend->attributes[1]));
151 printf("UserID: %s\n", asString(&friend->attributes[2]));
152 friend = friend->nextSibling;
153 printf("================================\n");
154 }
155
156 // Release the document and its class
157 ax_releaseParser(&parseContext);
158 ax_releaseClassParser(&classContext);
159 return 0;
160}
diff --git a/messenger/XML_Parser/obj/elf/asm-xml.o b/messenger/XML_Parser/obj/elf/asm-xml.o
new file mode 100644
index 00000000..02fe23ce
--- /dev/null
+++ b/messenger/XML_Parser/obj/elf/asm-xml.o
Binary files differ
diff --git a/messenger/XML_Parser/obj/mach-o/asm-xml.o b/messenger/XML_Parser/obj/mach-o/asm-xml.o
new file mode 100644
index 00000000..c4373bac
--- /dev/null
+++ b/messenger/XML_Parser/obj/mach-o/asm-xml.o
Binary files differ
diff --git a/messenger/XML_Parser/obj/ms-coff/asm-xml.obj b/messenger/XML_Parser/obj/ms-coff/asm-xml.obj
new file mode 100644
index 00000000..8f61851f
--- /dev/null
+++ b/messenger/XML_Parser/obj/ms-coff/asm-xml.obj
Binary files differ
diff --git a/messenger/XML_Parser/src/asm-xml.asm b/messenger/XML_Parser/src/asm-xml.asm
new file mode 100644
index 00000000..e9c20c59
--- /dev/null
+++ b/messenger/XML_Parser/src/asm-xml.asm
@@ -0,0 +1,5594 @@
1;[c]asm-xml.asm - Asm XML Parser
2;[c]
3;[c]Copyright (C) 2007-12, Marc Kerbiquet
4;[c]All rights reserved.
5;[c]
6;[c]Redistribution and use in source and binary forms, with or without
7;[c]modification, are permitted provided that the following conditions are met:
8;[c]
9;[c]1. Redistributions of source code must retain the above copyright notice,
10;[c] this list of conditions and the following disclaimer.
11;[c]2. Redistributions in binary form must reproduce the above copyright notice,
12;[c] this list of conditions and the following disclaimer in the documentation
13;[c] and/or other materials provided with the distribution.
14;[c]3. Neither the name of AsmXml nor the names of its contributors may be
15;[c] used to endorse or promote products derived from this software without
16;[c] specific prior written permission.
17;[c]
18;[c]THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19;[c]AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20;[c]IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21;[c]DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22;[c]FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23;[c]DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24;[c]SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25;[c]CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26;[c]OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27;[c]OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28;[c]
29;[c]
30;[c]Open this file with Code Browser (http://code-browser.sourceforge.net/)
31;[c]to view this long flat file as a structured text file.
32;[c]
33;[c]This is source code for fasm.
34;[c]
35;[c]Conventions:
36;[c]Preserved registers: ebx esi edi ebp
37;[c]Scratch registers: eax ecx edx
38;[c](same as Windows/Linux/BSD)
39;[c]
40;[of]:Macros
41macro struct name
42{
43 virtual at 0
44 label name
45}
46
47macro ends
48{
49.sizeof rd 0
50 end virtual
51}
52;[cf]
53;[of]:Definitions
54 struct MemoryContext
55.base rd 1 ; memory buffer
56.limit rd 1 ; limit of memory buffer
57.chunks rd 1 ; list of chunks
58.chunkSize rd 1 ; default size of chunks
59 ends
60;[c]
61 struct ParseContext
62.base rd 1 ; memory buffer
63.limit rd 1 ; limit of memory buffer
64.chunks rd 1 ; list of chunks
65.chunkSize rd 1 ; default size of chunks
66.errorCode rd 1
67.source rd 1 ; address of the first char
68.current rd 1 ; address of the last read char
69.line rd 1 ; line number of the last read char
70.column rd 1 ; column of the last read char
71.root rd 1 ; root element
72.version rd 2 ; version info (if any)
73.encoding rd 2 ; encoding (if any)
74.strict rd 1 ; 0 if not strict
75.doctype rd 1 ; can read doctype
76.invalidElement rb Element.sizeof
77 ends
78;[c]
79 struct CreateClassContext
80.base rd 1 ; memory buffer
81.limit rd 1 ; limit of memory buffer
82.chunks rd 1 ; list of chunks
83.chunkSize rd 1 ; default size of chunks
84.errorCode rd 1
85.line rd 1 ; line number of the last read char
86.column rd 1 ; column of the last read char
87.classes rd 1 ; the list of global classes
88.rootClass rd 1 ; the root class
89.rootElement rd 1 ; the root element
90 ends
91;[c]
92 struct ElementClass
93.offset rd 1 ; Offset of element in parent element
94 ; (0 when it is a collection)
95.name rd 1 ; name of the element
96.nameLimit rd 1 ; limit of the name
97.size rd 1 ; size to store the element
98.id rd 1 ; id
99.type rd 1 ; container, text or mixed
100.propertyCount rd 1 ; number of attributes + text elements
101.childCount rd 1 ; number of child classes
102.attributes rd 1 ; list of attributes
103.elements rd 1 ; list of elements
104.children rd 1 ; list of child classes
105 ; The order is the one defined in the class
106 ; definition file.
107.shared rb 1 ;
108.status rb 1 ; 0-unsolved 1-resolving 2-resolved
109 rb 2 ; padding
110.source rd 1 ; source element
111 ends
112;[c]
113 struct TextElementClass
114.offset rd 1 ; Offset of attribute in element
115 ; (the text element is stored as an attribute)
116.begin rd 1 ; element name (begin)
117.limit rd 1 ; element name (last char+1)
118 ends
119;[c]
120 struct Element
121.id rd 1 ; id of the element
122.nextSibling rd 1
123.firstChild rd 1
124.lastChild rd 1
125.reserved rd 2 ; store ignored attributes here
126 ends
127;[c]
128;[c]
129 struct Attribute
130.begin rd 1
131.limit rd 1
132 ends
133;[c]
134;[c]
135EC_TEXT equ 1
136EC_TEXT_COLL equ 2
137
138;[c]
139;[c]Error Codes
140;[c]
141RC_OK equ 0 ; everything is ok
142RC_MEMORY equ 1 ; out of memory
143
144; Schema
145RC_EMPTY_NAME equ 10 ; name empty or not defined
146RC_ATTR_DEFINED equ 11 ; attribute already defined
147RC_ELEM_DEFINED equ 12 ; element already defined
148RC_SCHEMA_EMPTY equ 13 ; schema does not contains a document
149RC_DOCUMENT_DEFINED equ 14 ; schema contains more than one document
150RC_UNDEFINED_CLASS equ 15 ; can't find collection in reference
151RC_UNDEFINED_GROUP equ 16 ; can't find a group in include
152RC_INVALID_ID equ 17 ; id is not a valid number
153RC_INVALID_IGNORE equ 18 ; ignore is not 'yes' or 'no'
154RC_RECURSIVE_ELEMENT equ 19 ; element cannot reference itself
155
156; Parsing
157RC_INVALID_ENTITY_REFERENCE equ 20
158RC_UNEXPECTED_END equ 21
159RC_INVALID_CHAR equ 22
160RC_OVERFLOW equ 23
161RC_NO_START_TAG equ 24
162RC_TAG_MISMATCH equ 25
163RC_INVALID_TAG equ 26
164RC_INVALID_ATTRIBUTE equ 27
165RC_INVALID_PI equ 28
166RC_INVALID_DOCTYPE equ 29
167RC_VERSION_EXPECTED equ 30
168
169;[c]
170;[c]Various constants
171;[c]
172TAB_SIZE equ 8
173DEFAULT_CHUNK_SIZE equ 1024*1024
174HEADER_SIZE equ 16 ; reserved space for chunks
175;[c]
176TYPE_CONTAINER equ 0
177TYPE_TEXT equ 1
178TYPE_MIXED equ 2
179;[c]
180ATTR_NAME equ 0
181ATTR_IGNORE equ 1
182ATTR_TYPE equ 2
183ATTR_ID equ 3
184;[c]
185;[c]Class Ids
186;[c]
187schemaId equ 0
188documentId equ 1
189attributeId equ 2
190textId equ 3
191collectionId equ 4
192elementId equ 5
193referenceId equ 6
194includeId equ 7
195groupId equ 8
196;[c]
197;[c]Resolution
198;[c]
199UNRESOLVED equ 0
200RESOLVING equ 1
201RESOLVED equ 2
202;[c]
203;[c]Atoms (for DOCTYPE)
204;[c]
205ATOM_DOCTYPE equ 0
206ATOM_ELEMENT equ 1
207ATOM_ATTLIST equ 2
208ATOM_PCDATA equ 3
209ATOM_IMPLIED equ 4
210ATOM_REQUIRED equ 5
211ATOM_FIXED equ 6
212ATOM_NDATA equ 7
213
214ATOM_CDATA equ 8
215ATOM_ID equ 9
216ATOM_IDREF equ 10
217ATOM_IDREFS equ 11
218ATOM_ENTITY equ 12
219ATOM_ENTITIES equ 13
220ATOM_NMTOKEN equ 14
221ATOM_NMTOKENS equ 15
222ATOM_NOTATION equ 16
223
224ATOM_VERSION equ 17
225ATOM_ENCODING equ 18
226ATOM_STANDALONE equ 19
227;[cf]
228;[of]:Documentation
229;[c]
230;[c]Element Map
231;[c]
232;[c] An element map is an array of 256 values each value correspond to
233;[c] an action to take corresponding to the current read char:
234;[c] * 1
235;[c] The character is invalid in the current state
236;[c]
237;[c] * Address % 4 = 0
238;[c] The address of the element map for the next char
239;[c]
240;[c] * Address % 4 = 1
241;[c] The address of the element class found preceded by the
242;[c] remaining chars and the type of class
243;[c] e.g.
244;[c] "bcd", 0, t, padding, ...
245;[c] * t = 0
246;[c] It is a collection, the pointer to the element class
247;[c] is at the next 4 byte align.
248;[c] * t = 1
249;[c] It is a text element, the text element class is stored
250;[c] after the padding.
251;[c]
252;[c] * Address % 4 = 3
253;[c] Same as previous but all chars have already been read.
254;[c] It is used when a name is the prefix of another name.
255;[c] e.g.:
256;[c] <ab>
257;[c] <abc>
258;[c]
259;[c]
260;[c]
261;[c]
262;[cf]
263;[of]:C Stubs
264;[of]:initialize
265;[c]Initialize the library
266;[c]
267;[c] void ax_initialize(malloc, free)
268;[c]
269;[c]ARGUMENTS
270;[c] malloc
271;[c] the memory alllocation function
272;[c] free
273;[c] the free memory function
274;[c]
275;[c]
276_initialize: push ebx
277 mov eax,[esp+8+0]
278 mov ebx,[esp+8+4]
279 call initialize
280 pop ebx
281 ret
282;[cf]
283;[of]:initializeParser
284;[c]Initialize the parse context
285;[c]
286;[c] errorCode = ax_initializeParser(context, chunkSize)
287;[c]
288;[c]ARGUMENTS
289;[c] context
290;[c] the parse context.
291;[c] chunkSize
292;[c] the default size of chunk
293;[c]
294;[c]RETURN VALUE
295;[c] The error code
296;[c]
297_initializeParser:
298 push ebp
299 mov ebp,[esp+8+0]
300 mov ecx,[esp+8+4]
301 call initializeParser
302 pop ebp
303 ret
304;[cf]
305;[of]:releaseParser
306;[c]Release the parse context
307;[c]
308;[c] ax_releaseParser(context)
309;[c]
310;[c]ARGUMENTS
311;[c] context
312;[c] the parse context. The memory base and memory limit must be
313;[c] initialized.
314;[c]
315_releaseParser: push ebp
316 mov ebp,[esp+8+0]
317 call releaseParser
318 pop ebp
319 ret
320;[cf]
321;[of]:parse
322;[c]Parse an XML string
323;[c]
324;[c] Element* ax_parse(context, source, type, strict)
325;[c]
326;[c]ARGUMENTS
327;[c] context
328;[c] the parse context. The object must have been initialized.
329;[c] source
330;[c] the xml to parse
331;[c] type
332;[c] the expected type of element to parse
333;[c]
334;[c]RETURN VALUE
335;[c] The created element or null if an error occured.
336;[c]
337_parse: push ebx
338 push esi
339 push edi
340 push ebp
341
342 mov ebp,[esp+20+ 0]
343 mov esi,[esp+20+ 4]
344 mov edx,[esp+20+ 8]
345 mov edi,[esp+20+12]
346 call parse
347
348 mov [ebp+ParseContext.current],esi
349 mov [ebp+ParseContext.errorCode],eax
350 jz .ok
351 call computeLineColumn
352 xor eax,eax
353 jmp .error
354
355.ok: mov eax,[ebp+ParseContext.root]
356.error: pop ebp
357 pop edi
358 pop esi
359 pop ebx
360 ret
361;[c]
362;[cf]
363;[c]
364;[of]:initializeClassParser
365;[c]Initialize the class parser
366;[c]
367;[c] errorCode = ax_initializeClassParser(context)
368;[c]
369;[c]ARGUMENTS
370;[c] context
371;[c] the class parser.
372;[c]
373;[c]RETURN VALUE
374;[c] The error code
375;[c]
376_initializeClassParser:
377 push ebp
378 mov ebp,[esp+8+0]
379 call initializeClassParser
380 pop ebp
381 ret
382;[cf]
383;[of]:releaseClassParser
384;[c]Release the class parser
385;[c]
386;[c] ax_releaseClassParser(context)
387;[c]
388;[c]ARGUMENTS
389;[c] context
390;[c] the class parser.
391;[c]
392_releaseClassParser:
393 push ebp
394 mov ebp,[esp+8+0]
395 call releaseClassParser
396 pop ebp
397 ret
398;[cf]
399;[of]:classFromElement
400;[c]Create a class from an element
401;[c]
402;[c] ElementClass* ax_classFromElement(element, context)
403;[c]
404;[c]ARGUMENTS
405;[c] element
406;[c] the xml element describing the class
407;[c] context
408;[c] the class context.
409;[c]
410;[c]RETURN VALUE
411;[c] The created class or null if an error occured.
412;[c]
413_classFromElement:
414 push esi
415 push edi
416 push ebp
417
418 mov esi,[esp+16]
419 mov ebp,[esp+16+4]
420 call classFromElement
421 mov [ebp+CreateClassContext.errorCode],eax
422 jnz .failed
423 mov eax,[ebp+CreateClassContext.rootClass]
424
425.error: pop ebp
426 pop edi
427 pop esi
428 ret
429
430.failed: xor eax,eax
431 jmp .error
432;[c]
433;[cf]
434;[of]:classFromString
435;[c]Create a class from a string
436;[c]
437;[c] ElementClass* ax_classFromString(string, context)
438;[c]
439;[c]ARGUMENTS
440;[c] string
441;[c] the xml element describing the class
442;[c] context
443;[c] the class context.
444;[c]
445;[c]RETURN VALUE
446;[c] The created class or null if an error occured.
447;[c]
448_classFromString:
449 push ebx
450 push esi
451 push edi
452 push ebp
453
454 mov esi,[esp+20+0]
455 mov ebp,[esp+20+4]
456 call classFromString
457 mov [ebp+CreateClassContext.errorCode],eax
458 jnz .failed
459 mov eax,[ebp+CreateClassContext.rootClass]
460
461.error: pop ebp
462 pop edi
463 pop esi
464 pop ebx
465 ret
466
467.failed: xor eax,eax
468 jmp .error
469;[cf]
470;[cf]
471;[of]:Functions
472;[of]:initialize
473;[c]Initialize the library
474;[c]
475;[c]ARGUMENTS
476;[c] eax
477;[c] the allocator function
478;[c] ebx
479;[c] the free memory function
480;[c]
481initialize:
482 mov [mallocFunction],eax
483 mov [freeFunction],ebx
484 ret
485;[cf]
486
487;[of]:initializeParser
488;[c]Initialize the parse context object
489;[c]
490;[c]ARGUMENTS
491;[c] ebp
492;[c] the parse context
493;[c] ecx
494;[c] chunk size
495;[c]
496;[c]RETURN VALUES
497;[c] eax+zf
498;[c] error code
499;[c]
500initializeParser:
501 xor eax,eax
502 mov [ebp+ParseContext.chunkSize],ecx
503 mov [ebp+ParseContext.chunks],eax
504 mov eax,ecx
505 jmp newChunk
506;[cf]
507;[of]:releaseParser
508;[c]Release the parse context object
509;[c]
510;[c]ARGUMENTS
511;[c] ebp
512;[c] the parse context
513;[c]
514releaseParser: jmp releaseChunks
515;[cf]
516;[of]:parse
517;[c]parse
518;[c]
519;[c]ARGUMENTS
520;[c] edx
521;[c] the type of the root element
522;[c] esi
523;[c] source
524;[c] edi
525;[c] strict flag
526;[c] ebp
527;[c] Parse context
528;[c]
529;[c]RETURN VALUES
530;[c] eax+zf
531;[c] error code
532;[c] esi
533;[c] Address of the first byte after the element.
534;[c] edi
535;[c] ???
536;[c]
537parse: mov [ebp+ParseContext.source],esi
538 mov [ebp+ParseContext.strict],edi
539 mov [ebp+ParseContext.doctype],1
540
541 sub eax,eax
542 mov [ebp+ParseContext.version+Attribute.begin],eax
543 mov [ebp+ParseContext.version+Attribute.limit],eax
544 mov [ebp+ParseContext.encoding+Attribute.begin],eax
545 mov [ebp+ParseContext.encoding+Attribute.limit],eax
546
547 ; Allocate memory for root element
548 mov edi,[ebp+ParseContext.base]
549 mov eax,[ebp+ParseContext.limit]
550 mov ebx,edi
551 add ebx,[edx+ElementClass.size]
552 cmp ebx,eax
553 jae parseChunkFull
554 mov [ebp+ParseContext.base],ebx
555 mov [ebp+ParseContext.root],edi
556
557resumeParseChunkFull:
558
559 ; Clear higher bits of eax
560 ; All the functions assume that the high bits of eax
561 ; are always zero.
562 xor eax,eax
563
564 call readProlog
565 jnz return
566
567 call readRootElement
568 jnz return
569
570 ; forbid the doctype
571 mov [ebp+ParseContext.doctype],0
572
573 call readMisc
574 jnz return
575
576 ; error if there is remaining chars
577 or al,al
578 jnz invalidChar
579
580 xor eax,eax
581 ret
582;[c]
583;[c]Sub-functions
584;[c]
585;[of]: readRootElement
586readRootElement:
587 cmp al,'<'
588 jnz notStartTag
589
590;[of]: Initialize Element
591 mov eax,[edx+ElementClass.id]
592 mov [edi+Element.id],eax
593 xor eax,eax
594 mov [edi+Element.firstChild],eax
595 mov [edi+Element.lastChild],eax
596 mov [edi+Element.nextSibling],eax
597
598 mov ecx,[edx+ElementClass.propertyCount]
599 lea ebx,[edi+Element.sizeof]
600
601 or ecx,ecx
602 jz .m0
603
604 shr ecx,1
605 jnc .m2
606 mov [ebx+Attribute.begin],eax
607 mov [ebx+Attribute.limit],eax
608 jz .m0
609 add ebx,Attribute.sizeof
610
611.m2: shr ecx,1
612 jnc .m4
613 mov [ebx+Attribute.begin],eax
614 mov [ebx+Attribute.limit],eax
615 mov [ebx+Attribute.sizeof+Attribute.begin],eax
616 mov [ebx+Attribute.sizeof+Attribute.limit],eax
617 jz .m0
618 add ebx,Attribute.sizeof*2
619
620.m4: mov [ebx+Attribute.sizeof*0+Attribute.begin],eax
621 mov [ebx+Attribute.sizeof*0+Attribute.limit],eax
622 mov [ebx+Attribute.sizeof*1+Attribute.begin],eax
623 mov [ebx+Attribute.sizeof*1+Attribute.limit],eax
624 mov [ebx+Attribute.sizeof*2+Attribute.begin],eax
625 mov [ebx+Attribute.sizeof*2+Attribute.limit],eax
626 mov [ebx+Attribute.sizeof*3+Attribute.begin],eax
627 mov [ebx+Attribute.sizeof*3+Attribute.limit],eax
628 add ebx,Attribute.sizeof*4
629 dec ecx
630 jnz .m4
631.m0:
632;[cf]
633;[of]: Read Element Name
634;[c]Read Element Name
635;[c]
636 mov ebx,edi
637 mov edi,[edx+ElementClass.name]
638 mov ecx,[edx+ElementClass.nameLimit]
639.loop: cmpsb
640 jnz invalidTag
641 cmp edi,ecx
642 jnz .loop
643 mov edi,ebx
644
645 movzx eax,byte [esi]
646 add esi,1
647 cmp al,'>'
648 jz readContent
649 cmp al, '/'
650 jz endOfElement
651 test byte [S + eax], 1
652 jz invalidChar
653;[cf]
654;[of]: Read Attributes
655;[c]Read Attributes
656;[c]
657;[c]Read the next attribute (skip blanks first)
658;[c]
659nextAttribute:
660 ; Skip blanks
661.sb: movzx eax,byte [esi]
662 add esi,1
663 test byte [S + eax], 1
664 jnz .sb
665
666;[c]
667;[c]Read the next attribute (blanks already skipped, first char already read)
668;[c]
669readAttributes:
670 ; No more attributes ?
671 cmp al, '>'
672 jz readContentOrText
673 cmp al, '/'
674 jz endOfElement
675
676;[c]
677;[c]Read and Decode Attribute Name
678;[c]
679readAttribute: mov ebx,[edx+ElementClass.attributes]
680 mov ecx,[ebx+eax*4] ; first char already loaded
681 test ecx,1
682 jnz .j2
683.l2: movzx eax,byte [esi]
684 mov ecx,[ecx+eax*4]
685 add esi,1
686 test ecx,1
687 jz .l2
688
689 test ecx,2
690 jnz terminalAttribute
691.j2: sub ecx,1
692 jz invalidAttribute
693 align 4
694.l21: movzx eax,byte [esi]
695 add ecx,1
696 add esi,1
697 cmp [ecx-1],al
698 jz .l21
699 test byte [ecx-1],255
700 jnz invalidAttribute
701
702commonAttribute:
703 mov ebx,edi
704 add ebx,[ecx]
705
706;[c]
707;[c]Skip Blanks and Equal Sign
708;[c]
709 cmp al,'=' ; I'm feeling lucky
710 jz readAttributeValue ;
711
712 test byte [S + eax], 1 ; Not '=', it MUST be a blank
713 jz invalidAttribute ; or it is an invalid attribute
714
715.skipBlank2: movzx eax,byte [esi]
716 add esi,1
717 test byte [S + eax], 1
718 jnz .skipBlank2
719
720 cmp al,'='
721 jnz invalidChar
722
723readAttributeValue:
724 movzx eax,byte [esi]
725 add esi,1
726 test byte [S + eax], 1
727 jnz readAttributeValue
728
729 cmp al,$27 ; '
730 jz .value
731 cmp al,'"'
732 jnz invalidChar
733.value: mov cl,al
734
735;[c]
736;[c]Read and Store Value
737;[c]
738 cmp [ebx+Attribute.begin],0
739 jnz attributeDefinedOrIgnored
740resumeBecauseIgnored:
741 mov [ebx+Attribute.begin],esi
742 mov ch,'&'
743.l3: mov al,[esi]
744 add esi,1
745 ;test byte [RAC + eax], 1 ; slower but it would allow
746 ;jz .l3 ; detection of < in attribute
747 ;cmp al,'<' ; makes the parser 5% slower
748 ;jz invalidChar ;
749 cmp al,ch
750 jz attributeReference
751 or al,al
752 jz unexpectedEnd
753 cmp al,cl
754 jnz .l3
755
756 lea ecx,[esi-1]
757 mov [ebx+Attribute.limit],ecx
758;[c]
759endOfAttribute:
760 ; Read next char
761 movzx eax,byte [esi]
762 add esi,1
763
764 ; Is it a blank ?
765 test byte [S + eax], 1
766 jnz nextAttribute
767
768 ; Is it a closing tag ?
769 cmp al, '>'
770 jz readContentOrText
771
772 ; Is it not the end of the element ?
773 cmp al, '/'
774 jnz readAttribute
775
776endOfElement: movzx eax,byte [esi]
777 add esi,1
778 cmp al,'>'
779 jnz invalidChar
780 xor eax,eax
781 ret
782;[c]
783terminalAttribute:
784 and ecx,not 2
785 jmp commonAttribute
786;[c]
787attributeDefinedOrIgnored:
788 mov eax,ebx
789 sub eax,edi
790 cmp eax,Element.reserved
791 jz resumeBecauseIgnored
792 jmp attributeDefined
793;[cf]
794
795;[of]: Read Content
796;[c]Read Content
797;[c]
798readContentOrText:
799 ; test if the content is just text
800 cmp [edx+ElementClass.type],TYPE_TEXT
801 jz readInnerText
802;[c]
803readContent:
804 cmp [edx+ElementClass.type],TYPE_MIXED
805 jz readPCDATA
806 mov bl,'<'
807
808.loop: mov al,[esi]
809 or al,al
810 jz unexpectedEnd
811 add esi,1
812 cmp al,bl
813 jnz .loop
814
815 mov al,[esi]
816 cmp al, '/'
817 jnz referenceOrComment
818
819;[of]:Read Close Tag
820readCloseTag:
821 add esi,1
822
823 mov edi,[edx+ElementClass.name]
824 mov ecx,[edx+ElementClass.nameLimit]
825.loop: cmpsb
826 jnz closeTagMismatch
827 cmp edi,ecx
828 jnz .loop
829
830 movzx eax,byte [esi]
831 add esi,1
832 cmp al, '>' ; I'm feeling lucky
833 jnz .skipBlanks4 ;
834 xor eax,eax
835 ret
836
837.skipBlanks4: test byte [S + eax], 1
838 jz invalidChar
839.skipBlank4: movzx eax,byte [esi]
840 add esi,1
841 test byte [S + eax], 1
842 jnz .skipBlank4
843 cmp al, '>'
844 jnz invalidChar
845
846 xor eax,eax ; element successfully read
847 ret
848;[cf]
849
850referenceOrComment:
851 cmp al,'!'
852 jz skipCommentOrCDATA
853 cmp al,'?'
854 jz skipContentPI
855;[of]:Read Child Element
856;[c]Read a child element (may be a text-only element)
857;[c]
858readChild: add esi,1
859;[c]
860;[c]Decode Element Name
861;[c]
862 mov ebx,[edx+ElementClass.elements]
863 mov ecx,[ebx+eax*4] ; first char already loaded
864 test ecx,1
865 jnz .skip
866.loop: movzx eax,byte [esi]
867 mov ecx,[ecx+eax*4]
868 add esi,1
869 test ecx,1
870 jz .loop
871
872.skip: test ecx,2
873 jnz terminalElement
874 dec ecx
875 jz invalidElement
876.loop2: movzx eax,byte [esi]
877 add ecx,1
878 add esi,1
879 cmp [ecx-1],al
880 jz .loop2
881 test byte [ecx-1],255
882 jnz invalidElement
883
884 mov bl,[ecx]
885
886;[of]:Skip Blanks
887 test byte [S + eax], 1
888 jz .eNotBlank1
889.eSkipBlank1: movzx eax,byte [esi]
890 add esi,1
891 test byte [S + eax], 1
892 jnz .eSkipBlank1
893.eNotBlank1:
894;[cf]
895
896 add ecx,3+1
897 and ecx,$FFFFFFFC
898 test bl,1
899 jz readChildElement
900
901;[c]
902;[of]:Read Text
903;[c]Read a Text-Only Element
904;[c]
905;[c] * esi is the source
906;[c] * edi is the element
907;[c]
908;[c] * ecx is the text element descriptor
909;[c] * al is the last non blank character in the tag (must be '>')
910;[c]
911readText:
912 mov ebx,edi
913 add ebx,[ecx+TextElementClass.offset]
914
915 cmp al,'/'
916 jz emptyText
917 cmp al,'>'
918 jnz invalidChar
919
920 mov [ebx+Attribute.begin],esi
921
922 movzx eax,byte [esi]
923 add esi,1
924 cmp al,'<'
925 jz emptyOrCDATAOrPI
926 or al,al
927 jz unexpectedEnd
928 cmp al,'&'
929 jz textReference
930
931.loop: movzx eax,byte [esi]
932 add esi,1
933 or al,al
934 jz unexpectedEnd
935 cmp al,'&'
936 jz textReference
937 cmp al,'<'
938 jnz .loop
939
940 movzx eax,byte [esi]
941 cmp al,'!'
942 jz textCommentOrCDATA
943 cmp al,'?'
944 jz textPI
945
946endOfEmptyText: sub esi,1
947 mov [ebx+Attribute.limit],esi
948 add esi,1
949
950endOfText: add esi,1
951 cmp al, '/'
952 jnz invalidChar
953
954 mov ebx,edi
955 mov edi,[ecx+TextElementClass.begin]
956 mov ecx,[ecx+TextElementClass.limit]
957.loop: cmpsb
958 jnz tagMismatch
959 cmp edi,ecx
960 jnz .loop
961 mov edi,ebx
962
963.eSkipBlank2: movzx eax,byte [esi]
964 add esi,1
965 test byte [S + eax], 1
966 jnz .eSkipBlank2
967
968 cmp al,'>'
969 jz readContent
970 jmp invalidChar
971;[c]
972emptyOrCDATAOrPI:
973 movzx eax,byte [esi]
974 cmp al,'?'
975 jz textPI
976 cmp al,'!'
977 jnz endOfEmptyText
978 cmp byte [esi+1],'['
979 jnz invalidCharOrComment
980 cmp byte [esi+2],'C'
981 jnz invalidChar
982 cmp byte [esi+3],'D'
983 jnz invalidChar
984 cmp byte [esi+4],'A'
985 jnz invalidChar
986 cmp byte [esi+5],'T'
987 jnz invalidChar
988 cmp byte [esi+6],'A'
989 jnz invalidChar
990 cmp byte [esi+7],'['
991 jnz invalidChar
992 add esi,8
993 mov [ebx+Attribute.begin],esi
994
995.loop: movzx eax,byte [esi]
996 add esi,1
997 or al,al
998 jz unexpectedEnd
999 cmp al,']'
1000 jnz .loop
1001 movzx eax,byte [esi]
1002 cmp al,']'
1003 jnz .loop
1004 mov al,[esi+1]
1005 cmp al,'>'
1006 jnz .loop
1007
1008 mov al,[esi+2]
1009 cmp al,'<'
1010 jnz .mixed
1011
1012 sub esi,1
1013 mov [ebx+Attribute.limit],esi
1014 add esi,4
1015 movzx eax,byte [esi]
1016 jmp endOfText
1017;[c]
1018;[c]The text starts with a CDATA section but contain something else,
1019;[c]let 's read it again with the slow method
1020;[c]
1021.mixed: mov esi,[ebx+Attribute.begin]
1022 sub esi,9 ; size("<![CDATA[")
1023 mov [ebx+Attribute.begin],esi
1024 call readValue
1025 jmp endOfText
1026;[c]
1027textReference:
1028textCommentOrCDATA:
1029textPI:
1030invalidCharOrComment:
1031 sub esi,1
1032 call readValue
1033 jmp endOfText
1034;[c]
1035emptyText: movzx eax,byte [esi]
1036 add esi,1
1037 cmp al,'>'
1038 jnz invalidChar
1039 mov [ebx+Attribute.begin],esi ; any non null ptr is ok
1040 mov [ebx+Attribute.limit],esi
1041 jmp readContent
1042;[cf]
1043;[of]:Read a Child Element
1044;[c]Read a Child Element
1045;[c]
1046;[c] * esi source
1047;[c] * edi parent element
1048;[c] * ecx the element description in parent
1049;[c] * edx type of parent
1050;[c]
1051
1052readChildElement:
1053
1054 push edx
1055 mov edx,[ecx]
1056
1057 ; Allocate memory
1058 mov ecx,[ebp+ParseContext.base]
1059 mov ebx,[edx+ElementClass.size]
1060 add ebx,ecx
1061 cmp ebx,[ebp+ParseContext.limit]
1062 jae .chunkFull
1063 mov [ebp+ParseContext.base],ebx
1064.resume:
1065 ; It is an element, not a collection:
1066 ; it must be store in an attribute slot instead of
1067 ; in the list of children.
1068 ; This case should be exceptional, it is placed
1069 ; out of the main flow to avoid breaking the pipeline
1070 cmp [edx+ElementClass.offset],0
1071 jnz .element
1072
1073 ; Append element
1074 cmp dword [edi+Element.firstChild],0
1075 jnz .rce1
1076 mov [edi+Element.firstChild],ecx
1077.rce1: mov ebx,[edi+Element.lastChild]
1078 or ebx,ebx
1079 jz .rce2
1080 mov [ebx+Element.nextSibling],ecx
1081.rce2: mov [edi+Element.lastChild],ecx
1082
1083.resume2: push edi
1084 mov edi,ecx
1085;[of]: Initialize Element
1086 push eax
1087 mov eax,[edx+ElementClass.id]
1088 mov [edi+Element.id],eax
1089 xor eax,eax
1090 mov [edi+Element.firstChild],eax
1091 mov [edi+Element.lastChild],eax
1092 mov [edi+Element.nextSibling],eax
1093
1094 mov ecx,[edx+ElementClass.propertyCount]
1095 lea ebx,[edi+Element.sizeof]
1096
1097 or ecx,ecx
1098 jz .xm0
1099
1100 shr ecx,1
1101 jnc .xm2
1102 mov [ebx+Attribute.begin],eax
1103 mov [ebx+Attribute.limit],eax
1104 jz .xm0
1105 add ebx,Attribute.sizeof
1106
1107.xm2: shr ecx,1
1108 jnc .xm4
1109 mov [ebx+Attribute.begin],eax
1110 mov [ebx+Attribute.limit],eax
1111 mov [ebx+Attribute.sizeof+Attribute.begin],eax
1112 mov [ebx+Attribute.sizeof+Attribute.limit],eax
1113 jz .xm0
1114 add ebx,Attribute.sizeof*2
1115
1116.xm4: mov [ebx+Attribute.sizeof*0+Attribute.begin],eax
1117 mov [ebx+Attribute.sizeof*0+Attribute.limit],eax
1118 mov [ebx+Attribute.sizeof*1+Attribute.begin],eax
1119 mov [ebx+Attribute.sizeof*1+Attribute.limit],eax
1120 mov [ebx+Attribute.sizeof*2+Attribute.begin],eax
1121 mov [ebx+Attribute.sizeof*2+Attribute.limit],eax
1122 mov [ebx+Attribute.sizeof*3+Attribute.begin],eax
1123 mov [ebx+Attribute.sizeof*3+Attribute.limit],eax
1124 add ebx,Attribute.sizeof*4
1125 dec ecx
1126 jnz .xm4
1127
1128.xm0: pop eax
1129;[cf]
1130 call readAttributes
1131 pop edi
1132 pop edx
1133 jz readContent
1134 ret
1135;[c]
1136.element: mov ebx,[edx+ElementClass.offset]
1137 cmp [edi+ebx+Attribute.begin],0
1138 jnz .elementDefined
1139 mov [edi+ebx+Attribute.begin],ecx
1140 jmp .resume2
1141
1142.elementDefined:
1143 pop edx
1144 jmp elementDefined
1145;[c]
1146.chunkFull: push eax
1147 push edx
1148 push edi
1149 mov eax,[edx+ElementClass.size]
1150 call extendMemory
1151 mov ecx,edi
1152 pop edi
1153 pop edx
1154 pop eax
1155 jz .resume
1156 pop edx
1157 jmp parseOutOfMemory
1158;[cf]
1159;[c]
1160terminalElement:
1161 add ecx,1
1162 mov bl,[ecx-3]
1163
1164;[of]:Skip Blanks
1165 test byte [S + eax], 1
1166 jz .eNotBlank1
1167.eSkipBlank1: movzx eax,byte [esi]
1168 add esi,1
1169 test byte [S + eax], 1
1170 jnz .eSkipBlank1
1171.eNotBlank1:
1172;[cf]
1173
1174 test bl,1
1175 jz readChildElement
1176 jmp readText
1177;[cf]
1178;[of]:Skip comment
1179skipCommentOrCDATA:
1180 add esi,1
1181 movzx eax,byte [esi]
1182 add esi,1
1183 cmp al,'-'
1184 jz .comment
1185;[c]
1186.CDATA: cmp al,'['
1187 jnz invalidChar
1188 cmp byte [esi],'C'
1189 jnz invalidChar
1190 cmp byte [esi+1],'D'
1191 jnz invalidChar
1192 cmp byte [esi+2],'A'
1193 jnz invalidChar
1194 cmp byte [esi+3],'T'
1195 jnz invalidChar
1196 cmp byte [esi+4],'A'
1197 jnz invalidChar
1198 cmp byte [esi+5],'['
1199 jnz invalidChar
1200 add esi,6
1201
1202.cd1: movzx eax,byte [esi]
1203 add esi,1
1204 or al,al
1205 jz unexpectedEnd
1206 cmp al,']'
1207 jnz .cd1
1208 movzx eax,byte [esi]
1209 cmp al,']'
1210 jnz .cd1
1211 mov al,[esi+1]
1212 cmp al,'>'
1213 jnz .cd1
1214 add esi,2
1215 jmp readContent
1216;[c]
1217.comment: call readComment
1218 jnz return
1219 jmp readContent
1220;[cf]
1221;[of]:Skip processing instruction
1222skipContentPI: call readPI
1223 jnz return
1224 jmp readContent
1225;[cf]
1226;[c]
1227;[of]:Read Inner Text
1228;[c]Read a Text-Only Element
1229;[c]
1230;[c] * esi is the source
1231;[c] * edi is the element
1232;[c] * edx is the type of the element
1233;[c]
1234;[c] * al is the last non blank character in the tag (must be '>')
1235;[c]
1236readInnerText: lea ebx,[edi+Element.sizeof]
1237 mov [ebx+Attribute.begin],esi
1238
1239 mov ecx,'&' * 256 + '<'
1240
1241 movzx eax,byte [esi]
1242 add esi,1
1243 cmp al,cl
1244 jz innerEmptyOrCDATAOrPI
1245 or al,al
1246 jz unexpectedEnd
1247 cmp al,ch
1248 jz innerTextReference
1249
1250.loop: movzx eax,byte [esi]
1251 add esi,1
1252 or al,al
1253 jz unexpectedEnd
1254 cmp al,ch
1255 jz innerTextReference
1256 cmp al,cl
1257 jnz .loop
1258
1259 movzx eax,byte [esi]
1260 cmp al,'!'
1261 jz innerTextCommentOrCDATA
1262 cmp al,'?'
1263 jz innerPI
1264
1265innerEndOfEmptyText:
1266 dec esi
1267 mov [ebx+Attribute.limit],esi
1268 inc esi
1269
1270innerEndOfText: cmp al, '/'
1271 jnz invalidChar
1272 jmp readCloseTag
1273;[c]
1274innerEmptyOrCDATAOrPI:
1275 movzx eax,byte [esi]
1276 cmp al,'?'
1277 jz innerPI
1278 cmp al,'!'
1279 jnz innerEndOfEmptyText
1280 cmp byte [esi+1],'['
1281 jnz innerInvalidCharOrComment
1282 cmp byte [esi+2],'C'
1283 jnz invalidChar
1284 cmp byte [esi+3],'D'
1285 jnz invalidChar
1286 cmp byte [esi+4],'A'
1287 jnz invalidChar
1288 cmp byte [esi+5],'T'
1289 jnz invalidChar
1290 cmp byte [esi+6],'A'
1291 jnz invalidChar
1292 cmp byte [esi+7],'['
1293 jnz invalidChar
1294 add esi,8
1295 mov [ebx+Attribute.begin],esi
1296
1297.loop: movzx eax,byte [esi]
1298 add esi,1
1299 or al,al
1300 jz unexpectedEnd
1301 cmp al,']'
1302 jnz .loop
1303 movzx eax,byte [esi]
1304 cmp al,']'
1305 jnz .loop
1306 mov al,[esi+1]
1307 cmp al,'>'
1308 jnz .loop
1309
1310 mov al,[esi+2]
1311 cmp al,'<'
1312 jnz .mixed
1313
1314 sub esi,1
1315 mov [ebx+Attribute.limit],esi
1316 add esi,4
1317 movzx eax,byte [esi]
1318 jmp innerEndOfText
1319;[c]
1320;[c]The text starts with a CDATA section but contain something else,
1321;[c]let 's read it again with the slow method
1322;[c]
1323.mixed: mov esi,[ebx+Attribute.begin]
1324 sub esi,9 ; size("<![CDATA[")
1325 mov [ebx+Attribute.begin],esi
1326 call readValue
1327 jmp innerEndOfText
1328;[c]
1329innerTextCommentOrCDATA:
1330innerTextReference:
1331innerInvalidCharOrComment:
1332innerPI:
1333 sub esi,1
1334 call readValue
1335 jmp innerEndOfText
1336;[cf]
1337;[of]:Read PCDATA
1338;[c]Read Character Data in a mixed content element
1339;[c]
1340;[c] * esi source
1341;[c] * edx type of element
1342;[c] * edi the element
1343;[c]
1344readPCDATA: ; Check that the segment is not empty
1345 movzx eax,byte [esi]
1346 cmp al,'<'
1347 jz interEmptyOrCDATA
1348 or al,al
1349 jz unexpectedEnd
1350
1351 ; Allocate memory for element
1352interResume0: mov ecx,[ebp+ParseContext.base]
1353 lea ebx,[ecx+Element.sizeof+Attribute.sizeof]
1354 cmp ebx,[ebp+ParseContext.limit]
1355 jae interChunkFull
1356 mov [ebp+ParseContext.base],ebx
1357interResume:
1358 ; Append CharData element
1359 cmp dword [edi+Element.firstChild],0
1360 jnz .rce1
1361 mov [edi+Element.firstChild],ecx
1362.rce1: mov ebx,[edi+Element.lastChild]
1363 or ebx,ebx
1364 jz .rce2
1365 mov [ebx+Element.nextSibling],ecx
1366.rce2: mov [edi+Element.lastChild],ecx
1367
1368 ; Initialize element
1369 ; Children fields (firstchild, ...)
1370 ; are not initialized
1371 sub ebx,ebx
1372 mov [ecx+Element.id],ebx
1373 mov [ecx+Element.nextSibling],ebx
1374 mov [ecx+Element.sizeof+Attribute.begin],esi
1375 lea ebx,[ecx+Element.sizeof]
1376 add esi,1
1377 jmp .first
1378
1379.loop: movzx eax,byte [esi]
1380 add esi,1
1381 or al,al
1382 jz unexpectedEnd
1383.first: cmp al,'&'
1384 jz interTextReference
1385 cmp al,'<'
1386 jnz .loop
1387
1388 movzx eax,byte [esi]
1389 cmp al,'!'
1390 jz interTextCommentOrCDATA
1391 cmp al,'?'
1392 jz interTextPI
1393
1394 dec esi
1395 mov [ebx+Attribute.limit],esi
1396 inc esi
1397
1398interEndOfText: cmp al, '/'
1399 jnz referenceOrComment
1400 jmp readCloseTag
1401;[c]
1402interEmptyOrCDATA: ; or comment
1403 add esi,1
1404 movzx eax,byte [esi]
1405 cmp al,'?'
1406 jz .resume
1407 cmp al,'!'
1408 jnz interEndOfText
1409.resume: sub esi,1
1410 movzx eax,byte [esi]
1411 jmp interResume0
1412;[c]
1413interTextCommentOrCDATA:
1414interTextReference:
1415interTextPI:
1416 sub esi,1
1417 call readValue
1418 jmp interEndOfText
1419;[c]
1420interChunkFull: push eax
1421 push edx
1422 push edi
1423 mov eax,Element.sizeof + Attribute.sizeof
1424 call extendMemory
1425 mov ecx,edi
1426 pop edi
1427 pop edx
1428 pop eax
1429 jz interResume
1430 jmp parseOutOfMemory
1431;[cf]
1432;[cf]
1433;[of]: attributeReference
1434attributeReference:
1435 push ecx
1436 push edx
1437 push edi
1438;[c]
1439;[c]Count chars
1440;[c]
1441 mov ah,cl
1442 lea ecx,[esi-1]
1443.l1: mov al,[esi]
1444 add esi,1
1445 or al,al
1446 jz .unexpectedEnd
1447 cmp al,ah
1448 jnz .l1
1449 mov edx,esi
1450 mov esi,[ebx+Attribute.begin]
1451 sub ecx,esi ; length of first part
1452 sub edx,esi ; maximum length
1453;[c]
1454;[c]Pre-reserve sufficient space
1455;[c]
1456 mov edi,[ebp+ParseContext.base]
1457 add edx,edi
1458 cmp edx,[ebp+ParseContext.limit]
1459 jae .chunkFull
1460.resume: mov [ebx+Attribute.begin],edi
1461;[c]
1462;[c]Copy first part
1463;[c]
1464 rep
1465 movsb
1466 add esi,1
1467
1468 mov cl,ah ; restore sting delimiter
1469 xor ah,ah ; restore ah to 0
1470;[c]
1471;[c]Copy remaining chars
1472;[c]
1473;[c] Note: it is no longer required to check for unexpected end in
1474;[c] this loop since we have already scanned the value while counting
1475;[c] chars.
1476;[c]
1477.decode: call decodeReference
1478.loop: stosb
1479 movzx eax,byte [esi]
1480 add esi,1
1481 cmp al,'&'
1482 jz .decode
1483 cmp al,cl
1484 jnz .loop
1485
1486 mov [ebx+Attribute.limit],edi
1487;[c]
1488;[c]Free remaining space (align on the next dword)
1489;[c]
1490 add edi,3
1491 and edi,not 3
1492 mov [ebp+ParseContext.base],edi
1493 pop edi
1494 pop edx
1495 pop ecx
1496
1497 ; Terminate this attribute and go to the next one
1498 jmp endOfAttribute
1499;[c]
1500.chunkFull: push eax
1501 push ecx
1502 push edx
1503 mov eax,edx
1504 sub eax,edi
1505 call extendMemory
1506 pop edx
1507 pop ecx
1508 pop eax
1509 jz .resume
1510
1511 pop edi
1512 pop edx
1513 pop ecx
1514 jmp parseOutOfMemory
1515;[c]
1516.unexpectedEnd: pop edi
1517 pop edx
1518 pop ecx
1519 jmp unexpectedEnd
1520;[cf]
1521
1522;[cf]
1523;[of]: readValue
1524;[c]Read a text value
1525;[c]
1526;[c]ARGUMENTS
1527;[c] ebx
1528;[c] attribute (begin contains the beginning of text)
1529;[c] esi
1530;[c] source points to first special char (< or &)
1531;[c]
1532readValue: push ecx
1533 push edx
1534 push edi
1535;[c]
1536;[c]Count chars
1537;[c]
1538 mov ecx,esi
1539 mov esi,[ebx+Attribute.begin]
1540 sub ecx,esi ; length of first part
1541;[c]
1542;[c]Pre-reserve sufficient space
1543;[c]
1544 mov edi,[ebp+ParseContext.base]
1545 lea edx,[edi+ecx]
1546 cmp edx,[ebp+ParseContext.limit]
1547 jae .chunkFull
1548.resume: mov [ebx+Attribute.begin],edi
1549;[c]
1550;[c]Copy first part
1551;[c]
1552 rep movsb
1553;[c]
1554;[c]Copy remaining chars
1555;[c]
1556;[c] Note: it is no longer to check for unexpected end in this loop since
1557;[c] we have already scanned the value while counting chars.
1558;[c]
1559 mov ecx,[ebp+ParseContext.limit]
1560 sub ecx,edi
1561 jmp .decodeContent
1562
1563.decode: call decodeReference
1564.loop: stosb
1565 sub ecx,1
1566 jz .realloc1
1567.decodeContent: movzx eax,byte [esi]
1568 add esi,1
1569 cmp al,'&'
1570 jz .decode
1571 cmp al,'<'
1572 jnz .loop
1573 movzx eax,byte [esi]
1574 cmp al,'!'
1575 jz .CDATAOrComment
1576 cmp al,'?'
1577 jz .PI
1578
1579 mov [ebx+Attribute.limit],edi
1580;[c]
1581;[c]Free remaining space (align on the next dword)
1582;[c]
1583 add edi,3
1584 and edi,not 3
1585 mov [ebp+ParseContext.base],edi
1586 pop edi
1587 pop edx
1588 pop ecx
1589
1590 ; Terminate this attribute and go to the next one
1591 movzx eax,byte [esi]
1592 ret
1593;[c]
1594.chunkFull: push ecx
1595 lea eax,[ecx+1] ; at least one extra char
1596 call extendMemory
1597 pop ecx
1598 jnz .outOfMemory
1599 jmp .resume
1600;[c]
1601.realloc1: call .realloc
1602 jmp .decodeContent
1603;[c]
1604.realloc: mov eax,edi
1605 sub eax,[ebx+Attribute.begin]
1606 add eax,[ebp+MemoryContext.chunkSize]
1607 add eax,3
1608 and eax,not 3
1609 push edi
1610 call extendMemory
1611 pop ecx
1612 jnz .outOfMemory1
1613
1614 push esi
1615 mov esi,[ebx+Attribute.begin]
1616 mov [ebx+Attribute.begin],edi
1617 sub ecx,esi
1618 rep movsb
1619 add esi,1
1620 mov ecx,[ebp+ParseContext.limit]
1621 sub ecx,edi
1622 pop esi
1623 ret
1624;[c]
1625.outOfMemory1: add esp,4
1626.outOfMemory: pop edi
1627 pop edx
1628 pop ecx
1629 add esp,4
1630 jmp parseOutOfMemory
1631;[c]
1632.unexpectedEnd: pop edi
1633 pop edx
1634 pop ecx
1635 add esp,4
1636 jmp unexpectedEnd
1637;[c]
1638.invalidChar: pop edi
1639 pop edx
1640 pop ecx
1641 add esp,4
1642 jmp invalidChar
1643;[c]
1644.error: pop edi
1645 pop edx
1646 pop ecx
1647 add esp,4
1648 or eax,eax
1649 ret
1650;[c]
1651.CDATAOrComment:
1652 add esi,1
1653 movzx eax,byte [esi]
1654 add esi,1
1655 cmp al,'-'
1656 jz .comment
1657
1658;[of]:Read CDATA Section
1659 cmp al,'['
1660 jnz .invalidChar
1661 cmp byte [esi],'C'
1662 jnz .invalidChar
1663 cmp byte [esi+1],'D'
1664 jnz .invalidChar
1665 cmp byte [esi+2],'A'
1666 jnz .invalidChar
1667 cmp byte [esi+3],'T'
1668 jnz .invalidChar
1669 cmp byte [esi+4],'A'
1670 jnz .invalidChar
1671 cmp byte [esi+5],'['
1672 jnz .invalidChar
1673 add esi,6
1674
1675 jmp .cd2
1676.cd1: stosb
1677 sub ecx,1
1678 jz .cd3 ; chunk is full - realloc
1679.cd2: movzx eax,byte [esi]
1680 add esi,1
1681 or al,al
1682 jz .unexpectedEnd
1683 cmp al,']'
1684 jnz .cd1
1685 movzx eax,byte [esi]
1686 cmp al,']'
1687 jnz .cd1
1688 mov al,[esi+1]
1689 cmp al,'>'
1690 jnz .cd1
1691 add esi,2
1692 jmp .decodeContent
1693
1694.cd3: call .realloc
1695 jmp .cd2
1696;[cf]
1697;[of]:Skip Comments
1698.comment: call readComment
1699 jnz .error
1700 jmp .decodeContent
1701;[cf]
1702;[of]:Skip PI
1703.PI: call readPI
1704 jnz .error
1705 jmp .decodeContent
1706;[cf]
1707;[cf]
1708;[of]: decodeReference
1709decodeReference:
1710 movzx eax,byte [esi]
1711 cmp al,'#'
1712 jz .num
1713 cmp al,'a'
1714 jz .a
1715 cmp al,'l'
1716 jz .l
1717 cmp al,'g'
1718 jz .g
1719 cmp al,'q'
1720 jnz .invalidEntityReference
1721
1722 ; &quot;
1723.q: cmp byte [esi+1],'u'
1724 jnz .invalidEntityReference
1725 cmp byte [esi+2],'o'
1726 jnz .invalidEntityReference
1727 cmp byte [esi+3],'t'
1728 jnz .invalidEntityReference
1729 cmp byte [esi+4],';'
1730 jnz .invalidEntityReference
1731 add esi,5
1732 mov al,'"'
1733 ret
1734
1735.num: add esi,1
1736 xor edx,edx
1737 movzx eax,byte [esi]
1738 add esi,1
1739 cmp al,'x'
1740 jz .hexa
1741 test byte [digit+eax],1
1742 jz .invalidChar
1743.nextDigit: sub al,'0'
1744 imul edx,10
1745 jc .overflow
1746 add edx,eax
1747 jc .overflow
1748 movzx eax,byte [esi]
1749 add esi,1
1750 test byte [digit+eax],1
1751 jnz .nextDigit
1752 cmp al,';'
1753 jnz .invalidEntityReference
1754 mov eax,edx
1755 test edx,$FFFFFF00
1756 jnz .invalidChar
1757 ret
1758
1759.hexa: movzx eax,byte [esi]
1760 add esi,1
1761 test byte [digit+eax],2
1762 jz .invalidChar
1763.nextXDigit: shl edx,4
1764 jc .overflow
1765 or dl,[xdigit+eax]
1766 movzx eax,byte [esi]
1767 add esi,1
1768 test byte [digit+eax],2
1769 jnz .nextXDigit
1770 cmp al,';'
1771 jnz .invalidEntityReference
1772 mov eax,edx
1773 test edx,$FFFFFF00
1774 jnz .invalidChar
1775 ret
1776
1777.a: mov al,[esi+1]
1778 cmp al,'p'
1779 jz .ap
1780 cmp al,'m'
1781 jnz .invalidEntityReference
1782
1783 ; &amp;
1784.am: cmp byte [esi+2],'p'
1785 jnz .invalidEntityReference
1786 cmp byte [esi+3],';'
1787 jnz .invalidEntityReference
1788 add esi,4
1789 mov al,'&'
1790 ret
1791
1792 ; &apos;
1793.ap: cmp byte [esi+2],'o'
1794 jnz .invalidEntityReference
1795 cmp byte [esi+3],'s'
1796 jnz .invalidEntityReference
1797 cmp byte [esi+4],';'
1798 jnz .invalidEntityReference
1799 add esi,5
1800 mov al,$27
1801 ret
1802
1803 ; &lt;
1804.l: cmp byte [esi+1],'t'
1805 jnz .invalidEntityReference
1806 cmp byte [esi+2],';'
1807 jnz .invalidEntityReference
1808 add esi,3
1809 mov al,'<'
1810 ret
1811
1812 ; &gt;
1813.g: cmp byte [esi+1],'t'
1814 jnz .invalidEntityReference
1815 cmp byte [esi+2],';'
1816 jnz .invalidEntityReference
1817 add esi,3
1818 mov al,'>'
1819 ret
1820;[c]
1821.invalidChar: add esp,4
1822 pop edi
1823 pop edx
1824 pop ecx
1825 jmp invalidChar
1826;[c]
1827.overflow: add esp,4
1828 pop edi
1829 pop edx
1830 pop ecx
1831 jmp overflow
1832;[c]
1833.invalidEntityReference:
1834 add esp,4
1835 pop edi
1836 pop edx
1837 pop ecx
1838 jmp invalidEntityReference
1839;[cf]
1840;[of]: readProlog
1841;[c]Read the prolog
1842;[c]
1843;[c] The time is not critical here, so the code is less optimized:
1844;[c] - use of subfunctions
1845;[c] - return error code (instead of direct exit)
1846;[c]
1847;[c]ARGUMENTS
1848;[c] esi
1849;[c] source
1850;[c]
1851;[c]RETURN VALUES
1852;[c] zf+eax
1853;[c] error code (zf=0) or current char (zf=1)
1854;[c] esi
1855;[c] next source char
1856;[c]
1857readProlog: call readXMLDecl
1858 jnz return
1859 jmp readMisc
1860;[cf]
1861;[of]: readXMLDecl
1862;[c]Read the XML declaration
1863;[c]
1864;[c]ARGUMENTS
1865;[c] esi
1866;[c] next char to read
1867;[c]
1868;[c]RETURN VALUES
1869;[c] zf+eax
1870;[c] error code
1871;[c] esi
1872;[c] next char to read
1873;[c]
1874;[c]REMARKS
1875;[c] If there is no xml-decl, the function just returns the same pointer
1876;[c] and the ok flag.
1877;[c]
1878
1879 struct XDA
1880.value rd 2
1881 ends
1882
1883readXMLDecl: push edi
1884 sub esp,XDA.sizeof
1885 mov edi,esp
1886 call .goon
1887 lea esp,[esp+XDA.sizeof]
1888 pop edi
1889 ret
1890
1891.goon: cmp byte [esi],'<'
1892 jnz ok
1893 cmp byte [esi+1],'?'
1894 jnz ok
1895 cmp byte [esi+2],'x'
1896 jnz ok
1897 cmp byte [esi+3],'m'
1898 jnz ok
1899 cmp byte [esi+4],'l'
1900 jnz ok
1901 add esi,5
1902
1903 ; Read version
1904 ; ------------
1905 call readNextChar
1906 call readBlanks
1907 jnz return
1908 call readAtom
1909 jnz return
1910 cmp ecx,ATOM_VERSION
1911 jnz noVersion
1912
1913 call readXMLDeclValue
1914 jnz return
1915
1916 mov ecx,[edi+XDA.value+Attribute.begin]
1917 mov [ebp+ParseContext.version+Attribute.begin],ecx
1918 mov ecx,[edi+XDA.value+Attribute.limit]
1919 mov [ebp+ParseContext.version+Attribute.limit],ecx
1920
1921 ; Read encoding
1922 ; -------------
1923 call isXMLDeclEnd
1924 jz ok
1925 call readBlanks
1926 jnz return
1927 call isXMLDeclEnd
1928 jz return
1929 call readAtom
1930 jnz return
1931 cmp ecx,ATOM_ENCODING
1932 jnz .notEncoding
1933
1934 call readXMLDeclValue
1935 jnz return
1936
1937 mov ecx,[edi+XDA.value+Attribute.begin]
1938 mov [ebp+ParseContext.encoding+Attribute.begin],ecx
1939 mov ecx,[edi+XDA.value+Attribute.limit]
1940 mov [ebp+ParseContext.encoding+Attribute.limit],ecx
1941
1942 ; Read standalone
1943 ; ---------------
1944 call isXMLDeclEnd
1945 jz ok
1946 call readBlanks
1947 jnz return
1948 call isXMLDeclEnd
1949 jz ok
1950 call readAtom
1951 jnz return
1952.notEncoding: cmp ecx,ATOM_STANDALONE
1953 jnz invalidChar
1954
1955 call readXMLDeclValue
1956 jnz return
1957
1958 ; Terminate
1959 ; ---------
1960 call isXMLDeclEnd
1961 jz ok
1962 jmp invalidChar
1963
1964;[of]:readXMLDeclValue
1965readXMLDeclValue:
1966
1967 ; Skip blanks
1968 ; -----------
1969 call skipBlanks
1970
1971 ; Skip equals
1972 ; -----------
1973 cmp al,'='
1974 jnz invalidChar
1975 call readNextChar
1976
1977 ; Skip blanks
1978 ; -----------
1979 call skipBlanks
1980
1981 ; Skip quote
1982 ; ----------
1983 cmp al,$27 ; '
1984 jz .value
1985 cmp al,'"'
1986 jnz invalidChar
1987.value: mov cl,al
1988 mov [edi+XDA.value+Attribute.begin],esi
1989
1990.loopValue: movzx eax,byte [esi]
1991 add esi,1
1992 or al,al
1993 jz unexpectedEnd
1994 cmp al,' ' ; Let's forbid blanks
1995 jz invalidChar ;
1996 cmp al,cl
1997 jnz .loopValue
1998 lea ecx,[esi-1]
1999 mov [edi+XDA.value+Attribute.limit],ecx
2000
2001 jmp readNextChar
2002;[cf]
2003;[of]:isXMLDeclEnd
2004isXMLDeclEnd: cmp al,'?'
2005 jnz return
2006 cmp byte [esi],'>'
2007 jnz return
2008 lea esi,[esi+1]
2009 ret
2010;[cf]
2011;[cf]
2012;[of]: readMisc
2013;[c]Read stuff before or after the root element
2014;[c]
2015;[c]ARGUMENTS
2016;[c] esi
2017;[c] next char to read
2018;[c]
2019;[c]RETURN VALUES
2020;[c] zf+eax
2021;[c] error code (zf=0) or current char (zf=1)
2022;[c] esi
2023;[c] next char to read
2024;[c]
2025readMisc:
2026 ; Skip blanks
2027.sb: movzx eax,byte [esi]
2028 add esi,1
2029 test byte [S + eax], 1
2030 jnz .sb
2031
2032 cmp al,'<'
2033 jnz .done
2034
2035 cmp byte [esi],'?'
2036 jnz .notPI
2037
2038 call readPI
2039 jmp .next
2040
2041.notPI: cmp byte [esi],'!'
2042 jnz .done
2043 add esi,1
2044
2045 movzx eax,byte [esi]
2046 add esi,1
2047 cmp al,'-'
2048 jnz .notComment
2049
2050 call readComment
2051 jmp .next
2052
2053.notComment: call readDOCTYPE
2054
2055.next: jnz return
2056 jmp .sb
2057
2058.done: test eax,0
2059 ret
2060;[cf]
2061;[of]: readComment
2062;[c]Read a comment
2063;[c]
2064;[c]ARGUMENTS
2065;[c] esi
2066;[c] points to the 2nd '-' of <!--
2067;[c]
2068;[c]RETURN VALUES
2069;[c] zf+eax
2070;[c] error code
2071;[c] esi
2072;[c] next char to read
2073;[c]
2074;[c]
2075readComment: cmp byte [esi],'-'
2076 jnz invalidChar
2077 add esi,1
2078
2079.loop: movzx eax,byte [esi]
2080 add esi,1
2081 or al,al
2082 jz unexpectedEnd
2083 cmp al,'-'
2084 jnz .loop
2085 movzx eax,byte [esi]
2086 add esi,1
2087 cmp al,'-'
2088 jnz .loop
2089 movzx eax,byte [esi]
2090 add esi,1
2091 cmp al,'>'
2092 jnz invalidChar
2093
2094 xor eax,eax
2095 ret
2096;[cf]
2097;[of]: readPI
2098;[c]Reads a Processing Instruction
2099;[c]
2100;[c]ARGUMENTS
2101;[c] esi
2102;[c] points to the '?'
2103;[c]
2104;[c]RETURN VALUES
2105;[c] zf+eax
2106;[c] error code
2107;[c] esi
2108;[c] next char to read
2109;[c]
2110readPI: add esi,1
2111
2112 mov ecx,esi
2113 movzx eax,byte [esi]
2114 add esi,1
2115 call readName
2116 jnz return
2117;[c]
2118;[c] The PI target cannot be 'xml' in any case
2119;[c]
2120 cmp byte [ecx],'x'
2121 jz .m
2122 cmp byte [ecx],'X'
2123 jnz .notXML
2124.m: cmp byte [ecx+1],'m'
2125 jz .l
2126 cmp byte [ecx+1],'M'
2127 jnz .notXML
2128.l: cmp byte [ecx+2],'l'
2129 jz .xml
2130 cmp byte [ecx+2],'L'
2131 jnz .notXML
2132.xml: add ecx,4
2133 cmp esi,ecx
2134 jz invalidPI
2135;[c]
2136;[c] If there is no blank, it MUST be the end of the PI
2137;[c]
2138.notXML: cmp al,'?'
2139 jnz .notEnd
2140 movzx eax,byte [esi]
2141 add esi,1
2142 cmp al,'>'
2143 jz .ok
2144 jmp invalidChar
2145;[c]
2146;[c] It is not the end: there must be at least one blank
2147;[c]
2148.notEnd: call readBlanks
2149 jnz return
2150 jmp .next
2151;[c]
2152;[c] Read the content of the Processing Instruction
2153;[c]
2154.loop: movzx eax,byte [esi]
2155 add esi,1
2156.next: or al,al
2157 jz unexpectedEnd
2158 cmp al,'?'
2159 jnz .loop
2160 movzx eax,byte [esi]
2161 add esi,1
2162 cmp al,'>'
2163 jnz .next
2164
2165.ok: xor eax,eax
2166 ret
2167;[cf]
2168;[of]: readDOCTYPE
2169readDOCTYPE: call readAtom
2170 jnz return
2171 call readBlanks
2172 jnz return
2173
2174 cmp ecx,ATOM_DOCTYPE
2175 jnz invalidChar
2176 cmp [ebp+ParseContext.doctype],1
2177 jnz invalidDOCTYPE
2178 mov [ebp+ParseContext.doctype],0
2179
2180 call readName
2181 jnz return
2182
2183 call skipBlanks
2184 call readExternalID
2185 jnz return
2186 call skipBlanks
2187
2188 ; ('[' intSubset ']')?
2189 cmp al,'['
2190 jnz .notIntSubset
2191 call readIntSubset
2192 cmp al,']'
2193 jnz invalidChar
2194
2195 movzx eax,byte [esi]
2196 add esi,1
2197 call skipBlanks
2198
2199.notIntSubset: cmp al,'>'
2200 jnz invalidChar
2201 xor eax,eax
2202 ret
2203;[c]
2204;[c]Sub-functions
2205;[of]: readNmtoken
2206readNmtoken: jmp readName
2207;[cf]
2208;[of]: readExternalID
2209readExternalID:
2210 ; SYSTEM
2211 cmp al,'S'
2212 jz readSystem
2213
2214 ; PUBLIC
2215 cmp al,'P'
2216 jz readPublic
2217
2218 jmp ok
2219;[cf]
2220;[of]: readSystem
2221readSystem: cmp byte [esi],'Y'
2222 jnz invalidChar
2223 cmp byte [esi+1],'S'
2224 jnz invalidChar
2225 cmp byte [esi+2],'T'
2226 jnz invalidChar
2227 cmp byte [esi+3],'E'
2228 jnz invalidChar
2229 cmp byte [esi+4],'M'
2230 jnz invalidChar
2231 add esi,5
2232
2233 call readNextChar
2234 call readBlanks
2235 jnz return
2236 jmp readString
2237;[cf]
2238;[of]: readPublic
2239readPublic: cmp byte [esi],'U'
2240 jnz invalidChar
2241 cmp byte [esi+1],'B'
2242 jnz invalidChar
2243 cmp byte [esi+2],'L'
2244 jnz invalidChar
2245 cmp byte [esi+3],'I'
2246 jnz invalidChar
2247 cmp byte [esi+4],'C'
2248 jnz invalidChar
2249 add esi,5
2250
2251 call readNextChar
2252 call readBlanks
2253 jnz return
2254 call readPubidLiteral
2255 jnz return
2256
2257 ; Not a blank: there is no SystemLiteral
2258 test byte [S + eax], 1
2259 jz ok
2260
2261 call skipBlanks
2262 cmp al,$27 ; '
2263 jz readString
2264 cmp al,'"'
2265 jz readString
2266 jmp ok
2267
2268;[cf]
2269;[of]: readPubidLiteral
2270readPubidLiteral:
2271 mov cl,al
2272 cmp al,$27 ; '
2273 jz .loop
2274 cmp al,'"'
2275 jnz invalidChar
2276.loop: movzx eax,byte [esi]
2277 add esi,1
2278 or al,al
2279 jz unexpectedEnd
2280 cmp byte [PubidChar+eax],1
2281 jnz invalidChar
2282 cmp al,cl
2283 jnz .loop
2284 jmp readNextChar
2285;[cf]
2286;[of]: readString
2287readString: mov cl,al
2288 cmp al,$27 ; '
2289 jz .loop
2290 cmp al,'"'
2291 jnz invalidChar
2292.loop: mov al,[esi]
2293 add esi,1
2294 or al,al
2295 jz unexpectedEnd
2296 cmp al,cl
2297 jnz .loop
2298 jmp readNextChar
2299;[cf]
2300;[of]: readIntSubset
2301readIntSubset:
2302
2303 ; Skip blanks
2304.loop: movzx eax,byte [esi]
2305 add esi,1
2306
2307.first: test byte [S + eax], 1
2308 jnz .loop
2309
2310 cmp al,'%'
2311 jnz .notPERef
2312 call readPERef
2313 jmp .next
2314
2315.notPERef: cmp al,'<'
2316 jnz ok
2317
2318 cmp byte [esi],'?'
2319 jnz .notPI
2320 call readPI
2321 jmp .next
2322
2323.notPI: cmp byte [esi],'!'
2324 jnz ok
2325 add esi,1
2326
2327 movzx eax,byte [esi]
2328 add esi,1
2329 cmp al,'-'
2330 jnz .notComment
2331 call readComment
2332 jmp .next
2333
2334.notComment: call readDecl
2335
2336.next: jz .loop
2337 ret
2338;[cf]
2339;[of]: readPERef
2340readPERef: call readNextChar
2341 call readName
2342 jnz return
2343 cmp al,';'
2344 jnz invalidChar
2345 jmp ok
2346;[cf]
2347;[of]: readDecl
2348readDecl: call readAtom
2349 jnz return
2350 call readBlanks
2351 jnz return
2352
2353 cmp ecx,ATOM_ELEMENT
2354 jz .element
2355 cmp ecx,ATOM_ATTLIST
2356 jz .attlist
2357 cmp ecx,ATOM_ENTITY
2358 jz .entity
2359 cmp ecx,ATOM_NOTATION
2360 jz .notation
2361 jmp invalidChar
2362;[c]
2363.element: call readName
2364 jnz return
2365 call readBlanks
2366 jnz return
2367 call readContentSpec
2368 jmp .common
2369;[c]
2370.attlist: call readName
2371 jnz return
2372 call readAttDefs
2373 jmp .common
2374;[c]
2375.entity: cmp al,'%'
2376 jnz .notPE
2377
2378 call readNextChar
2379 call readBlanks
2380 jnz return
2381 call readName
2382 jnz return
2383 call readBlanks
2384 jnz return
2385 call readPEDef
2386 jmp .common
2387
2388.notPE: call readName
2389 jnz return
2390 call readBlanks
2391 jnz return
2392 call readEntityDef
2393 jmp .common
2394;[c]
2395.notation: call readName
2396 jnz return
2397 call readBlanks
2398 jnz return
2399 call readExternalID
2400
2401.common: jnz return
2402 call skipBlanks
2403 cmp al,'>'
2404 jnz invalidChar
2405 jmp ok
2406;[cf]
2407;[of]: readAttDefs
2408readAttDefs:
2409.loop: ; Not a blank: the list is terminated
2410 test byte [S + eax], 1
2411 jz ok
2412
2413 call skipBlanks
2414
2415 ; Not a name: the list is terminated
2416 cmp byte [terminalChar+eax],1
2417 jnz ok
2418
2419 call readName
2420 jnz return
2421 call readBlanks
2422 jnz return
2423 call readAttType
2424 jnz return
2425 call readBlanks
2426 jnz return
2427 call readDefaultDecl
2428 jnz return
2429
2430 jmp .loop
2431;[cf]
2432;[of]: readAttType
2433readAttType: cmp al,'('
2434 jz .list
2435
2436 call readAtom
2437 jnz return
2438
2439 cmp ecx,ATOM_CDATA
2440 jc invalidChar
2441 cmp ecx,ATOM_NOTATION + 1
2442 jnc invalidChar
2443
2444 cmp ecx,ATOM_NOTATION
2445 jnz ok
2446;[c]
2447;[c] 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
2448;[c]
2449 call readBlanks
2450 jnz return
2451 cmp al,'('
2452 jnz invalidChar
2453
2454.loop: call readNextChar
2455 call skipBlanks
2456 call readName
2457 jnz return
2458 call skipBlanks
2459 cmp al,'|'
2460 jz .loop
2461
2462 jmp .common
2463;[c]
2464;[c] '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
2465;[c]
2466.list: call readNextChar
2467 call skipBlanks
2468 call readNmtoken
2469 jnz return
2470 call skipBlanks
2471 cmp al,'|'
2472 jz .list
2473
2474.common: or al,al
2475 jz unexpectedEnd
2476 cmp al,')'
2477 jnz invalidChar
2478 jmp readNextChar
2479;[cf]
2480;[of]: readDefaultDecl
2481readDefaultDecl:
2482 cmp al,'#'
2483 jnz readAttValue
2484 call readNextChar
2485 call readAtom
2486 jnz return
2487 cmp ecx,ATOM_IMPLIED
2488 jz ok
2489 cmp ecx,ATOM_REQUIRED
2490 jz ok
2491 cmp ecx,ATOM_FIXED
2492 jnz invalidChar
2493
2494 call readBlanks
2495 jnz return
2496 jmp readAttValue
2497;[cf]
2498;[of]: readEntityDef
2499readEntityDef: cmp al,$27 ; '
2500 jz readEntityValue
2501 cmp al,'"'
2502 jz readEntityValue
2503
2504 call readExternalID
2505 jnz return
2506
2507 ; if the next char is not a blank: it can't be a NDATA
2508 test byte [S + eax],1
2509 jz ok
2510
2511 call skipBlanks
2512 call readAtom
2513 jnz return
2514 cmp ecx,ATOM_NDATA
2515 jnz ok
2516 call readBlanks
2517 jnz return
2518 jmp readName
2519;[cf]
2520;[of]: readPEDef
2521readPEDef: cmp al,$27 ; '
2522 jz readEntityValue
2523 cmp al,'"'
2524 jz readEntityValue
2525 jmp readExternalID
2526;[cf]
2527
2528;[of]: readContentSpec
2529readContentSpec:
2530 ;
2531 ; Name Cardinality
2532 ;
2533 cmp byte [terminalChar+eax],1
2534 jnz .notName
2535 call readName
2536 jnz return
2537 jmp readCardinality
2538
2539 ;
2540 ; #PCDATA
2541 ;
2542.notName: cmp al,'#'
2543 jnz .notPCDATA
2544 call readNextChar
2545 call readAtom
2546 jnz return
2547 cmp ecx,ATOM_PCDATA
2548 jnz invalidChar
2549 jmp ok
2550
2551 ;
2552 ; Group
2553 ;
2554.notPCDATA: cmp al,'('
2555 jnz ok
2556
2557.next: movzx eax,byte [esi]
2558 add esi,1
2559 call skipBlanks
2560 call readContentSpec
2561 jnz return
2562 call skipBlanks
2563
2564 cmp al,'|'
2565 jz .next
2566 cmp al,','
2567 jz .next
2568 cmp al,')'
2569 jnz invalidChar
2570 call readNextChar
2571 jmp readCardinality
2572;[cf]
2573;[of]: readCardinality
2574readCardinality:
2575 cmp al,'+'
2576 jz readNextChar
2577 cmp al,'?'
2578 jz readNextChar
2579 cmp al,'*'
2580 jz readNextChar
2581 jmp ok
2582;[cf]
2583;[of]: readEntityValue
2584readEntityValue:
2585 jmp readAttValue
2586;[cf]
2587;[of]: readAttValue
2588readAttValue: cmp al,$27 ; '
2589 jz .value
2590 cmp al,'"'
2591 jnz invalidChar
2592.value: mov cl,al
2593.loop: mov al,[esi]
2594 add esi,1
2595 ;cmp al,'<' ; readEntityValue accepts '<'
2596 ;jz invalidChar
2597 or al,al
2598 jz unexpectedEnd
2599 cmp al,cl
2600 jnz .loop
2601 jmp readNextChar
2602;[cf]
2603;[cf]
2604
2605;[of]: readAtom
2606;[c]Read an atom
2607;[c]
2608;[c]ARGUMENTS
2609;[c] eax
2610;[c] current char
2611;[c] esi
2612;[c] next char to read
2613;[c]
2614;[c]RETURN VALUES
2615;[c] zf+eax
2616;[c] error code (zf=0) or first non blank char following atom
2617;[c] esi
2618;[c] next char to read
2619;[c] ecx
2620;[c] the atom id or -1 if not found
2621;[c]
2622readAtom: push ebx
2623 push edx
2624 push edi
2625
2626 ;
2627 ; Read the atom name
2628 ;
2629 lea ebx,[esi-1] ; beginning of the atom
2630 jmp .first
2631.loop: mov al,[esi]
2632 add esi,1
2633.first: cmp al,'A'
2634 jc .endOfAtom
2635 cmp al,'Z'+1
2636 jc .loop
2637 cmp al,'a'
2638 jc .endOfAtom
2639 cmp al,'z'+1
2640 jc .loop
2641.endOfAtom: lea edx,[esi-1] ; end of the atom
2642
2643 ;
2644 ; Find the atom in the table
2645 ;
2646 push esi
2647
2648 cmp ebx,edx
2649 jz .noMatch
2650
2651 sub ecx,ecx ; the atom
2652 dec ecx
2653.compareAtom: inc ecx
2654 mov edi,[atomTable+ecx*4]
2655 or edi,edi
2656 jz .noMatch
2657 mov esi,ebx
2658.compare: cmpsb
2659 jnz .compareAtom
2660 cmp esi,edx
2661 jnz .compare
2662 cmp byte [edi], 0
2663 jnz .compareAtom
2664
2665.done: pop esi
2666 pop edi
2667 pop edx
2668 pop ebx
2669 test eax,0
2670 ret
2671
2672.noMatch: sub ecx,ecx
2673 dec ecx
2674 jmp .done
2675;[cf]
2676;[of]: readName
2677readName:
2678 ; there must be at least one char
2679 cmp byte [terminalChar+eax],1
2680 jnz invalidChar
2681
2682.loop: movzx eax,byte [esi]
2683 add esi,1
2684 cmp byte [terminalChar+eax],1
2685 jz .loop
2686 test eax,0
2687 ret
2688;[cf]
2689;[of]: readNextChar
2690readNextChar: movzx eax,byte [esi]
2691 add esi,1
2692 jmp ok
2693;[cf]
2694;[of]: readBlanks
2695;[c]There must be at least one blank
2696;[c]
2697readBlanks: test byte [S + eax], 1
2698 jz invalidChar
2699
2700 movzx eax,byte [esi]
2701 add esi,1
2702 call skipBlanks
2703 test eax,0
2704 ret
2705;[cf]
2706;[of]: skipBlanks
2707;[c]Skip blanks
2708;[c]
2709;[c]ARGUMENTS
2710;[c] eax
2711;[c] the current char
2712;[c] esi
2713;[c] the address of the next char
2714;[c]
2715;[c]RETURN VALUES
2716;[c] eax
2717;[c] the first non blank char
2718;[c] esi
2719;[c] the address of the next char
2720;[c]
2721skipBlanks: test byte [S + eax], 1
2722 jz .done
2723.loop: movzx eax,byte [esi]
2724 add esi,1
2725 test byte [S + eax], 1
2726 jnz .loop
2727.done: ret
2728;[cf]
2729;[c]
2730;[c]Recoverable Errors...
2731;[c]
2732;[of]: parseChunkFull
2733parseChunkFull: push ecx
2734 push edx
2735 mov eax,[edx+ElementClass.size]
2736 call extendMemory
2737 pop edx
2738 pop ecx
2739 jz resumeParseChunkFull
2740 ret
2741;[cf]
2742;[of]: invalidAttribute
2743invalidAttribute:
2744 cmp [ebp+ParseContext.strict],0
2745 jnz .invalid
2746
2747 ; We are in a non-strict mode, this
2748 ; unknown attribute must just be ignored, so
2749 ; we read all chars until the first '=' char
2750 ; no matter whether the char is valid or not.
2751 ;
2752 jmp .first
2753.loop: movzx eax,byte [esi]
2754 add esi,1
2755.first: or al,al
2756 jz unexpectedEnd
2757 cmp al,'='
2758 jnz .loop
2759
2760 ; set offset to the 'ignored' slot and resume
2761 ; reading the attribute's value.
2762 ;
2763 mov ebx,edi
2764 add ebx,Element.reserved
2765 jmp readAttributeValue
2766
2767.invalid: mov eax,RC_INVALID_ATTRIBUTE
2768 or eax,eax
2769 ret
2770;[cf]
2771;[of]: invalidElement
2772invalidElement: cmp [ebp+ParseContext.strict],0
2773 jnz invalidChar
2774
2775 ; We are in a non-strict mode, this
2776 ; unknown attribute must just be ignored, so
2777 ; we read all chars until the first '=' char
2778 ; no matter whether the char is valid or not.
2779 ;
2780 jmp .first
2781.loop: movzx eax,byte [esi]
2782 add esi,1
2783.first: or al,al
2784 jz unexpectedEnd
2785 cmp byte [terminalChar+eax],1
2786 jz .loop
2787
2788;[of]:Skip Blanks
2789 test byte [S + eax], 1
2790 jz .eNotBlank1
2791.eSkipBlank1: movzx eax,byte [esi]
2792 add esi,1
2793 test byte [S + eax], 1
2794 jnz .eSkipBlank1
2795.eNotBlank1:
2796;[cf]
2797
2798 ; Read content using the invalid class and invalid element
2799 push edx
2800 push edi
2801 mov edx,invalidClass
2802 lea edi,[ebp+ParseContext.invalidElement]
2803 call readAttributes
2804 pop edi
2805 pop edx
2806 jz readContent
2807 ret
2808;[cf]
2809;[of]: closeTagMismatch
2810closeTagMismatch:
2811 cmp [ebp+ParseContext.strict],0
2812 jnz tagMismatch
2813
2814 ; We are in a non-strict mode, this
2815 ; unknown attribute must just be ignored, so
2816 ; we read all chars until the first '>' char
2817 ; no matter whether the char is valid or not.
2818 ;
2819.loop: movzx eax,byte [esi]
2820 add esi,1
2821 or al,al
2822 jz unexpectedEnd
2823 cmp al, '>'
2824 jnz .loop
2825
2826 xor eax,eax ; element successfully read
2827 ret
2828;[cf]
2829;[c]
2830;[c]Errors...
2831;[c]
2832;[of]: ok
2833ok: test eax,0
2834return: ret
2835;[cf]
2836;[of]: invalidEntityReference
2837invalidEntityReference:
2838 mov eax,RC_INVALID_ENTITY_REFERENCE
2839 or eax,eax
2840 ret
2841;[cf]
2842;[of]: unexpectedEnd
2843unexpectedEnd: mov eax,RC_UNEXPECTED_END
2844 or eax,eax
2845 ret
2846;[cf]
2847;[of]: invalidChar
2848invalidChar: mov eax,RC_INVALID_CHAR
2849 or eax,eax
2850 ret
2851;[cf]
2852;[of]: invalidPI
2853invalidPI: mov eax,RC_INVALID_PI
2854 or eax,eax
2855 ret
2856;[cf]
2857;[of]: overflow
2858overflow: mov eax,RC_OVERFLOW
2859 or eax,eax
2860 ret
2861;[cf]
2862;[of]: notStartTag
2863notStartTag: mov eax,RC_NO_START_TAG
2864 or eax,eax
2865 ret
2866;[cf]
2867;[of]: tagMismatch
2868tagMismatch: mov eax,RC_TAG_MISMATCH
2869 or eax,eax
2870 ret
2871;[cf]
2872;[of]: invalidTag
2873invalidTag: mov eax,RC_INVALID_TAG
2874 or eax,eax
2875 ret
2876;[cf]
2877;[of]: parseOutOfMemory
2878parseOutOfMemory:
2879 mov eax,RC_MEMORY
2880 or eax,eax
2881 ret
2882;[cf]
2883;[of]: attributeDefined
2884attributeDefined:
2885 mov eax,RC_ATTR_DEFINED
2886 or eax,eax
2887 ret
2888;[cf]
2889;[of]: elementDefined
2890elementDefined:
2891 mov eax,RC_ELEM_DEFINED
2892 or eax,eax
2893 ret
2894;[cf]
2895;[of]: invalidDOCTYPE
2896invalidDOCTYPE:
2897 mov eax,RC_INVALID_DOCTYPE
2898 or eax,eax
2899 ret
2900;[cf]
2901;[of]: noVersion
2902noVersion: mov eax,RC_VERSION_EXPECTED
2903 or eax,eax
2904 ret
2905;[cf]
2906;[cf]
2907;[of]:computeLineColumn
2908;[c]Read the text file again nd setup line and column
2909;[c]
2910;[c] It is faster to count lines only when an error occurs. So the parsing
2911;[c] routine does not compute lines and if an error occurs, the file is
2912;[c] read again just to find the line and column of the last read byte.
2913;[c]
2914;[c]ARGUMENTS
2915;[c] esi
2916;[c] the position of the last read byte
2917;[c] ebp
2918;[c] the parse context
2919;[c]
2920;[c]RETURN VALUES
2921;[c] [ebp+ParseContext.line]
2922;[c] the line
2923;[c] [ebp+ParseContext.column]
2924;[c] the column
2925;[c]
2926computeLineColumn:
2927 push ebx
2928 push esi
2929 push edi
2930
2931 mov edi,esi
2932 mov esi,[ebp+ParseContext.source]
2933 mov ecx,1 ; line number
2934 mov edx,esi ; beginning of line
2935 cmp esi,edi
2936 jz .continue
2937
2938.loop1: movzx eax,byte [esi]
2939 add esi,1
2940 cmp al,13
2941 jz .CR
2942 cmp al,10
2943 jz .LF
2944.next: cmp esi,edi
2945 jnz .loop1
2946 jmp .continue
2947
2948.CR: cmp esi,edi
2949 jz .LF
2950 cmp byte [esi],10
2951 jnz .LF
2952 add esi,1
2953.LF: add ecx,1
2954 mov edx,esi
2955 jmp .next
2956
2957.continue: mov [ebp+ParseContext.line],ecx
2958
2959 ;
2960 ; Compute column by expanding tabs
2961 ;
2962
2963 mov esi,edx
2964 xor ecx,ecx ; column
2965 mov edx,TAB_SIZE ; next tab
2966 cmp esi,edi
2967 jz .continue2
2968.loop2: movzx eax,byte [esi]
2969 add esi,1
2970 cmp al,9
2971 jnz .notTab
2972 mov ecx,edx
2973 add edx,TAB_SIZE
2974 cmp esi,edi
2975 jnz .loop2
2976 jmp .continue2
2977.notTab: add ecx,1
2978 cmp esi,edi
2979 jnz .loop2
2980
2981.continue2: inc ecx
2982 mov [ebp+ParseContext.column],ecx
2983
2984 pop edi
2985 pop esi
2986 pop ebx
2987 ret
2988;[cf]
2989
2990;[of]:initializeClassParser
2991;[c]Initialize the class parser
2992;[c]
2993;[c]ARGUMENTS
2994;[c] ebp
2995;[c] the parse context
2996;[c]
2997;[c]RETURN VALUES
2998;[c] eax+zf
2999;[c] error code
3000;[c]
3001initializeClassParser:
3002 mov eax,DEFAULT_CHUNK_SIZE
3003 xor ecx,ecx
3004 mov [ebp+ParseContext.chunkSize],eax
3005 mov [ebp+ParseContext.chunks],ecx
3006 jmp newChunk
3007;[cf]
3008;[of]:releaseClassParser
3009;[c]Release the class parser
3010;[c]
3011;[c]ARGUMENTS
3012;[c] ebp
3013;[c] the class parser
3014;[c]
3015releaseClassParser:
3016 jmp releaseChunks
3017;[cf]
3018;[of]:classFromString
3019;[c]Create a class from a string
3020;[c]
3021;[c]ARGUMENTS
3022;[c] esi
3023;[c] the xml string describing the class
3024;[c] ebp
3025;[c] the class context.
3026;[c]
3027;[c]RETURN VALUE
3028;[c] eax+zf
3029;[c] error code
3030;[c]
3031classFromString:
3032 push esi
3033 push edi
3034 push ebp
3035 mov edi,ebp
3036
3037 sub esp,ParseContext.sizeof
3038 mov ebp,esp
3039 mov ecx,16384
3040 call initializeParser
3041 jnz .error
3042
3043 mov edx,SchemaClass
3044 push edi
3045 call parse
3046 pop edi
3047 jz .ok
3048
3049 push eax
3050 call computeLineColumn
3051 pop eax
3052 mov ecx,[ebp+ParseContext.line]
3053 mov edx,[ebp+ParseContext.column]
3054 mov [edi+CreateClassContext.line],ecx
3055 mov [edi+CreateClassContext.column],edx
3056 jmp .error2
3057
3058.ok: mov esi,[ebp+ParseContext.root]
3059 mov ebp,edi
3060 call classFromElement
3061 mov ebp,esp
3062
3063.error2: push eax
3064 call releaseParser
3065 pop eax
3066
3067.error: add esp,ParseContext.sizeof
3068 or eax,eax
3069 pop ebp
3070 pop edi
3071 pop esi
3072 ret
3073;[cf]
3074;[of]:classFromElement
3075;[c]Create a class from an element
3076;[c]
3077;[c]ARGUMENTS
3078;[c] ebp
3079;[c] the create class context
3080;[c] esi
3081;[c] root element
3082;[c]
3083;[c]RETURN VALUES
3084;[c] eax+zf
3085;[c] error code
3086;[c]
3087classFromElement:
3088 push ebx
3089 push esi
3090 push edi
3091 mov [ebp+CreateClassContext.rootElement],esi
3092
3093 ;
3094 ; Declare all global classes
3095 ;
3096 mov eax,esi
3097 call declareGlobalClasses
3098 jnz .error
3099
3100 ;
3101 ; Define all global classes
3102 ;
3103 mov esi,[esi+Element.firstChild]
3104 mov edx,[ebp+CreateClassContext.classes]
3105 mov ebx,ebp
3106 jmp .first
3107.loop: mov edi,[edx]
3108 add edx,4
3109 push edx
3110 call initializeClass
3111 pop edx
3112 jnz .error
3113 mov esi,[esi+Element.nextSibling]
3114.first: or esi,esi
3115 jnz .loop
3116
3117.error: pop edi
3118 pop esi
3119 pop ebx
3120 ret
3121;[c]
3122;[c]SUB-FUNCTIONS
3123;[of]: declareGlobalClasses
3124;[c]Create the list of global classes
3125;[c]
3126;[c] Create a class for each <collection> under the root
3127;[c]
3128;[c]ARGUMENTS
3129;[c] eax
3130;[c] the schema element
3131;[c] ebp
3132;[c] the context
3133;[c]
3134;[c]RETURN VALUES
3135;[c] eax+zf
3136;[c] error code
3137;[c] ebx
3138;[c] the root source element
3139;[c] ecx
3140;[c] the root element class
3141;[c]
3142declareGlobalClasses:
3143 push esi
3144 push edi
3145 mov esi,eax
3146
3147 ;
3148 ; Create an array to store all classes
3149 ;
3150 call countGlobals
3151 inc eax
3152 shl eax,2
3153 mov ecx,4
3154 mov edx,ebp
3155 call allocateMemory
3156 jnz .error
3157 mov [ebp+CreateClassContext.classes],edi
3158
3159 xor eax,eax
3160 mov [ebp+CreateClassContext.rootClass],eax
3161
3162 ;
3163 ; Enumerate all the collection element
3164 ; under the root element.
3165 ;
3166 mov esi,[esi+Element.firstChild]
3167 jmp .first
3168.loop: ; Create the class
3169 mov eax,esi
3170 xor ebx,ebx
3171 cmp [esi+Element.id],elementId
3172 jnz .notElement
3173 inc ebx
3174.notElement: mov ecx,ebp
3175 call newElementClass
3176 jnz .error
3177
3178 ; Add it to the list
3179 mov eax,ebx
3180 stosd
3181
3182 ; Save the source element to the class
3183 ; (for forward references)
3184 mov [ebx+ElementClass.source],esi
3185
3186 ; Mark the collection/element as shared
3187 mov [ebx+ElementClass.shared],1
3188
3189 cmp [esi+Element.id],documentId
3190 jnz .notDocument
3191 cmp [ebp+CreateClassContext.rootClass],0
3192 jnz .dupDocument
3193 mov [ebp+CreateClassContext.rootClass],eax
3194.notDocument:
3195
3196 mov esi,[esi+Element.nextSibling]
3197.first: or esi,esi
3198 jnz .loop
3199
3200 ;
3201 ; Check that the schema contains one document
3202 ;
3203 mov eax,[ebp+CreateClassContext.rootClass]
3204 or eax,eax
3205 jz .schemaEmpty
3206
3207 ; Terminate the list with a null
3208 xor eax,eax
3209 stosd
3210
3211 xor eax,eax
3212.error: pop edi
3213 pop esi
3214 ret
3215;[c]
3216.schemaEmpty: mov eax,RC_SCHEMA_EMPTY
3217 or eax,eax
3218 jmp .error
3219;[c]
3220.dupDocument: mov eax,RC_DOCUMENT_DEFINED
3221 or eax,eax
3222 jmp .error
3223;[c]
3224;[c]SUB-FUNCTIONS
3225;[of]: countGlobals
3226;[c]Count number of child classes of type collection
3227;[c]
3228;[c]ARGUMENTS
3229;[c] eax
3230;[c] the element
3231;[c]
3232;[c]RETURN VALUES
3233;[c] eax
3234;[c] the number of child classes
3235;[c]
3236countGlobals: push esi
3237 mov esi,[eax+Element.firstChild]
3238 xor eax,eax
3239 jmp .first
3240.loop: inc eax
3241 mov esi,[esi+Element.nextSibling]
3242.first: or esi,esi
3243 jnz .loop
3244 pop esi
3245 ret
3246;[cf]
3247;[cf]
3248;[of]: createOneClass
3249;[c]Create one class
3250;[c]
3251;[c]ARGUMENTS
3252;[c] eax
3253;[c] 0 = collection
3254;[c] 1 = element
3255;[c] ebx
3256;[c] context
3257;[c] esi
3258;[c] current element
3259;[c]
3260;[c]RETURN VALUES
3261;[c] eax+zf
3262;[c] error code
3263;[c] edi
3264;[c] the class
3265;[c]
3266createOneClass:
3267 ; Create the new element class
3268 push ebx
3269 push esi
3270 mov ecx,ebx
3271 mov ebx,eax
3272 mov eax,esi
3273 call newElementClass
3274 mov edi,ebx
3275 pop esi
3276 pop ebx
3277
3278 jz initializeClass
3279 ret
3280;[cf]
3281;[of]: initializeClass
3282;[c]Initialize one class
3283;[c]
3284;[c]ARGUMENTS
3285;[c] ebx
3286;[c] context
3287;[c] esi
3288;[c] current source element
3289;[c] edi
3290;[c] class
3291;[c]
3292;[c]RETURN VALUES
3293;[c] eax+zf
3294;[c] error code
3295;[c]
3296 struct TreeBuilder
3297.context rd 1 ; the create class context
3298.attributeRoot rd 1 ; the root node for attributes
3299.elementRoot rd 1 ; the root node for elements
3300.rootElement rd 1 ; the root element
3301.offset rd 1 ; the attribute offset
3302.propertyCount rd 1 ; number of attributes/text element
3303.childCount rd 1 ; number of child classes
3304.childIndex rd 1 ; index to store next child class
3305.children rd 1 ; the array to store child classes
3306
3307; Arguments and local variables for addItem
3308.collectionClass rd 1 ;
3309.rootNode rd 1 ; the root node
3310.ignored rd 1 ; 1 if the element is an ignored element
3311.nameBegin rd 1 ;
3312.nameLimit rd 1 ;
3313.ignore rd 1 ;
3314 ends
3315
3316initializeClass:
3317 ; Already resolved ?
3318 cmp [edi+ElementClass.status],RESOLVED
3319 jz .resolved
3320
3321 ; Already being resolved ?
3322 cmp [edi+ElementClass.status],RESOLVING
3323 jz .circular
3324
3325 ; Mark as resolution in progress
3326 mov [edi+ElementClass.status],RESOLVING
3327
3328 push ebx
3329 push esi
3330 push edi
3331 push ebp
3332 sub esp,TreeBuilder.sizeof
3333 mov ebp,esp
3334 mov [ebp+TreeBuilder.context],ebx
3335 mov [ebp+TreeBuilder.rootElement],esi
3336 xor eax,eax
3337 mov [ebp+TreeBuilder.attributeRoot],eax
3338 mov [ebp+TreeBuilder.elementRoot],eax
3339 mov [ebp+TreeBuilder.propertyCount],eax
3340 mov [ebp+TreeBuilder.childIndex],eax
3341 mov [ebp+TreeBuilder.offset],Element.sizeof
3342 mov eax,esi
3343 call countChildren
3344 jnz .error
3345 mov [ebp+TreeBuilder.childCount],ebx
3346
3347 ;
3348 ; Allocate memory for child collections
3349 ;
3350 mov eax,ebx
3351 shl eax,2
3352 mov ecx,4
3353 mov edx,[ebp+TreeBuilder.context]
3354 push edi
3355 call allocateMemory
3356 mov ebx,edi
3357 pop edi
3358 jnz .error
3359 mov [edi+ElementClass.children],ebx
3360 mov [ebp+TreeBuilder.children],ebx
3361
3362 ;
3363 ; Text type : the first attribute is reserved
3364 ; to store the text value.
3365 ;
3366 cmp [edi+ElementClass.type],TYPE_TEXT
3367 jnz .notText
3368 add [ebp+TreeBuilder.offset],Attribute.sizeof
3369 add [ebp+TreeBuilder.propertyCount],1
3370.notText:
3371
3372 ; Build the attribute tree
3373 ;
3374 mov esi,[ebp+TreeBuilder.rootElement]
3375 call buildTrees
3376 jnz .error
3377
3378 ; Build the attribute map from the tree
3379 ;
3380 mov ebx,-1
3381 mov esi,[ebp+TreeBuilder.attributeRoot]
3382 call createAttributeMap
3383 jnz .error
3384 mov [edi+ElementClass.attributes],ebx
3385
3386 ; Build the element map from the tree
3387 ;
3388 xor ebx,ebx
3389 mov esi,[ebp+TreeBuilder.elementRoot]
3390 call createElementMap
3391 jnz .error
3392 mov [edi+ElementClass.elements],ebx
3393
3394 ;
3395 ; Finalize:
3396 ; - copy the number of properties
3397 ; - setup the size of the element
3398 ; - mark as resolved
3399 ;
3400 mov eax,[ebp+TreeBuilder.propertyCount]
3401 imul ebx,eax,Attribute.sizeof
3402 add ebx,Element.sizeof
3403 mov ecx,[ebp+TreeBuilder.childCount]
3404 mov [edi+ElementClass.propertyCount],eax
3405 mov [edi+ElementClass.size],ebx
3406 mov [edi+ElementClass.childCount],ecx
3407 mov [edi+ElementClass.status],RESOLVED
3408
3409 xor eax,eax
3410
3411.error: lea esp,[ebp+TreeBuilder.sizeof] ; zf unchanged
3412 pop ebp
3413 pop edi
3414 pop esi
3415 pop ebx
3416.resolved: ret
3417;[c]
3418.circular: mov eax,RC_RECURSIVE_ELEMENT
3419 or eax,eax
3420 ret
3421;[c]
3422;[c]SUB-FUNCTIONS
3423;[of]: copyString
3424copyString: push esi
3425 push edi
3426 rep movsb
3427 xor eax,eax
3428 stosb
3429 pop edi
3430 pop esi
3431 ret
3432;[cf]
3433;[of]: buildTrees
3434;[c]Build the tree of elements and the tree of attributes
3435;[c]
3436;[c]ARGUMENTS
3437;[c] esi
3438;[c] the source element
3439;[c] ebp
3440;[c] the tree builder
3441;[c]
3442;[c]RETURN VALUES
3443;[c] eax+zf
3444;[c] error code
3445;[c]
3446;[c]REMARKS
3447;[c] The 'root' local variable will contain the root attribute map
3448;[c]
3449buildTrees: push ebx
3450 push esi
3451 push edi
3452
3453 ; Process all attributes of the element
3454 mov esi,[esi+Element.firstChild]
3455 jmp .first
3456
3457.loop: cmp [esi+Element.id],attributeId
3458 jz .attribute
3459 cmp [esi+Element.id],textId
3460 jz .txt
3461 cmp [esi+Element.id],collectionId
3462 jz .collection
3463 cmp [esi+Element.id],elementId
3464 jz .element
3465 cmp [esi+Element.id],referenceId
3466 jz .reference
3467 cmp [esi+Element.id],includeId
3468 jz .include
3469.next: mov esi,[esi+Element.nextSibling]
3470.first: or esi,esi
3471 jnz .loop
3472
3473 xor eax,eax
3474.error: pop edi
3475 pop esi
3476 pop ebx
3477 ret
3478;[c]
3479;[c]Process a <attribute> element
3480;[c]
3481.attribute: xor eax,eax
3482 lea edi,[ebp+TreeBuilder.attributeRoot]
3483 call addItem
3484 jnz .error
3485 jmp .next
3486;[c]
3487;[c]Process a <text> element
3488;[c]
3489.txt: xor eax,eax
3490 jmp .common
3491;[c]
3492;[c]Process a <collection> element
3493;[c]
3494.collection:
3495 ; Create subclass
3496 sub eax,eax
3497 mov ebx,[ebp+TreeBuilder.context]
3498 call createOneClass
3499 jnz .error
3500
3501 ; Save it to the list
3502 mov eax,[ebp+TreeBuilder.childIndex]
3503 mov ecx,[ebp+TreeBuilder.children]
3504 mov [ecx+eax*4],edi
3505 inc eax
3506 mov [ebp+TreeBuilder.childIndex],eax
3507
3508 ; Add it to the tree
3509 mov eax,edi
3510 jmp .common
3511;[c]
3512;[c]Process a <element> element
3513;[c]
3514.element:
3515 ; Create subclass
3516 mov eax,1
3517 mov ebx,[ebp+TreeBuilder.context]
3518 call createOneClass
3519 jnz .error
3520
3521 ; Add it to the tree
3522 mov eax,edi
3523 jmp .common
3524;[c]
3525;[c]Process a <reference> element
3526;[c]
3527.reference: lea eax,[esi+Element.sizeof] ; eax to name attribute
3528 call findClass
3529 mov edi,ebx
3530 jnz .error
3531
3532 ; Save it to the list
3533 mov eax,[ebp+TreeBuilder.childIndex]
3534 mov ecx,[ebp+TreeBuilder.children]
3535 mov [ecx+eax*4],edi
3536 inc eax
3537 mov [ebp+TreeBuilder.childIndex],eax
3538
3539 mov eax,edi
3540;[c]
3541.common: lea edi,[ebp+TreeBuilder.elementRoot]
3542 call addItem
3543 jnz .error
3544 jmp .next
3545;[c]
3546.include: lea eax,[esi+Element.sizeof] ; eax to name attribute
3547 call findGroup
3548 jnz .error
3549
3550 push esi
3551 mov esi,ebx
3552 call buildTrees
3553 pop esi
3554 jmp .next
3555;[c]
3556;[c]SUB-FUNCTIONS
3557;[of]: addItem
3558;[c]Add one item to the tree
3559;[c]
3560;[c]ARGUMENTS
3561;[c] eax
3562;[c] the collection class or null
3563;[c] esi
3564;[c] the element
3565;[c] edi
3566;[c] the root node of the tree (element or attribute)
3567;[c] ebp
3568;[c] local variables
3569;[c]
3570;[c]RETURN VALUES
3571;[c] eax+zf
3572;[c] error code
3573;[c]
3574;[c]REMARKS
3575;[c] It can be a text, attribute or collection item.
3576;[c]
3577addItem: push eax
3578 push ebx
3579 lea eax,[esi+Element.sizeof+ATTR_IGNORE*Attribute.sizeof]
3580 xor ebx,ebx
3581 cmp [eax+Attribute.begin],0
3582 jz .found
3583 lea ecx,[no]
3584 call compareAttributeValue
3585 jz .found
3586 mov ebx,1
3587 lea ecx,[yes]
3588 call compareAttributeValue
3589 jz .found
3590
3591 pop ebx
3592 pop eax
3593 mov eax,RC_INVALID_IGNORE
3594 or eax,eax
3595 ret
3596
3597.found: mov [ebp+TreeBuilder.ignore],ebx
3598 pop ebx
3599 pop eax
3600
3601 mov ecx,[esi+Element.sizeof+Attribute.limit]
3602 mov edx,[esi+Element.sizeof+Attribute.begin]
3603
3604
3605;[c]
3606;[c]Add one item to the tree
3607;[c]
3608;[c]ARGUMENTS
3609;[c] eax
3610;[c] the collection class or null
3611;[c] ecx+edx
3612;[c] the name of the element
3613;[c] edi
3614;[c] the root node of the tree (element or attribute)
3615;[c] ebp
3616;[c] local variables
3617;[c]
3618;[c]RETURN VALUES
3619;[c] eax+zf
3620;[c] error code
3621;[c]
3622;[c]REMARKS
3623;[c] It can be a text, attribute or collection item.
3624;[c]
3625;[c]
3626addItem2: push ebx
3627 push esi
3628 push edi
3629 push ebp
3630 mov [ebp+TreeBuilder.collectionClass],eax
3631 mov [ebp+TreeBuilder.rootNode],edi
3632 mov [ebp+TreeBuilder.nameLimit],ecx
3633 mov [ebp+TreeBuilder.nameBegin],edx
3634
3635 ; empty name ?
3636 cmp ecx,edx
3637 jz .emptyName
3638
3639 ; esi = list
3640 ; ebx = previous node
3641 mov esi,[ebp+TreeBuilder.rootNode]
3642 mov esi,[esi]
3643 xor ebx,ebx
3644
3645 ; read char
3646.next: mov al,[edx]
3647 inc edx
3648
3649 push ecx
3650 push edx
3651 call findOrCreateNode
3652 pop edx
3653 pop ecx
3654 jnz .error
3655 ; esi: list
3656 ; edi: node
3657
3658 ; Attach to previous node
3659 or ebx,ebx
3660 jz .root
3661 cmp [ebx+Node.succ],0
3662 jnz .root
3663 mov [ebx+Node.succ],esi
3664.root:
3665 ; Save the root list
3666 mov eax,[ebp+TreeBuilder.rootNode]
3667 cmp dword [eax],0
3668 jnz .hasRoot
3669 mov [eax],esi
3670.hasRoot:
3671
3672 mov ebx,edi ; the previous node is the current one
3673 mov esi,[ebx+Node.succ] ; get the successor
3674 cmp ecx,edx
3675 jnz .next
3676
3677 ; Save the attribute offset
3678 ; and update it
3679
3680 ; Is there already something with same name ?
3681 cmp dword [ebx+Node.index],-1
3682 jz .noconflict
3683 cmp dword [ebx+Node.index],Element.reserved ; no conflict if ignored
3684 jnz .conflict
3685.noconflict: cmp dword [ebx+Node.collectionClass],0
3686 jnz .conflict
3687
3688 mov ecx,[ebp+TreeBuilder.collectionClass]
3689 or ecx,ecx
3690 jz .txt
3691
3692 mov [ebx+Node.collectionClass],ecx
3693
3694 ; If the it is not a collection but an element
3695 ; it must also be assigned an offset like a text element
3696 cmp dword [ecx+ElementClass.offset],0
3697 jz .common
3698
3699 cmp [ebp+TreeBuilder.ignore],1
3700 jz .ignore
3701
3702 ; If the element is shared, it must be solved first,
3703 ; then duplicated.
3704 ;
3705 cmp byte [ecx+ElementClass.shared],0
3706 jz .notShared
3707
3708 push ebx
3709 push ecx
3710 mov ebx,[ebp+TreeBuilder.context]
3711 mov esi,[ecx+ElementClass.source]
3712 mov edi,ecx
3713 call initializeClass
3714 pop ecx
3715 pop ebx
3716 jnz .error
3717
3718 push ebx
3719 mov ebx,[ebp+TreeBuilder.context]
3720 mov eax,ecx
3721 call copyElementClass
3722 mov ecx,ebx
3723 pop ebx
3724 jnz .error
3725
3726 ; Replace the class by the duplicata
3727 mov [ebx+Node.collectionClass],ecx
3728 jmp .notShared
3729
3730.txt: cmp [ebp+TreeBuilder.ignore],1
3731 jz .ignore
3732
3733.notShared: mov eax,[ebp+TreeBuilder.offset]
3734 mov [ebx+Node.index],eax
3735 add eax,Attribute.sizeof
3736 mov [ebp+TreeBuilder.offset],eax
3737 add [ebp+TreeBuilder.propertyCount],1
3738 jmp .common
3739
3740.ignore: mov [ebx+Node.index],Element.reserved
3741
3742.common: mov ecx,[ebp+TreeBuilder.nameBegin]
3743 mov edx,[ebp+TreeBuilder.nameLimit]
3744 call newDString
3745 mov [ebx+Node.nameBegin],ecx
3746 mov [ebx+Node.nameLimit],edx
3747
3748 xor eax,eax
3749.error: or eax,eax
3750 pop ebp
3751 pop edi
3752 pop esi
3753 pop ebx
3754 ret
3755
3756.emptyName: mov eax,RC_EMPTY_NAME
3757 jmp .error
3758
3759.conflict: mov eax,RC_ATTR_DEFINED
3760 jmp .error
3761;[c]
3762;[of]:newDString
3763;[c]Create a new DString by copying another one
3764;[c]
3765;[c]ARGUMENTS
3766;[c] ecx
3767;[c] begin
3768;[c] edx
3769;[c] end
3770;[c]
3771;[c]RETURN VALUES
3772;[c] eax+zf
3773;[c] error code
3774;[c] ecx
3775;[c] begin (copy)
3776;[c] edx
3777;[c] end (copy)
3778;[c]
3779newDString: push esi
3780 push edi
3781
3782 mov esi,ecx
3783 mov eax,edx
3784 sub eax,esi
3785 mov ecx,1
3786 mov edx,[ebp+TreeBuilder.context]
3787 push eax
3788 call allocateMemory
3789 pop ecx
3790 jnz .error
3791 push ecx
3792 push edi
3793 rep
3794 movsb
3795 pop ecx
3796 pop edx
3797 add edx,ecx
3798
3799 xor eax,eax
3800.error: pop edi
3801 pop esi
3802 ret
3803;[cf]
3804;[cf]
3805;[cf]
3806;[of]: createElementMap
3807;[c]Create an element map for one node
3808;[c]
3809;[c]ARGUMENTS
3810;[c] ebx
3811;[c] the previous node or nil
3812;[c] esi
3813;[c] the node
3814;[c] ebp
3815;[c]
3816;[c]RETURN VALUE
3817;[c] eax+zf
3818;[c] error code
3819;[c] ebx
3820;[c] the map
3821;[c]
3822createElementMap:
3823 push esi
3824 push edi
3825
3826 ; Empty node ?
3827 or esi,esi
3828 jz .empty
3829
3830 call createMap
3831
3832 ; If the previous node contains an offset, create the
3833 ; attribute and make any non-name char a
3834 ; target to this attribute.
3835 ;
3836 ; Note: it cannot happen on the root node since
3837 ; a name cannot be empty.
3838 or ebx,ebx
3839 jz .noAttr
3840 cmp [ebx+Node.collectionClass],0
3841 jnz .elem
3842 cmp [ebx+Node.index],-1
3843 jz .noAttr
3844.elem:
3845 ; Case where a name is a prefix of another name:
3846 ; ab
3847 ; abc
3848 ; ab must be added on non-chars of the abc's map
3849 ;
3850 ;mov eax,8
3851 ;mov ecx,4
3852 ;push edi
3853 ;mov edx,[ebp+TreeBuilder.context]
3854 ;call allocateMemory
3855 ;pop edx
3856 ;jnz .error
3857 ;mov ecx,[ebx+Node.collectionClass]
3858 ;mov word [edi],0
3859 ;mov [edi+4],ecx
3860
3861 push ebx
3862 push esi
3863 mov esi,ebx
3864 call createTerminalElement
3865 mov ecx,ebx
3866 pop esi
3867 pop ebx
3868 jnz .error
3869
3870 push edi
3871 push edx
3872 mov edx,edi
3873 lea edi,[ecx+3] ; set bit 0 & 1 to 1
3874 call mapTerminal
3875 pop edx
3876 pop edi
3877.noAttr:
3878
3879 ; Process each node
3880.lp: cmp [esi+Node.shared],0
3881 jnz .shared
3882
3883 ; The node has only one possible attribute:
3884 ; Create the attribute
3885
3886 call createElement
3887 jnz .error
3888 add ebx,1 ; set bit 0 to 1
3889 jmp .next
3890
3891 ; The node has multiple possible attributes:
3892 ; Create a submap and point to it
3893.shared: push esi
3894 mov ebx,esi
3895 mov esi,[esi+Node.succ]
3896 call createElementMap
3897 pop esi
3898 jnz .error
3899
3900 ; Point to the attribute or map (depending on bit 0)
3901.next: movzx eax,[esi+Node.char]
3902 mov [edi+eax*4],ebx
3903
3904 mov esi,[esi+Node.next]
3905 or esi,esi
3906 jnz .lp
3907
3908 mov ebx,edi
3909.ok: xor eax,eax
3910.error: pop edi
3911 pop esi
3912 ret
3913
3914.empty: mov ebx,noElement
3915 jmp .ok
3916;[c]
3917;[of]:createElement
3918;[c]Create an element
3919;[c]
3920;[c]ARGUMENTS
3921;[c] esi
3922;[c] Node
3923;[c]
3924;[c]RETURN VALUES
3925;[c] zf+eax
3926;[c] Error code
3927;[c] ebx
3928;[c] Element
3929;[c]
3930createElement:
3931
3932 ; Compute the number of remaining chars
3933 xor eax,eax
3934 mov ebx,esi
3935 sub eax,1 ; avoid jmp+1
3936.nextChar: add eax,1
3937 mov ebx,[ebx+Node.succ]
3938 or ebx,ebx
3939 jnz .nextChar
3940
3941 ; Add null char
3942 ; Add flag char
3943 ; Add pointer
3944 ; Align to multiple of 4
3945 add eax,1+1+3+4
3946 and eax,not 3
3947
3948 cmp [esi+Node.collectionClass],0
3949 jnz .coll
3950 add eax,TextElementClass.sizeof - 4
3951
3952 ; Allocate memory for element
3953.coll: mov ecx,4
3954 push edi
3955 mov edx,[ebp+TreeBuilder.context]
3956 call allocateMemory
3957 mov ebx,edi
3958 pop edi
3959 jnz .error
3960
3961 ; Copy remaining chars into attribute
3962 mov ecx,ebx
3963 mov eax,[esi+Node.succ]
3964 mov edx,esi
3965 or eax,eax
3966 jz .skip2
3967.nextChar2: mov edx,eax
3968 mov al,[edx+Node.char]
3969 mov [ecx],al
3970 add ecx,1
3971 mov eax,[edx+Node.succ]
3972 or eax,eax
3973 jnz .nextChar2
3974.skip2: mov byte [ecx],0
3975 add ecx,1
3976
3977 mov eax,[edx+Node.collectionClass]
3978 or eax,eax
3979 setz byte [ecx]
3980 add ecx,1+3
3981 and ecx,not 3
3982 or eax,eax
3983 jz .txt
3984
3985 ; Write Collection Class Information
3986 mov [ecx],eax
3987
3988 cmp [eax+ElementClass.offset],0
3989 jz .ok
3990 mov ecx,[edx+Node.index]
3991 mov [eax+ElementClass.offset],ecx
3992 jmp .ok
3993
3994 ; Write Text Class Information
3995.txt: push esi
3996 push edi
3997 mov eax,[edx+Node.index]
3998 mov esi,[edx+Node.nameBegin]
3999 mov edi,[edx+Node.nameLimit]
4000 mov [ecx+TextElementClass.offset],eax
4001 mov [ecx+TextElementClass.begin],esi
4002 mov [ecx+TextElementClass.limit],edi
4003 pop edi
4004 pop esi
4005
4006.ok: xor eax,eax
4007.error: ret
4008;[cf]
4009;[of]:createTerminalElement
4010;[c]Create a terminal element
4011;[c]
4012;[c]ARGUMENTS
4013;[c] esi
4014;[c] Node
4015;[c]
4016;[c]RETURN VALUES
4017;[c] zf+eax
4018;[c] Error code
4019;[c] ebx
4020;[c] Element
4021;[c]
4022createTerminalElement:
4023
4024 ; Add null char
4025 ; Add flag char
4026 ; Add pointer
4027 ; Align to multiple of 4
4028 mov eax,8
4029 cmp [esi+Node.collectionClass],0
4030 jnz .coll
4031 add eax,TextElementClass.sizeof - 4
4032
4033 ; Allocate memory for element
4034.coll: mov ecx,4
4035 push edi
4036 mov edx,[ebp+TreeBuilder.context]
4037 call allocateMemory
4038 mov ebx,edi
4039 pop edi
4040 jnz .error
4041
4042 ; Copy remaining chars into attribute
4043 mov ecx,ebx
4044 mov byte [ecx],0
4045 add ecx,1
4046 mov eax,[esi+Node.collectionClass]
4047 or eax,eax
4048 setz byte [ecx]
4049 add ecx,1+3
4050 and ecx,not 3
4051 or eax,eax
4052 jz .txt
4053
4054 ; Write Collection Class Information
4055 mov [ecx],eax
4056
4057 cmp [eax+ElementClass.offset],0
4058 jz .ok
4059 mov ecx,[esi+Node.index]
4060 mov [eax+ElementClass.offset],ecx
4061 jmp .ok
4062
4063 ; Write Text Class Information
4064.txt: push edi
4065 mov eax,[esi+Node.index]
4066 mov edx,[esi+Node.nameBegin]
4067 mov edi,[esi+Node.nameLimit]
4068 mov [ecx+TextElementClass.offset],eax
4069 mov [ecx+TextElementClass.begin],edx
4070 mov [ecx+TextElementClass.limit],edi
4071 pop edi
4072
4073.ok: xor eax,eax
4074.error: ret
4075;[cf]
4076;[cf]
4077;[of]: createAttributeMap
4078;[c]Create an attribute map for one node
4079;[c]
4080;[c]ARGUMENTS
4081;[c] ebx
4082;[c] -1 if the node does not have an attribute
4083;[c] esi
4084;[c] the node
4085;[c] ebp
4086;[c]
4087;[c]RETURN VALUE
4088;[c] eax+zf
4089;[c] error code
4090;[c] ebx
4091;[c] the map
4092;[c]
4093createAttributeMap:
4094 ; The node is null: return an empty map
4095 or esi,esi
4096 jnz .noEmpty
4097 mov ebx,noAttribute
4098 xor eax,eax
4099 ret
4100.noEmpty:
4101
4102 push esi
4103 push edi
4104
4105 call createMap
4106
4107 ; If the previous node contains an offset, create the
4108 ; attribute and make any non-name char a
4109 ; target to this attribute.
4110 ;
4111 ; Note: it cannot happen on the root node since
4112 ; a name cannot be empty.
4113 cmp ebx,-1
4114 jz .noAttr
4115
4116 push edi
4117 xor eax,eax
4118 call allocateAttribute
4119 pop edx
4120 jnz .error
4121 mov byte [edi],0
4122 mov [edi+1],ebx
4123 mov ebx,edx
4124 add edi,3 ; set bit 0 & 1 to 1
4125 call mapTerminal
4126 mov edi,ebx
4127.noAttr:
4128
4129 ; Process each node
4130.lp: cmp [esi+Node.shared],0
4131 jnz .shared
4132
4133 ; The node has only one possible attribute:
4134 ; Create the attribute
4135
4136 call createAttribute
4137 jnz .error
4138 add ebx,1 ; set bit 0 to 1
4139 jmp .next
4140
4141 ; The node has multiple possible attributes:
4142 ; Create a submap and point to it
4143.shared: push esi
4144 mov ebx,[esi+Node.index]
4145 mov esi,[esi+Node.succ]
4146 call createAttributeMap
4147 pop esi
4148 jnz .error
4149
4150 ; Point to the attribute or map (depending on bit 0)
4151.next: movzx eax,[esi+Node.char]
4152 mov [edi+eax*4],ebx
4153
4154 mov esi,[esi+Node.next]
4155 or esi,esi
4156 jnz .lp
4157
4158 xor eax,eax
4159 mov ebx,edi
4160.error: pop edi
4161 pop esi
4162 ret
4163;[c]
4164;[of]:mapTerminal
4165;[c]Set the object for each invalid name char
4166;[c]
4167;[c]ARGUMENT
4168;[c] edx
4169;[c] the map
4170;[c] edi
4171;[c] the object
4172;[c]
4173mapTerminal: push esi
4174
4175 mov ecx,256
4176 lea esi,[terminalChar]
4177.next: cmp byte [esi],1
4178 jz .skip
4179 mov [edx],edi
4180.skip: add edx,4
4181 add esi,1
4182 sub ecx,1
4183 jnz .next
4184
4185 pop esi
4186 ret
4187;[cf]
4188;[of]:createMap
4189createMap:
4190 ; Allocate a map
4191 call allocateMap
4192 jnz .error
4193
4194 ; Initialize map
4195 push edi
4196 mov ecx,256
4197 mov eax,1
4198 rep
4199 stosd
4200 pop edi
4201
4202 xor eax,eax
4203.error: ret
4204;[cf]
4205;[of]:allocateMap
4206;[c]Allocates a map
4207;[c]
4208;[c]ARGUMENTS
4209;[c] ebp
4210;[c] the tree builder local variables
4211;[c]
4212;[c]RETURN VALUES
4213;[c] zf
4214;[c] 0 if not enough memory
4215;[c] eax
4216;[c] error code
4217;[c] edi
4218;[c] the map
4219;[c]
4220MAP_SIZE = 256*4
4221MAP_ALIGN = 64
4222;[c]
4223allocateMap: mov ecx,MAP_ALIGN
4224 mov eax,MAP_SIZE
4225 mov edx,[ebp+TreeBuilder.context]
4226 jmp allocateMemory
4227;[cf]
4228;[of]:createAttribute
4229;[c]Create an attribute
4230;[c]
4231;[c]ARGUMENTS
4232;[c] esi
4233;[c] Node
4234;[c]
4235;[c]RETURN VALUES
4236;[c] zf+eax
4237;[c] Error code
4238;[c] ebx
4239;[c] Attribute
4240;[c]
4241createAttribute:
4242
4243 ; Compute the number of remaining chars
4244 xor eax,eax
4245 mov ebx,esi
4246 sub eax,1 ; avoid jmp+1
4247.nextChar: add eax,1
4248 mov ebx,[ebx+Node.succ]
4249 or ebx,ebx
4250 jnz .nextChar
4251
4252 ; Allocate memory for attribute
4253 push edi
4254 call allocateAttribute
4255 mov ebx,edi
4256 pop edi
4257 jnz .error
4258
4259 ; Copy remaining chars into attribute
4260 mov ecx,ebx
4261 mov edx,esi
4262 mov eax,[edx+Node.succ]
4263 or eax,eax
4264 jz .skip2
4265.nextChar2: mov edx,eax
4266 mov al,[edx+Node.char]
4267 mov [ecx],al
4268 add ecx,1
4269 mov eax,[edx+Node.succ]
4270 or eax,eax
4271 jnz .nextChar2
4272.skip2: mov byte [ecx],0
4273
4274 ; Append the index from the last node (edx)
4275 mov eax,[edx+Node.index]
4276 mov [ecx+1],eax
4277
4278 xor eax,eax
4279.error: ret
4280;[cf]
4281;[of]:allocateAttribute
4282;[c]Allocates an attribute
4283;[c]
4284;[c]ARGUMENTS
4285;[c] eax
4286;[c] extra size
4287;[c] ebp
4288;[c] the tree builder local variables
4289;[c]
4290;[c]RETURN VALUES
4291;[c] zf
4292;[c] 0 if not enough memory
4293;[c] eax
4294;[c] error code
4295;[c] edi
4296;[c] the map
4297;[c]
4298allocateAttribute:
4299 mov ecx,4
4300 add eax,1+4
4301 mov edx,[ebp+TreeBuilder.context]
4302 jmp allocateMemory
4303;[cf]
4304;[cf]
4305;[of]: countChildren
4306;[c]Count number of child classes of type collection
4307;[c]
4308;[c]ARGUMENTS
4309;[c] eax
4310;[c] the element
4311;[c]
4312;[c]RETURN VALUES
4313;[c] ebx
4314;[c] the number of child classes
4315;[c]
4316countChildren: push esi
4317 push edi
4318 mov esi,[eax+Element.firstChild]
4319 xor edi,edi
4320 jmp .first
4321.loop: cmp [esi+Element.id],collectionId
4322 jz .count
4323 cmp [esi+Element.id],documentId
4324 jz .count
4325 cmp [esi+Element.id],referenceId
4326 jz .count
4327 cmp [esi+Element.id],includeId
4328 jnz .next
4329
4330 lea eax,[esi+Element.sizeof] ; eax to name attribute
4331 call findGroup
4332 jnz .error
4333
4334 mov eax,ebx
4335 call countChildren
4336 add edi,ebx
4337 jmp .next
4338
4339.count: inc edi
4340.next: mov esi,[esi+Element.nextSibling]
4341.first: or esi,esi
4342 jnz .loop
4343 mov ebx,edi
4344 xor eax,eax
4345.error: pop edi
4346 pop esi
4347 ret
4348;[cf]
4349;[of]: findClass
4350;[c]find a class by name
4351;[c]
4352;[c]ARGUMENTS
4353;[c] eax
4354;[c] the name attribute to look for
4355;[c] ebp
4356;[c] the context
4357;[c]
4358;[c]RETURN VALUES
4359;[c] eax+zf
4360;[c] error code
4361;[c] ebx
4362;[c] the class
4363;[c]
4364findClass: push esi
4365 push edi
4366 mov edi,eax
4367 mov esi,[ebp+TreeBuilder.context]
4368 mov esi,[esi+CreateClassContext.classes]
4369 jmp .next
4370
4371.loop: push eax
4372 lea eax,[eax+ElementClass.name]
4373 lea ebx,[edi+Attribute.begin]
4374 call compareAttributes
4375 pop ebx
4376 jnz .next
4377
4378 ; found
4379 xor eax,eax
4380 jmp .done
4381
4382.next: lodsd
4383 or eax,eax
4384 jnz .loop
4385
4386 ; not found
4387 mov eax,RC_UNDEFINED_CLASS
4388 or eax,eax
4389
4390.done: pop edi
4391 pop esi
4392 ret
4393;[c]
4394;[c]
4395;[cf]
4396;[of]: findGroup
4397;[c]Find a group by name
4398;[c]
4399;[c]ARGUMENTS
4400;[c] eax
4401;[c] the name attribute
4402;[c]
4403;[c]
4404;[c]RETURN VALUES
4405;[c] eax+zf
4406;[c] nz if not found
4407;[c] ebx
4408;[c] the group element
4409;[c]
4410findGroup: push esi
4411 push edi
4412
4413 mov esi,[ebp+TreeBuilder.context]
4414 mov esi,[esi+CreateClassContext.rootElement]
4415 mov esi,[esi+Element.firstChild]
4416 mov ebx,eax
4417 jmp .first
4418
4419.loop: cmp [esi+Element.id],groupId
4420 jnz .next
4421
4422 lea eax,[esi+Element.sizeof+ATTR_NAME*Attribute.sizeof]
4423 call compareAttributes
4424 jnz .next
4425 xor eax,eax
4426 mov ebx,esi
4427 jmp .found
4428
4429.next: mov esi,[esi+Element.nextSibling]
4430.first: or esi,esi
4431 jnz .loop
4432
4433 mov eax,RC_UNDEFINED_GROUP
4434 or eax,eax
4435.found: pop edi
4436 pop esi
4437 ret
4438;[cf]
4439;[c]
4440;[c]CLASSES
4441;[of]: Node
4442;[of]:Comment
4443;[c]Node
4444;[c]
4445;[c]A Node object is just a part of a tree that is a temporary object used to
4446;[c]build the maps of attributes/elements.
4447;[c]
4448;[c]The goal is to have an efficient implementation of a dictionary,
4449;[c]i.e. a set of name -> value.
4450;[c]
4451;[c]A null node pointer is an empty node. So a list is simply initialized
4452;[c]by clearing a register.
4453;[c]
4454;[c]A node is also a list of nodes, one for each char that can appear at this
4455;[c]level. The list of nodes is obtained by following the 'next' property.
4456;[c]
4457;[c]When a character matches, the 'succ' gives the next node for the next
4458;[c]possible character(s).
4459;[c]
4460; succ
4461; Node ---------> Node
4462; | |next
4463; |next
4464; |
4465; | succ
4466; Node ---------> Node
4467; |
4468; |next
4469; |
4470; | succ
4471; Node ---------> Node
4472; |
4473; |next
4474; .
4475; .
4476
4477;[cf]
4478;[of]:Definitions
4479 struct Node
4480.next rd 1
4481.succ rd 1
4482.char rb 1
4483.shared rb 1
4484 rb 2
4485.index rd 1
4486.collectionClass rd 1
4487.nameBegin rd 1
4488.nameLimit rd 1
4489 ends
4490;[cf]
4491;[c]
4492;[of]:findOrCreateNode
4493;[c]Find or create a node
4494;[c]
4495;[c]ARGUMENTS
4496;[c] esi
4497;[c] the parent node or nil
4498;[c] al
4499;[c] the char
4500;[c]
4501;[c]RETURN VALUES
4502;[c] zf
4503;[c] 0 if error
4504;[c] eax
4505;[c] error code
4506;[c] esi
4507;[c] the new parent node
4508;[c] edi
4509;[c] the found or created node
4510;[c]
4511;[c]REMARKS
4512;[c] If the node already exists, the shared flag is set.
4513;[c]
4514findOrCreateNode:
4515
4516 call findNode
4517 jz .notFound
4518
4519 mov [edi+Node.shared],1
4520 jmp .ok
4521
4522 ; Allocate a node
4523.notFound: push eax
4524 call allocateNode
4525 pop edx
4526 jnz .error
4527
4528 ; Append node
4529 call appendNode
4530
4531 ; Initialize node
4532 xor eax,eax
4533 mov [edi+Node.next],eax
4534 mov [edi+Node.succ],eax
4535 mov [edi+Node.char],dl
4536 mov [edi+Node.shared],al
4537 mov [edi+Node.index],-1
4538 mov [edi+Node.collectionClass],eax
4539
4540.ok: xor eax,eax
4541.error: ret
4542;[cf]
4543;[of]:allocateNode
4544;[c]Allocates a node
4545;[c]
4546;[c]ARGUMENTS
4547;[c] ebp
4548;[c] the tree builder local variables
4549;[c]
4550;[c]RETURN VALUES
4551;[c] zf
4552;[c] 0 if not enough memory
4553;[c] eax
4554;[c] error code
4555;[c] edi
4556;[c] the node
4557;[c]
4558allocateNode: mov ecx,4
4559 mov eax,Node.sizeof
4560 mov edx,[ebp+TreeBuilder.context]
4561 jmp allocateMemory
4562;[cf]
4563;[of]:appendNode
4564;[c]Append a node
4565;[c]
4566;[c]ARGUMENTS
4567;[c] esi
4568;[c] parent node
4569;[c] edi
4570;[c] node to append to parent
4571;[c]
4572;[c]RETURN VALUES
4573;[c] esi
4574;[c] parent node
4575;[c] edi
4576;[c] node to append
4577;[c]
4578;[c]REMARKS
4579;[c] if the parent node is nil (i.e. empty), edi becomes the parent.
4580;[c]
4581appendNode: call lastNode
4582 jz .empty
4583 mov [esi+Node.next],edi
4584 ret
4585.empty: mov esi,edi
4586 ret
4587;[cf]
4588;[of]:findNode
4589;[c]Find a node
4590;[c]
4591;[c]ARGUMENTS
4592;[c] al
4593;[c] char
4594;[c] esi
4595;[c] parent node
4596;[c]
4597;[c]RETURN VALUES
4598;[c] edi
4599;[c] search node or nil
4600;[c] zf
4601;[c] 1 if not found
4602;[c]
4603findNode: mov edi,esi
4604 jmp .first
4605
4606.next: cmp al,[edi+Node.char]
4607 jz .done
4608 mov edi,[edi+Node.next]
4609.first: or edi,edi
4610 jnz .next
4611
4612.done: or edi,edi
4613 ret
4614;[cf]
4615;[of]:lastNode
4616;[c]Returns the last node
4617;[c]
4618;[c]ARGUMENTS
4619;[c] esi
4620;[c] parent node
4621;[c]
4622;[c]RETURN VALUES
4623;[c] esi
4624;[c] the last node
4625;[c] zf
4626;[c] 1 if the list of nodes is empty
4627;[c]
4628lastNode: or esi,esi
4629 jnz .first
4630 ret
4631.next: mov esi,eax
4632.first: mov eax,[esi+Node.next]
4633 or eax,eax
4634 jnz .next
4635 or esi,esi
4636 ret
4637;[cf]
4638;[cf]
4639;[cf]
4640
4641;[of]: newElementClass
4642;[c]Create a new element class
4643;[c]
4644;[c]ARGUMENTS
4645;[c] eax
4646;[c] source element
4647;[c] ebx
4648;[c] is element
4649;[c] ecx
4650;[c] context
4651;[c]
4652;[c]RETURN VALUES
4653;[c] eax+zf
4654;[c] error code
4655;[c] ebx
4656;[c] the new element class
4657;[c]
4658newElementClass:
4659 push esi
4660 push edi
4661 mov esi,eax
4662
4663 ;
4664 ; Allocate memory for element class + name
4665 ;
4666 mov eax,[esi+Element.sizeof+Attribute.limit]
4667 sub eax,[esi+Element.sizeof+Attribute.begin]
4668 add eax,ElementClass.sizeof+1
4669 mov edx,ecx
4670 mov ecx,4
4671 call allocateMemory
4672 jnz .error
4673
4674 ;
4675 ; Reset offset
4676 ;
4677 ; the offset is set to 0 if the element is a collection,
4678 ; and it is temporary set to 1 if it is an element, it
4679 ; is just a flag now, but it will replaced by an offset
4680 ; later.
4681 ;
4682 mov [edi+ElementClass.offset],ebx
4683 mov [edi+ElementClass.shared],0
4684 mov [edi+ElementClass.status],UNRESOLVED
4685
4686 ;
4687 ; Setup type
4688 ;
4689 lea eax,[esi+Element.sizeof+ATTR_TYPE*Attribute.sizeof]
4690 mov ebx,TYPE_MIXED
4691 lea ecx,[mixedValue]
4692 call compareAttributeValue
4693 jz .found
4694 mov ebx,TYPE_CONTAINER
4695 lea ecx,[textValue]
4696 call compareAttributeValue
4697 jnz .found
4698 mov ebx,TYPE_TEXT
4699.found: mov [edi+ElementClass.type],ebx
4700
4701 ;
4702 ; Copy and Set Name
4703 ;
4704 push esi
4705 lea eax,[edi+ElementClass.sizeof]
4706 mov [edi+ElementClass.name],eax
4707 push edi
4708 mov ecx,[esi+Element.sizeof+Attribute.limit]
4709 mov esi,[esi+Element.sizeof+Attribute.begin]
4710 sub ecx,esi
4711 mov edi,eax
4712 rep movsb
4713 mov esi,edi
4714 xor eax,eax
4715 stosb
4716 pop edi
4717 mov [edi+ElementClass.nameLimit],esi
4718 pop esi
4719
4720 ;
4721 ; Setup id
4722 ;
4723 mov eax,[esi+Element.sizeof+ATTR_ID*Attribute.sizeof+Attribute.begin]
4724 mov ebx,[esi+Element.sizeof+ATTR_ID*Attribute.sizeof+Attribute.limit]
4725 call toInteger
4726 jnz .error
4727 mov [edi+ElementClass.id],ebx
4728
4729 xor eax,eax
4730 mov ebx,edi
4731.error: pop edi
4732 pop esi
4733 ret
4734;[cf]
4735;[of]: copyElementClass
4736;[c]Copy an element class
4737;[c]
4738;[c]ARGUMENTS
4739;[c] eax
4740;[c] source class
4741;[c] ebx
4742;[c] context
4743;[c]
4744;[c]RETURN VALUES
4745;[c] eax+zf
4746;[c] error code
4747;[c] ebx
4748;[c] the new element class
4749;[c]
4750copyElementClass:
4751 push esi
4752 push edi
4753 mov esi,eax
4754
4755 ;
4756 ; Allocate memory for element class
4757 ;
4758 mov eax,ElementClass.sizeof
4759 mov edx,ebx
4760 mov ecx,4
4761 call allocateMemory
4762 jnz .error
4763
4764 mov ebx,edi
4765 mov ecx,ElementClass.sizeof / 4
4766 rep movsd
4767
4768 xor eax,eax
4769.error: pop edi
4770 pop esi
4771 ret
4772;[cf]
4773;[cf]
4774;[cf]
4775
4776;[of]:Utility Functions
4777;[of]:compareAttributeValue
4778;[c]Compare the value of an attribute
4779;[c]
4780;[c]ARGUMENTS
4781;[c] eax
4782;[c] the attribute
4783;[c] ecx
4784;[c] the value (zero terminated)
4785;[c]
4786;[c]RETURN VALUES
4787;[c] zf
4788;[c] 1 if equal
4789;[c]
4790compareAttributeValue:
4791 push esi
4792 push edi
4793
4794 mov edi,ecx
4795 mov esi,[eax+Attribute.begin]
4796 mov ecx,[eax+Attribute.limit]
4797 sub ecx,esi
4798 jz .done
4799.next: cmpsb
4800 jnz .diff
4801 sub ecx,1
4802 jnz .next
4803
4804.done: cmp byte [edi],0
4805
4806.diff: pop edi
4807 pop esi
4808 ret
4809;[cf]
4810;[of]:compareAttributes
4811;[c]Compare two attributes
4812;[c]
4813;[c]ARGUMENTS
4814;[c] eax
4815;[c] the first attribute
4816;[c] ebx
4817;[c] the second attribute
4818;[c]
4819;[c]RETURN VALUES
4820;[c] zf
4821;[c] 1 if equal
4822;[c]
4823compareAttributes:
4824 push esi
4825 push edi
4826 mov esi,[eax+Attribute.begin]
4827 mov edi,[ebx+Attribute.begin]
4828
4829 ; Compare length
4830 mov ecx,[eax+Attribute.limit]
4831 mov edx,[ebx+Attribute.limit]
4832 sub ecx,esi
4833 sub edx,edi
4834 cmp ecx,edx
4835 jnz .diff
4836
4837 repz cmpsb
4838.diff:
4839 pop edi
4840 pop esi
4841 ret
4842;[cf]
4843;[of]:toInteger
4844;[c]Converts a string to an integer
4845;[c]
4846;[c]ARGUMENTS
4847;[c] eax
4848;[c] the string to parse
4849;[c] ebx
4850;[c] the end of string
4851;[c]
4852;[c]RETURN VALUES
4853;[c] eax+zf
4854;[c] error code
4855;[c] ebx
4856;[c] integer value
4857;[c]
4858toInteger: push esi
4859 push edi
4860 mov esi,eax
4861 mov edi,ebx
4862 xor eax,eax
4863 jmp .first
4864
4865.loop: movzx ecx,byte [esi]
4866 cmp cl,'0'
4867 jc .error
4868 cmp cl,'9'+1
4869 jnc .error
4870 inc esi
4871 mov edx,10
4872 imul eax,edx
4873 sub cl,'0'
4874 add eax,ecx
4875.first: cmp esi,edi
4876 jnz .loop
4877
4878 mov ebx,eax
4879 xor eax,eax
4880
4881.done: pop edi
4882 pop esi
4883 ret
4884;[c]
4885.error: mov eax,RC_INVALID_ID
4886 or eax,eax
4887 jmp .done
4888;[cf]
4889;[cf]
4890;[of]:Memory
4891;[of]:allocateMemory
4892;[c]Allocates a memory block
4893;[c]
4894;[c]ARGUMENTS
4895;[c] eax
4896;[c] size
4897;[c] ecx
4898;[c] alignment
4899;[c] edx
4900;[c] context
4901;[c]
4902;[c]RETURN VALUES
4903;[c] eax+zf
4904;[c] error code
4905;[c] edi
4906;[c] the object
4907;[c]
4908allocateMemory: mov edi,[edx+MemoryContext.base]
4909 sub ecx,1
4910 add edi,ecx
4911 not ecx
4912 and edi,ecx
4913 add eax,edi
4914 cmp eax,[edx+MemoryContext.limit]
4915 jnc .chunkFull
4916 mov [edx+MemoryContext.base],eax
4917 xor eax,eax
4918 ret
4919;[c]
4920.chunkFull: push edx
4921 push ebp
4922 mov ebp,edx
4923 sub eax,edi
4924 call extendMemory ; let's assume that alignment is ok
4925 pop ebp
4926 pop edx
4927 ret
4928;[cf]
4929;[of]:extendMemory
4930;[c]Extend memory
4931;[c]
4932;[c]When there is not enough memory available, a new chunk is created
4933;[c]
4934;[c]ARGUMENTS
4935;[c] eax
4936;[c] size
4937;[c] ebp
4938;[c] the parse context
4939;[c]
4940;[c]RETURN VALUES
4941;[c] eax+zf
4942;[c] error code
4943;[c] edi
4944;[c] the allocated memory buffer
4945;[c]
4946extendMemory: push eax
4947 mov ecx,[ebp+MemoryContext.chunkSize]
4948 add eax,ecx
4949 call newChunk
4950 pop ecx
4951 jnz .error
4952
4953 mov edi,[ebp+MemoryContext.base]
4954 add ecx,edi
4955 mov [ebp+MemoryContext.base],ecx
4956
4957 xor eax,eax
4958.error: ret
4959;[cf]
4960;[of]:releaseChunks
4961;[c]Release the memory handled by the memory context
4962;[c]
4963;[c]ARGUMENTS
4964;[c] ebp
4965;[c] the context
4966;[c]
4967releaseChunks: push ebx
4968 mov eax,[ebp+MemoryContext.chunks]
4969 or eax,eax
4970 jz .done
4971.loop: mov ebx,[eax]
4972 call freeChunk
4973 mov eax,ebx
4974 or eax,eax
4975 jnz .loop
4976.done: pop ebx
4977 ret
4978;[cf]
4979;[of]:newChunk
4980;[c]Create a new chunk of memory
4981;[c]
4982;[c]ARGUMENTS
4983;[c] ebp
4984;[c] the parse context
4985;[c] eax
4986;[c] the size of chunk
4987;[c]
4988;[c]RETURN VALUES
4989;[c] eax+zf
4990;[c] error code
4991;[c]
4992newChunk: mov ecx,eax
4993 add eax,HEADER_SIZE ; size for link
4994 push ecx
4995 push eax
4996 call [mallocFunction]
4997 add esp,4
4998 pop ecx
4999 or eax,eax
5000 jz .outOfMemory
5001 mov edx,[ebp+MemoryContext.chunks]
5002 mov [eax],edx
5003 mov [ebp+MemoryContext.chunks],eax
5004 add eax,HEADER_SIZE
5005 add ecx,eax
5006 mov [ebp+MemoryContext.base],eax
5007 mov [ebp+MemoryContext.limit],ecx
5008
5009 xor eax,eax
5010 ret
5011;[c]
5012.outOfMemory: mov eax,RC_MEMORY
5013 or eax,eax
5014 ret
5015;[cf]
5016;[of]:freeChunk
5017;[c]Free a chunk
5018;[c]
5019;[c]ARGUMENTS
5020;[c] eax
5021;[c] the chunk
5022;[c]
5023freeChunk: push eax
5024 call [freeFunction]
5025 add esp,4
5026 ret
5027;[cf]
5028;[cf]
5029
5030;[of]:Data
5031 align 4
5032
5033;[of]:S
5034;[c]The blank map
5035;[c]
5036;[c] Flag for each character:
5037;[c] - 1 for blank characters (9, 10, 13, 32)
5038;[c] - 0 for other characters
5039;[c]
5040S: db 0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0
5041 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5042 db 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5043 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5044 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5045 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5046 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5047 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5048 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5049 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5050 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5051 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5052 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5053 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5054 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5055 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5056;[cf]
5057;[of]:RAC
5058;[c]Regular Attribute Chars
5059;[c]
5060;[c] Flag for each character:
5061;[c] - 1 for special chars (" ' & \0)
5062;[c] - 0 for other characters
5063;[c]
5064RAC: db 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5065 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5066 db 0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0
5067 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5068 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5069 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5070 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5071 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5072 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5073 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5074 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5075 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5076 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5077 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5078 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5079 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5080;[cf]
5081;[of]:terminalChar
5082;[c]Any zero char is a terminator for an attribute name or an element name
5083;[c]
5084terminalChar: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5085 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5086 db 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0 ; -.
5087 db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 ; :
5088 db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5089 db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1 ; _
5090 db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5091 db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
5092 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5093 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5094 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5095 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5096 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5097 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5098 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5099 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5100;[cf]
5101;[of]:digit
5102;[c]Two flags for each chars:
5103;[c] - bit 0 for decimal chars
5104;[c] - bit 1 for hexadecimal chars
5105;[c]
5106digit: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5107 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5108 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5109 db 3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0
5110 db 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0
5111 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5112 db 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0
5113 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5114 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5115 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5116 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5117 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5118 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5119 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5120 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5121 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5122;[cf]
5123;[of]:xdigit
5124;[c]Hexadecimal value of a char, assuming that the char is a valid
5125;[c]hexadecimal digit.
5126;[c]
5127xdigit: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5128 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5129 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5130 db 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0
5131 db 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0
5132 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5133 db 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0
5134 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5135 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5136 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5137 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5138 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5139 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5140 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5141 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5142 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5143;[cf]
5144;[of]:noElement / noAttribute
5145;[c]The default map for element without child elements (attribute only elements).
5146;[c]
5147noAttribute:
5148noElement:
5149 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5150 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5151 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5152 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5153 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5154 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5155 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5156 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5157 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5158 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5159 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5160 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5161 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5162 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5163 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5164 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5165;[cf]
5166;[of]:PubidChar
5167;[c]Valid characters for PubidLiteral
5168;[c]
5169PubidChar: db 0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0
5170 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5171 db 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1
5172 db 1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1
5173 db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5174 db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1
5175 db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5176 db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0
5177 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5178 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5179 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5180 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5181 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5182 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5183 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5184 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5185;[cf]
5186;[of]:invalidClass
5187;[c]This special class is used to ignore unknown elements when
5188;[c]parsing in non strict mode.
5189;[c]
5190invalidClass:
5191 dd Element.reserved ; store as ignored
5192 dd invalidName
5193 dd invalidName+1
5194 dd Element.sizeof + 0 * Attribute.sizeof
5195 dd 0 ; null id
5196 dd TYPE_CONTAINER
5197 dd 0 ; no child
5198 dd 0 ; no element
5199 dd noAttribute
5200 dd noElement
5201;[cf]
5202
5203;[of]:Schema Class
5204;[c]Schema Class
5205;[c]
5206SchemaClass: dd 0
5207 dd schemaName
5208 dd schemaName+6
5209 dd Element.sizeof
5210 dd schemaId
5211 dd TYPE_CONTAINER
5212 dd 0
5213 dd 0
5214 dd noAttribute
5215 dd schemaMap
5216
5217;[of]:Attribute Class
5218;[c]Attribute Class
5219;[c]
5220attributeClass: dd 0
5221 dd attributeName
5222 dd attributeName+9
5223 dd Element.sizeof + 2 * Attribute.sizeof
5224 dd attributeId
5225 dd TYPE_CONTAINER
5226 dd 2
5227 dd 0
5228 dd nameIgnoreAttr
5229 dd noElement
5230
5231;[cf]
5232;[of]:Text Class
5233;[c]Text Class
5234;[c]
5235textClass: dd 0
5236 dd textName
5237 dd textName+4
5238 dd Element.sizeof + 2 * Attribute.sizeof
5239 dd textId
5240 dd TYPE_CONTAINER
5241 dd 2
5242 dd 0
5243 dd nameIgnoreAttr
5244 dd noElement
5245
5246;[cf]
5247;[of]:Document Class
5248documentClass: dd 0
5249 dd documentName
5250 dd documentName+8
5251 dd Element.sizeof + 4 * Attribute.sizeof
5252 dd documentId
5253 dd TYPE_CONTAINER
5254 dd 4
5255 dd 0
5256 dd nameAndTypeAttr
5257 dd elementMap
5258;[cf]
5259;[of]:Collection Class
5260collectionClass:
5261 dd 0
5262 dd collectionName
5263 dd collectionName+10
5264 dd Element.sizeof + 4 * Attribute.sizeof
5265 dd collectionId
5266 dd TYPE_CONTAINER
5267 dd 4
5268 dd 0
5269 dd nameAndTypeAttr
5270 dd elementMap
5271;[cf]
5272;[of]:Group Class
5273groupClass:
5274 dd 0
5275 dd groupName
5276 dd groupName+5
5277 dd Element.sizeof + 4 * Attribute.sizeof
5278 dd groupId
5279 dd TYPE_CONTAINER
5280 dd 4
5281 dd 0
5282 dd nameAndTypeAttr
5283 dd elementMap
5284;[cf]
5285;[of]:Element Class
5286elementClass:
5287 dd 0
5288 dd elementName
5289 dd elementName+7
5290 dd Element.sizeof + 4 * Attribute.sizeof
5291 dd elementId
5292 dd TYPE_CONTAINER
5293 dd 4
5294 dd 0
5295 dd nameAndTypeAttr
5296 dd elementMap
5297;[cf]
5298;[of]:Reference Class
5299referenceClass:
5300 dd 0
5301 dd referenceName
5302 dd referenceName+9
5303 dd Element.sizeof + 2 * Attribute.sizeof
5304 dd referenceId
5305 dd TYPE_CONTAINER
5306 dd 2
5307 dd 0
5308 dd nameIgnoreAttr
5309 dd noElement
5310;[cf]
5311;[of]:Include Class
5312includeClass:
5313 dd 0
5314 dd includeName
5315 dd includeName+7
5316 dd Element.sizeof + 1 * Attribute.sizeof
5317 dd includeId
5318 dd TYPE_CONTAINER
5319 dd 1
5320 dd 0
5321 dd nameAttr
5322 dd noElement
5323;[cf]
5324
5325;[of]:Element maps
5326 align 4
5327schemaMap: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5328 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5329 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5330 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5331 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5332 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5333 dd 1,1,1,.c+1,.d+1,.e+1,1,.g+1,1,1,1,1,1,1,1,1
5334 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5335 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5336 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5337 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5338 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5339 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5340 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5341 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5342 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5343
5344.c: align 4
5345 db "ollection",0,0
5346 align 4
5347 dd collectionClass
5348
5349.d: align 4
5350 db "ocument",0,0
5351 align 4
5352 dd documentClass
5353
5354.e: align 4
5355 db "lement",0,0
5356 align 4
5357 dd elementClass
5358
5359.g: align 4
5360 db "roup",0,0
5361 align 4
5362 dd groupClass
5363
5364 align 4
5365elementMap: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5366 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5367 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5368 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5369 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5370 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5371 dd 1,.a+1,1,.c+1,1,.e+1,1,1,1,.i+1,1,1,1,1,1,1
5372 dd 1,1,.r+1,1,.t+1,1,1,1,1,1,1,1,1,1,1,1
5373 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5374 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5375 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5376 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5377 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5378 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5379 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5380 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5381
5382 align 4
5383.a: db "ttribute",0,0
5384 align 4
5385 dd attributeClass
5386
5387 align 4
5388.t: db "ext",0,0
5389 align 4
5390 dd textClass
5391
5392.c: align 4
5393 db "ollection",0,0
5394 align 4
5395 dd collectionClass
5396
5397.e: align 4
5398 db "lement",0,0
5399 align 4
5400 dd elementClass
5401
5402.i: align 4
5403 db "nclude",0,0
5404 align 4
5405 dd includeClass
5406
5407.r: align 4
5408 db "eference",0,0
5409 align 4
5410 dd referenceClass
5411;[cf]
5412;[of]:name=
5413 align 4
5414nameAttr: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5415 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5416 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5417 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5418 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5419 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5420 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,.name+1,1
5421 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5422 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5423 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5424 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5425 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5426 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5427 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5428 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5429 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5430
5431 align 4
5432.name: db "ame",0
5433 dd Element.sizeof + 0 * Attribute.sizeof
5434
5435;[cf]
5436;[of]:name= ignore=
5437 align 4
5438nameIgnoreAttr:
5439 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5440 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5441 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5442 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5443 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5444 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5445 dd 1,1,1,1,1,1,1,1,1,.ignore+1,1,1,1,1,.name+1,1
5446 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5447 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5448 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5449 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5450 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5451 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5452 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5453 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5454 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5455
5456 align 4
5457.name: db "ame",0
5458 dd Element.sizeof + 0 * Attribute.sizeof
5459
5460 align 4
5461.ignore: db "gnore",0
5462 dd Element.sizeof + 1 * Attribute.sizeof
5463
5464;[cf]
5465;[of]:name= ignore= id= type=
5466
5467 align 4
5468nameAndTypeAttr:
5469 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5470 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5471 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5472 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5473 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5474 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5475 dd 1,1,1,1,1,1,1,1,1,.i,1,1,1,1,.name+1,1
5476 dd 1,1,1,1,.type+1,1,1,1,1,1,1,1,1,1,1,1
5477 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5478 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5479 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5480 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5481 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5482 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5483 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5484 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5485
5486.i: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5487 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5488 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5489 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5490 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5491 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5492 dd 1,1,1,1,.id+1,1,1,.ignore+1,1,1,1,1,1,1,1,1
5493 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5494 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5495 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5496 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5497 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5498 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5499 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5500 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5501 dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
5502
5503 align 4
5504.name: db "ame",0
5505 dd Element.sizeof + 0 * Attribute.sizeof
5506
5507 align 4
5508.ignore db "nore",0
5509 dd Element.sizeof + 1 * Attribute.sizeof
5510
5511 align 4
5512.type: db "ype",0
5513 dd Element.sizeof + 2 * Attribute.sizeof
5514
5515 align 4
5516.id: db 0
5517 dd Element.sizeof + 3 * Attribute.sizeof
5518;[cf]
5519
5520;[of]:Element Names
5521schemaName db "schema",0
5522documentName db "document",0
5523attributeName db "attribute",0
5524textName db "text",0
5525collectionName db "collection",0
5526elementName db "element",0
5527referenceName db "reference",0
5528includeName db "include",0
5529groupName db "group",0
5530invalidName db "?",0
5531
5532textValue db "text",0
5533mixedValue db "mixed",0
5534
5535yes db "yes",0
5536no db "no",0
5537;[cf]
5538;[cf]
5539;[of]:Atoms
5540atomTable dd DOCTYPEName
5541 dd ELEMENTName
5542 dd ATTLISTName
5543 dd PCDATAName
5544 dd IMPLIEDName
5545 dd REQUIREDName
5546 dd FIXEDName
5547 dd NDATAName
5548
5549 dd CDATAName
5550 dd IDName
5551 dd IDREFName
5552 dd IDREFSName
5553 dd ENTITYName
5554 dd ENTITIESName
5555 dd NMTOKENName
5556 dd NMTOKENSName
5557 dd NOTATIONName
5558
5559 dd versionName
5560 dd encodingName
5561 dd standaloneName
5562 dd 0
5563
5564DOCTYPEName db "DOCTYPE",0
5565ELEMENTName db "ELEMENT",0
5566ATTLISTName db "ATTLIST",0
5567PCDATAName db "PCDATA",0
5568IMPLIEDName db "IMPLIED",0
5569REQUIREDName db "REQUIRED",0
5570FIXEDName db "FIXED",0
5571NDATAName db "NDATA",0
5572
5573CDATAName db "CDATA",0
5574IDName db "ID",0
5575IDREFName db "IDREF",0
5576IDREFSName db "IDREFS",0
5577ENTITYName db "ENTITY",0
5578ENTITIESName db "ENTITIES",0
5579NMTOKENName db "NMTOKEN",0
5580NMTOKENSName db "NMTOKENS",0
5581NOTATIONName db "NOTATION",0
5582
5583versionName db "version",0
5584encodingName db "encoding",0
5585standaloneName db "standalone",0
5586;[cf]
5587;[cf]
5588;[of]:BSS
5589section '.asmdata' writeable
5590
5591mallocFunction rd 1
5592freeFunction rd 1
5593
5594;[cf]
diff --git a/messenger/XML_Parser/src/elf.asm b/messenger/XML_Parser/src/elf.asm
new file mode 100644
index 00000000..c8a6d7d8
--- /dev/null
+++ b/messenger/XML_Parser/src/elf.asm
@@ -0,0 +1,19 @@
1;[c]asm-xml.asm - Asm XML Parser
2;[c]
3;[c]Compile this file with fasm.
4;[c]
5format ELF
6
7include "asm-xml.asm"
8
9;[c]
10;[c]Public Functions
11;[c]
12public _initialize as "ax_initialize"
13public _initializeParser as "ax_initializeParser"
14public _releaseParser as "ax_releaseParser"
15public _parse as "ax_parse"
16public _initializeClassParser as "ax_initializeClassParser"
17public _releaseClassParser as "ax_releaseClassParser"
18public _classFromElement as "ax_classFromElement"
19public _classFromString as "ax_classFromString"
diff --git a/messenger/XML_Parser/src/win32.asm b/messenger/XML_Parser/src/win32.asm
new file mode 100644
index 00000000..a31effec
--- /dev/null
+++ b/messenger/XML_Parser/src/win32.asm
@@ -0,0 +1,19 @@
1;[c]asm-xml.asm - Asm XML Parser
2;[c]
3;[c]Compile this file with fasm.
4;[c]
5format MS COFF
6
7include "asm-xml.asm"
8
9;[c]
10;[c]Public Functions
11;[c]
12public _initialize as "_ax_initialize"
13public _initializeParser as "_ax_initializeParser"
14public _releaseParser as "_ax_releaseParser"
15public _parse as "_ax_parse"
16public _initializeClassParser as "_ax_initializeClassParser"
17public _releaseClassParser as "_ax_releaseClassParser"
18public _classFromElement as "_ax_classFromElement"
19public _classFromString as "_ax_classFromString"