diff options
Diffstat (limited to 'messenger/XML_Parser')
-rw-r--r-- | messenger/XML_Parser/README | 15 | ||||
-rw-r--r-- | messenger/XML_Parser/asm-xml.h | 162 | ||||
-rw-r--r-- | messenger/XML_Parser/friends.xml | 10 | ||||
-rw-r--r-- | messenger/XML_Parser/main.c | 160 | ||||
-rw-r--r-- | messenger/XML_Parser/obj/elf/asm-xml.o | bin | 0 -> 19361 bytes | |||
-rw-r--r-- | messenger/XML_Parser/obj/mach-o/asm-xml.o | bin | 0 -> 19326 bytes | |||
-rw-r--r-- | messenger/XML_Parser/obj/ms-coff/asm-xml.obj | bin | 0 -> 19421 bytes | |||
-rw-r--r-- | messenger/XML_Parser/src/asm-xml.asm | 5594 | ||||
-rw-r--r-- | messenger/XML_Parser/src/elf.asm | 19 | ||||
-rw-r--r-- | messenger/XML_Parser/src/win32.asm | 19 |
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 | |||
5 | Include the "asm-xml.h" file in your source file. | ||
6 | |||
7 | Link your project with the AsmXml object file. | ||
8 | ~ ~ ~ ~ | ||
9 | Here 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 | ||
16 | extern "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 | //----------------------------------------------------------------------------- | ||
50 | typedef struct AXElement AXElement ; | ||
51 | typedef struct AXAttribute AXAttribute ; | ||
52 | typedef struct AXElementClass AXElementClass ; | ||
53 | typedef struct AXParseContext AXParseContext ; | ||
54 | typedef struct AXClassContext AXClassContext ; | ||
55 | |||
56 | struct 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 | |||
75 | struct 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 | |||
89 | struct 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 | |||
98 | struct 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 | |||
109 | struct 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 | |||
132 | extern | ||
133 | void ACC ax_initialize (void* mallocFun, | ||
134 | void* freeFun); | ||
135 | extern | ||
136 | int ACC ax_initializeParser (AXParseContext* context, | ||
137 | unsigned int chunkSize); | ||
138 | extern | ||
139 | int ACC ax_releaseParser (AXParseContext* context); | ||
140 | extern | ||
141 | AXElement* ACC ax_parse (AXParseContext* context, | ||
142 | const char* source, | ||
143 | AXElementClass* type, | ||
144 | int strict); | ||
145 | extern | ||
146 | int ACC ax_initializeClassParser (AXClassContext* context); | ||
147 | extern | ||
148 | int ACC ax_releaseClassParser (AXClassContext* context); | ||
149 | extern | ||
150 | AXElementClass* ACC ax_classFromElement (AXElement* e, | ||
151 | AXClassContext* context); | ||
152 | extern | ||
153 | AXElementClass* 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 | |||
12 | static const int chunkSize = 16*1024*1024; // 16Mk | ||
13 | static const char schemaFilename[] = "schema.xml"; | ||
14 | static const char xmlFilename[] = "friends.xml"; | ||
15 | |||
16 | char buffer[65536]; | ||
17 | |||
18 | /////////////////////////////////////////////////////////////////////////////// | ||
19 | // Print an attribute / text value | ||
20 | /////////////////////////////////////////////////////////////////////////////// | ||
21 | const 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 | /////////////////////////////////////////////////////////////////////////////// | ||
34 | void 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 | /////////////////////////////////////////////////////////////////////////////// | ||
42 | AXElementClass* 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 | /////////////////////////////////////////////////////////////////////////////// | ||
64 | AXElement* 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 | /////////////////////////////////////////////////////////////////////////////// | ||
88 | int 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 | ||
41 | macro struct name | ||
42 | { | ||
43 | virtual at 0 | ||
44 | label name | ||
45 | } | ||
46 | |||
47 | macro 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] | ||
135 | EC_TEXT equ 1 | ||
136 | EC_TEXT_COLL equ 2 | ||
137 | |||
138 | ;[c] | ||
139 | ;[c]Error Codes | ||
140 | ;[c] | ||
141 | RC_OK equ 0 ; everything is ok | ||
142 | RC_MEMORY equ 1 ; out of memory | ||
143 | |||
144 | ; Schema | ||
145 | RC_EMPTY_NAME equ 10 ; name empty or not defined | ||
146 | RC_ATTR_DEFINED equ 11 ; attribute already defined | ||
147 | RC_ELEM_DEFINED equ 12 ; element already defined | ||
148 | RC_SCHEMA_EMPTY equ 13 ; schema does not contains a document | ||
149 | RC_DOCUMENT_DEFINED equ 14 ; schema contains more than one document | ||
150 | RC_UNDEFINED_CLASS equ 15 ; can't find collection in reference | ||
151 | RC_UNDEFINED_GROUP equ 16 ; can't find a group in include | ||
152 | RC_INVALID_ID equ 17 ; id is not a valid number | ||
153 | RC_INVALID_IGNORE equ 18 ; ignore is not 'yes' or 'no' | ||
154 | RC_RECURSIVE_ELEMENT equ 19 ; element cannot reference itself | ||
155 | |||
156 | ; Parsing | ||
157 | RC_INVALID_ENTITY_REFERENCE equ 20 | ||
158 | RC_UNEXPECTED_END equ 21 | ||
159 | RC_INVALID_CHAR equ 22 | ||
160 | RC_OVERFLOW equ 23 | ||
161 | RC_NO_START_TAG equ 24 | ||
162 | RC_TAG_MISMATCH equ 25 | ||
163 | RC_INVALID_TAG equ 26 | ||
164 | RC_INVALID_ATTRIBUTE equ 27 | ||
165 | RC_INVALID_PI equ 28 | ||
166 | RC_INVALID_DOCTYPE equ 29 | ||
167 | RC_VERSION_EXPECTED equ 30 | ||
168 | |||
169 | ;[c] | ||
170 | ;[c]Various constants | ||
171 | ;[c] | ||
172 | TAB_SIZE equ 8 | ||
173 | DEFAULT_CHUNK_SIZE equ 1024*1024 | ||
174 | HEADER_SIZE equ 16 ; reserved space for chunks | ||
175 | ;[c] | ||
176 | TYPE_CONTAINER equ 0 | ||
177 | TYPE_TEXT equ 1 | ||
178 | TYPE_MIXED equ 2 | ||
179 | ;[c] | ||
180 | ATTR_NAME equ 0 | ||
181 | ATTR_IGNORE equ 1 | ||
182 | ATTR_TYPE equ 2 | ||
183 | ATTR_ID equ 3 | ||
184 | ;[c] | ||
185 | ;[c]Class Ids | ||
186 | ;[c] | ||
187 | schemaId equ 0 | ||
188 | documentId equ 1 | ||
189 | attributeId equ 2 | ||
190 | textId equ 3 | ||
191 | collectionId equ 4 | ||
192 | elementId equ 5 | ||
193 | referenceId equ 6 | ||
194 | includeId equ 7 | ||
195 | groupId equ 8 | ||
196 | ;[c] | ||
197 | ;[c]Resolution | ||
198 | ;[c] | ||
199 | UNRESOLVED equ 0 | ||
200 | RESOLVING equ 1 | ||
201 | RESOLVED equ 2 | ||
202 | ;[c] | ||
203 | ;[c]Atoms (for DOCTYPE) | ||
204 | ;[c] | ||
205 | ATOM_DOCTYPE equ 0 | ||
206 | ATOM_ELEMENT equ 1 | ||
207 | ATOM_ATTLIST equ 2 | ||
208 | ATOM_PCDATA equ 3 | ||
209 | ATOM_IMPLIED equ 4 | ||
210 | ATOM_REQUIRED equ 5 | ||
211 | ATOM_FIXED equ 6 | ||
212 | ATOM_NDATA equ 7 | ||
213 | |||
214 | ATOM_CDATA equ 8 | ||
215 | ATOM_ID equ 9 | ||
216 | ATOM_IDREF equ 10 | ||
217 | ATOM_IDREFS equ 11 | ||
218 | ATOM_ENTITY equ 12 | ||
219 | ATOM_ENTITIES equ 13 | ||
220 | ATOM_NMTOKEN equ 14 | ||
221 | ATOM_NMTOKENS equ 15 | ||
222 | ATOM_NOTATION equ 16 | ||
223 | |||
224 | ATOM_VERSION equ 17 | ||
225 | ATOM_ENCODING equ 18 | ||
226 | ATOM_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] | ||
481 | initialize: | ||
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] | ||
500 | initializeParser: | ||
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] | ||
514 | releaseParser: 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] | ||
537 | parse: 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 | |||
557 | resumeParseChunkFull: | ||
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 | ||
586 | readRootElement: | ||
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] | ||
659 | nextAttribute: | ||
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] | ||
669 | readAttributes: | ||
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] | ||
679 | readAttribute: 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 | |||
702 | commonAttribute: | ||
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 | |||
723 | readAttributeValue: | ||
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 | ||
740 | resumeBecauseIgnored: | ||
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] | ||
759 | endOfAttribute: | ||
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 | |||
776 | endOfElement: movzx eax,byte [esi] | ||
777 | add esi,1 | ||
778 | cmp al,'>' | ||
779 | jnz invalidChar | ||
780 | xor eax,eax | ||
781 | ret | ||
782 | ;[c] | ||
783 | terminalAttribute: | ||
784 | and ecx,not 2 | ||
785 | jmp commonAttribute | ||
786 | ;[c] | ||
787 | attributeDefinedOrIgnored: | ||
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] | ||
798 | readContentOrText: | ||
799 | ; test if the content is just text | ||
800 | cmp [edx+ElementClass.type],TYPE_TEXT | ||
801 | jz readInnerText | ||
802 | ;[c] | ||
803 | readContent: | ||
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 | ||
820 | readCloseTag: | ||
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 | |||
850 | referenceOrComment: | ||
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] | ||
858 | readChild: 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] | ||
911 | readText: | ||
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 | |||
946 | endOfEmptyText: sub esi,1 | ||
947 | mov [ebx+Attribute.limit],esi | ||
948 | add esi,1 | ||
949 | |||
950 | endOfText: 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] | ||
972 | emptyOrCDATAOrPI: | ||
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] | ||
1027 | textReference: | ||
1028 | textCommentOrCDATA: | ||
1029 | textPI: | ||
1030 | invalidCharOrComment: | ||
1031 | sub esi,1 | ||
1032 | call readValue | ||
1033 | jmp endOfText | ||
1034 | ;[c] | ||
1035 | emptyText: 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 | |||
1052 | readChildElement: | ||
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] | ||
1160 | terminalElement: | ||
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 | ||
1179 | skipCommentOrCDATA: | ||
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 | ||
1222 | skipContentPI: 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] | ||
1236 | readInnerText: 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 | |||
1265 | innerEndOfEmptyText: | ||
1266 | dec esi | ||
1267 | mov [ebx+Attribute.limit],esi | ||
1268 | inc esi | ||
1269 | |||
1270 | innerEndOfText: cmp al, '/' | ||
1271 | jnz invalidChar | ||
1272 | jmp readCloseTag | ||
1273 | ;[c] | ||
1274 | innerEmptyOrCDATAOrPI: | ||
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] | ||
1329 | innerTextCommentOrCDATA: | ||
1330 | innerTextReference: | ||
1331 | innerInvalidCharOrComment: | ||
1332 | innerPI: | ||
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] | ||
1344 | readPCDATA: ; 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 | ||
1352 | interResume0: 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 | ||
1357 | interResume: | ||
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 | |||
1398 | interEndOfText: cmp al, '/' | ||
1399 | jnz referenceOrComment | ||
1400 | jmp readCloseTag | ||
1401 | ;[c] | ||
1402 | interEmptyOrCDATA: ; 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] | ||
1413 | interTextCommentOrCDATA: | ||
1414 | interTextReference: | ||
1415 | interTextPI: | ||
1416 | sub esi,1 | ||
1417 | call readValue | ||
1418 | jmp interEndOfText | ||
1419 | ;[c] | ||
1420 | interChunkFull: 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 | ||
1434 | attributeReference: | ||
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] | ||
1532 | readValue: 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 | ||
1709 | decodeReference: | ||
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 | ; " | ||
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 | ; & | ||
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 | ; ' | ||
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 | ; < | ||
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 | ; > | ||
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] | ||
1857 | readProlog: 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 | |||
1883 | readXMLDecl: 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 | ||
1965 | readXMLDeclValue: | ||
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 | ||
2004 | isXMLDeclEnd: 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] | ||
2025 | readMisc: | ||
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] | ||
2075 | readComment: 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] | ||
2110 | readPI: 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 | ||
2169 | readDOCTYPE: 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 | ||
2206 | readNmtoken: jmp readName | ||
2207 | ;[cf] | ||
2208 | ;[of]: readExternalID | ||
2209 | readExternalID: | ||
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 | ||
2221 | readSystem: 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 | ||
2239 | readPublic: 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 | ||
2270 | readPubidLiteral: | ||
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 | ||
2287 | readString: 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 | ||
2301 | readIntSubset: | ||
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 | ||
2340 | readPERef: call readNextChar | ||
2341 | call readName | ||
2342 | jnz return | ||
2343 | cmp al,';' | ||
2344 | jnz invalidChar | ||
2345 | jmp ok | ||
2346 | ;[cf] | ||
2347 | ;[of]: readDecl | ||
2348 | readDecl: 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 | ||
2408 | readAttDefs: | ||
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 | ||
2433 | readAttType: 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 | ||
2481 | readDefaultDecl: | ||
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 | ||
2499 | readEntityDef: 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 | ||
2521 | readPEDef: cmp al,$27 ; ' | ||
2522 | jz readEntityValue | ||
2523 | cmp al,'"' | ||
2524 | jz readEntityValue | ||
2525 | jmp readExternalID | ||
2526 | ;[cf] | ||
2527 | |||
2528 | ;[of]: readContentSpec | ||
2529 | readContentSpec: | ||
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 | ||
2574 | readCardinality: | ||
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 | ||
2584 | readEntityValue: | ||
2585 | jmp readAttValue | ||
2586 | ;[cf] | ||
2587 | ;[of]: readAttValue | ||
2588 | readAttValue: 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] | ||
2622 | readAtom: 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 | ||
2677 | readName: | ||
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 | ||
2690 | readNextChar: 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] | ||
2697 | readBlanks: 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] | ||
2721 | skipBlanks: 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 | ||
2733 | parseChunkFull: 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 | ||
2743 | invalidAttribute: | ||
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 | ||
2772 | invalidElement: 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 | ||
2810 | closeTagMismatch: | ||
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 | ||
2833 | ok: test eax,0 | ||
2834 | return: ret | ||
2835 | ;[cf] | ||
2836 | ;[of]: invalidEntityReference | ||
2837 | invalidEntityReference: | ||
2838 | mov eax,RC_INVALID_ENTITY_REFERENCE | ||
2839 | or eax,eax | ||
2840 | ret | ||
2841 | ;[cf] | ||
2842 | ;[of]: unexpectedEnd | ||
2843 | unexpectedEnd: mov eax,RC_UNEXPECTED_END | ||
2844 | or eax,eax | ||
2845 | ret | ||
2846 | ;[cf] | ||
2847 | ;[of]: invalidChar | ||
2848 | invalidChar: mov eax,RC_INVALID_CHAR | ||
2849 | or eax,eax | ||
2850 | ret | ||
2851 | ;[cf] | ||
2852 | ;[of]: invalidPI | ||
2853 | invalidPI: mov eax,RC_INVALID_PI | ||
2854 | or eax,eax | ||
2855 | ret | ||
2856 | ;[cf] | ||
2857 | ;[of]: overflow | ||
2858 | overflow: mov eax,RC_OVERFLOW | ||
2859 | or eax,eax | ||
2860 | ret | ||
2861 | ;[cf] | ||
2862 | ;[of]: notStartTag | ||
2863 | notStartTag: mov eax,RC_NO_START_TAG | ||
2864 | or eax,eax | ||
2865 | ret | ||
2866 | ;[cf] | ||
2867 | ;[of]: tagMismatch | ||
2868 | tagMismatch: mov eax,RC_TAG_MISMATCH | ||
2869 | or eax,eax | ||
2870 | ret | ||
2871 | ;[cf] | ||
2872 | ;[of]: invalidTag | ||
2873 | invalidTag: mov eax,RC_INVALID_TAG | ||
2874 | or eax,eax | ||
2875 | ret | ||
2876 | ;[cf] | ||
2877 | ;[of]: parseOutOfMemory | ||
2878 | parseOutOfMemory: | ||
2879 | mov eax,RC_MEMORY | ||
2880 | or eax,eax | ||
2881 | ret | ||
2882 | ;[cf] | ||
2883 | ;[of]: attributeDefined | ||
2884 | attributeDefined: | ||
2885 | mov eax,RC_ATTR_DEFINED | ||
2886 | or eax,eax | ||
2887 | ret | ||
2888 | ;[cf] | ||
2889 | ;[of]: elementDefined | ||
2890 | elementDefined: | ||
2891 | mov eax,RC_ELEM_DEFINED | ||
2892 | or eax,eax | ||
2893 | ret | ||
2894 | ;[cf] | ||
2895 | ;[of]: invalidDOCTYPE | ||
2896 | invalidDOCTYPE: | ||
2897 | mov eax,RC_INVALID_DOCTYPE | ||
2898 | or eax,eax | ||
2899 | ret | ||
2900 | ;[cf] | ||
2901 | ;[of]: noVersion | ||
2902 | noVersion: 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] | ||
2926 | computeLineColumn: | ||
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] | ||
3001 | initializeClassParser: | ||
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] | ||
3015 | releaseClassParser: | ||
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] | ||
3031 | classFromString: | ||
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] | ||
3087 | classFromElement: | ||
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] | ||
3142 | declareGlobalClasses: | ||
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] | ||
3236 | countGlobals: 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] | ||
3266 | createOneClass: | ||
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 | |||
3316 | initializeClass: | ||
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 | ||
3424 | copyString: 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] | ||
3449 | buildTrees: 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] | ||
3577 | addItem: 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] | ||
3626 | addItem2: 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] | ||
3779 | newDString: 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] | ||
3822 | createElementMap: | ||
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] | ||
3930 | createElement: | ||
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] | ||
4022 | createTerminalElement: | ||
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] | ||
4093 | createAttributeMap: | ||
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] | ||
4173 | mapTerminal: 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 | ||
4189 | createMap: | ||
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] | ||
4220 | MAP_SIZE = 256*4 | ||
4221 | MAP_ALIGN = 64 | ||
4222 | ;[c] | ||
4223 | allocateMap: 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] | ||
4241 | createAttribute: | ||
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] | ||
4298 | allocateAttribute: | ||
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] | ||
4316 | countChildren: 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] | ||
4364 | findClass: 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] | ||
4410 | findGroup: 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] | ||
4514 | findOrCreateNode: | ||
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] | ||
4558 | allocateNode: 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] | ||
4581 | appendNode: 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] | ||
4603 | findNode: 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] | ||
4628 | lastNode: 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] | ||
4658 | newElementClass: | ||
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] | ||
4750 | copyElementClass: | ||
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] | ||
4790 | compareAttributeValue: | ||
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] | ||
4823 | compareAttributes: | ||
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] | ||
4858 | toInteger: 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] | ||
4908 | allocateMemory: 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] | ||
4946 | extendMemory: 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] | ||
4967 | releaseChunks: 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] | ||
4992 | newChunk: 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] | ||
5023 | freeChunk: 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] | ||
5040 | S: 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] | ||
5064 | RAC: 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] | ||
5084 | terminalChar: 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] | ||
5106 | digit: 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] | ||
5127 | xdigit: 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] | ||
5147 | noAttribute: | ||
5148 | noElement: | ||
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] | ||
5169 | PubidChar: 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] | ||
5190 | invalidClass: | ||
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] | ||
5206 | SchemaClass: 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] | ||
5220 | attributeClass: 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] | ||
5235 | textClass: 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 | ||
5248 | documentClass: 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 | ||
5260 | collectionClass: | ||
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 | ||
5273 | groupClass: | ||
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 | ||
5286 | elementClass: | ||
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 | ||
5299 | referenceClass: | ||
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 | ||
5312 | includeClass: | ||
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 | ||
5327 | schemaMap: 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 | ||
5365 | elementMap: 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 | ||
5414 | nameAttr: 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 | ||
5438 | nameIgnoreAttr: | ||
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 | ||
5468 | nameAndTypeAttr: | ||
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 | ||
5521 | schemaName db "schema",0 | ||
5522 | documentName db "document",0 | ||
5523 | attributeName db "attribute",0 | ||
5524 | textName db "text",0 | ||
5525 | collectionName db "collection",0 | ||
5526 | elementName db "element",0 | ||
5527 | referenceName db "reference",0 | ||
5528 | includeName db "include",0 | ||
5529 | groupName db "group",0 | ||
5530 | invalidName db "?",0 | ||
5531 | |||
5532 | textValue db "text",0 | ||
5533 | mixedValue db "mixed",0 | ||
5534 | |||
5535 | yes db "yes",0 | ||
5536 | no db "no",0 | ||
5537 | ;[cf] | ||
5538 | ;[cf] | ||
5539 | ;[of]:Atoms | ||
5540 | atomTable 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 | |||
5564 | DOCTYPEName db "DOCTYPE",0 | ||
5565 | ELEMENTName db "ELEMENT",0 | ||
5566 | ATTLISTName db "ATTLIST",0 | ||
5567 | PCDATAName db "PCDATA",0 | ||
5568 | IMPLIEDName db "IMPLIED",0 | ||
5569 | REQUIREDName db "REQUIRED",0 | ||
5570 | FIXEDName db "FIXED",0 | ||
5571 | NDATAName db "NDATA",0 | ||
5572 | |||
5573 | CDATAName db "CDATA",0 | ||
5574 | IDName db "ID",0 | ||
5575 | IDREFName db "IDREF",0 | ||
5576 | IDREFSName db "IDREFS",0 | ||
5577 | ENTITYName db "ENTITY",0 | ||
5578 | ENTITIESName db "ENTITIES",0 | ||
5579 | NMTOKENName db "NMTOKEN",0 | ||
5580 | NMTOKENSName db "NMTOKENS",0 | ||
5581 | NOTATIONName db "NOTATION",0 | ||
5582 | |||
5583 | versionName db "version",0 | ||
5584 | encodingName db "encoding",0 | ||
5585 | standaloneName db "standalone",0 | ||
5586 | ;[cf] | ||
5587 | ;[cf] | ||
5588 | ;[of]:BSS | ||
5589 | section '.asmdata' writeable | ||
5590 | |||
5591 | mallocFunction rd 1 | ||
5592 | freeFunction 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] | ||
5 | format ELF | ||
6 | |||
7 | include "asm-xml.asm" | ||
8 | |||
9 | ;[c] | ||
10 | ;[c]Public Functions | ||
11 | ;[c] | ||
12 | public _initialize as "ax_initialize" | ||
13 | public _initializeParser as "ax_initializeParser" | ||
14 | public _releaseParser as "ax_releaseParser" | ||
15 | public _parse as "ax_parse" | ||
16 | public _initializeClassParser as "ax_initializeClassParser" | ||
17 | public _releaseClassParser as "ax_releaseClassParser" | ||
18 | public _classFromElement as "ax_classFromElement" | ||
19 | public _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] | ||
5 | format MS COFF | ||
6 | |||
7 | include "asm-xml.asm" | ||
8 | |||
9 | ;[c] | ||
10 | ;[c]Public Functions | ||
11 | ;[c] | ||
12 | public _initialize as "_ax_initialize" | ||
13 | public _initializeParser as "_ax_initializeParser" | ||
14 | public _releaseParser as "_ax_releaseParser" | ||
15 | public _parse as "_ax_parse" | ||
16 | public _initializeClassParser as "_ax_initializeClassParser" | ||
17 | public _releaseClassParser as "_ax_releaseClassParser" | ||
18 | public _classFromElement as "_ax_classFromElement" | ||
19 | public _classFromString as "_ax_classFromString" | ||