From c9d71e61d53bf8e2200792258c9e3287ddfa3cc6 Mon Sep 17 00:00:00 2001 From: Magmus Date: Sun, 30 Jun 2013 18:11:27 -0700 Subject: Added asm-xml source --- core/XML_Parser/src/asm-xml.asm | 5594 +++++++++++++++++++++++++++++++++++++++ core/XML_Parser/src/elf.asm | 19 + core/XML_Parser/src/win32.asm | 19 + 3 files changed, 5632 insertions(+) create mode 100644 core/XML_Parser/src/asm-xml.asm create mode 100644 core/XML_Parser/src/elf.asm create mode 100644 core/XML_Parser/src/win32.asm (limited to 'core') diff --git a/core/XML_Parser/src/asm-xml.asm b/core/XML_Parser/src/asm-xml.asm new file mode 100644 index 00000000..e9c20c59 --- /dev/null +++ b/core/XML_Parser/src/asm-xml.asm @@ -0,0 +1,5594 @@ +;[c]asm-xml.asm - Asm XML Parser +;[c] +;[c]Copyright (C) 2007-12, Marc Kerbiquet +;[c]All rights reserved. +;[c] +;[c]Redistribution and use in source and binary forms, with or without +;[c]modification, are permitted provided that the following conditions are met: +;[c] +;[c]1. Redistributions of source code must retain the above copyright notice, +;[c] this list of conditions and the following disclaimer. +;[c]2. Redistributions in binary form must reproduce the above copyright notice, +;[c] this list of conditions and the following disclaimer in the documentation +;[c] and/or other materials provided with the distribution. +;[c]3. Neither the name of AsmXml nor the names of its contributors may be +;[c] used to endorse or promote products derived from this software without +;[c] specific prior written permission. +;[c] +;[c]THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;[c]AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;[c]IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;[c]DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +;[c]FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;[c]DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +;[c]SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +;[c]CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +;[c]OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +;[c]OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;[c] +;[c] +;[c]Open this file with Code Browser (http://code-browser.sourceforge.net/) +;[c]to view this long flat file as a structured text file. +;[c] +;[c]This is source code for fasm. +;[c] +;[c]Conventions: +;[c]Preserved registers: ebx esi edi ebp +;[c]Scratch registers: eax ecx edx +;[c](same as Windows/Linux/BSD) +;[c] +;[of]:Macros +macro struct name +{ + virtual at 0 + label name +} + +macro ends +{ +.sizeof rd 0 + end virtual +} +;[cf] +;[of]:Definitions + struct MemoryContext +.base rd 1 ; memory buffer +.limit rd 1 ; limit of memory buffer +.chunks rd 1 ; list of chunks +.chunkSize rd 1 ; default size of chunks + ends +;[c] + struct ParseContext +.base rd 1 ; memory buffer +.limit rd 1 ; limit of memory buffer +.chunks rd 1 ; list of chunks +.chunkSize rd 1 ; default size of chunks +.errorCode rd 1 +.source rd 1 ; address of the first char +.current rd 1 ; address of the last read char +.line rd 1 ; line number of the last read char +.column rd 1 ; column of the last read char +.root rd 1 ; root element +.version rd 2 ; version info (if any) +.encoding rd 2 ; encoding (if any) +.strict rd 1 ; 0 if not strict +.doctype rd 1 ; can read doctype +.invalidElement rb Element.sizeof + ends +;[c] + struct CreateClassContext +.base rd 1 ; memory buffer +.limit rd 1 ; limit of memory buffer +.chunks rd 1 ; list of chunks +.chunkSize rd 1 ; default size of chunks +.errorCode rd 1 +.line rd 1 ; line number of the last read char +.column rd 1 ; column of the last read char +.classes rd 1 ; the list of global classes +.rootClass rd 1 ; the root class +.rootElement rd 1 ; the root element + ends +;[c] + struct ElementClass +.offset rd 1 ; Offset of element in parent element + ; (0 when it is a collection) +.name rd 1 ; name of the element +.nameLimit rd 1 ; limit of the name +.size rd 1 ; size to store the element +.id rd 1 ; id +.type rd 1 ; container, text or mixed +.propertyCount rd 1 ; number of attributes + text elements +.childCount rd 1 ; number of child classes +.attributes rd 1 ; list of attributes +.elements rd 1 ; list of elements +.children rd 1 ; list of child classes + ; The order is the one defined in the class + ; definition file. +.shared rb 1 ; +.status rb 1 ; 0-unsolved 1-resolving 2-resolved + rb 2 ; padding +.source rd 1 ; source element + ends +;[c] + struct TextElementClass +.offset rd 1 ; Offset of attribute in element + ; (the text element is stored as an attribute) +.begin rd 1 ; element name (begin) +.limit rd 1 ; element name (last char+1) + ends +;[c] + struct Element +.id rd 1 ; id of the element +.nextSibling rd 1 +.firstChild rd 1 +.lastChild rd 1 +.reserved rd 2 ; store ignored attributes here + ends +;[c] +;[c] + struct Attribute +.begin rd 1 +.limit rd 1 + ends +;[c] +;[c] +EC_TEXT equ 1 +EC_TEXT_COLL equ 2 + +;[c] +;[c]Error Codes +;[c] +RC_OK equ 0 ; everything is ok +RC_MEMORY equ 1 ; out of memory + +; Schema +RC_EMPTY_NAME equ 10 ; name empty or not defined +RC_ATTR_DEFINED equ 11 ; attribute already defined +RC_ELEM_DEFINED equ 12 ; element already defined +RC_SCHEMA_EMPTY equ 13 ; schema does not contains a document +RC_DOCUMENT_DEFINED equ 14 ; schema contains more than one document +RC_UNDEFINED_CLASS equ 15 ; can't find collection in reference +RC_UNDEFINED_GROUP equ 16 ; can't find a group in include +RC_INVALID_ID equ 17 ; id is not a valid number +RC_INVALID_IGNORE equ 18 ; ignore is not 'yes' or 'no' +RC_RECURSIVE_ELEMENT equ 19 ; element cannot reference itself + +; Parsing +RC_INVALID_ENTITY_REFERENCE equ 20 +RC_UNEXPECTED_END equ 21 +RC_INVALID_CHAR equ 22 +RC_OVERFLOW equ 23 +RC_NO_START_TAG equ 24 +RC_TAG_MISMATCH equ 25 +RC_INVALID_TAG equ 26 +RC_INVALID_ATTRIBUTE equ 27 +RC_INVALID_PI equ 28 +RC_INVALID_DOCTYPE equ 29 +RC_VERSION_EXPECTED equ 30 + +;[c] +;[c]Various constants +;[c] +TAB_SIZE equ 8 +DEFAULT_CHUNK_SIZE equ 1024*1024 +HEADER_SIZE equ 16 ; reserved space for chunks +;[c] +TYPE_CONTAINER equ 0 +TYPE_TEXT equ 1 +TYPE_MIXED equ 2 +;[c] +ATTR_NAME equ 0 +ATTR_IGNORE equ 1 +ATTR_TYPE equ 2 +ATTR_ID equ 3 +;[c] +;[c]Class Ids +;[c] +schemaId equ 0 +documentId equ 1 +attributeId equ 2 +textId equ 3 +collectionId equ 4 +elementId equ 5 +referenceId equ 6 +includeId equ 7 +groupId equ 8 +;[c] +;[c]Resolution +;[c] +UNRESOLVED equ 0 +RESOLVING equ 1 +RESOLVED equ 2 +;[c] +;[c]Atoms (for DOCTYPE) +;[c] +ATOM_DOCTYPE equ 0 +ATOM_ELEMENT equ 1 +ATOM_ATTLIST equ 2 +ATOM_PCDATA equ 3 +ATOM_IMPLIED equ 4 +ATOM_REQUIRED equ 5 +ATOM_FIXED equ 6 +ATOM_NDATA equ 7 + +ATOM_CDATA equ 8 +ATOM_ID equ 9 +ATOM_IDREF equ 10 +ATOM_IDREFS equ 11 +ATOM_ENTITY equ 12 +ATOM_ENTITIES equ 13 +ATOM_NMTOKEN equ 14 +ATOM_NMTOKENS equ 15 +ATOM_NOTATION equ 16 + +ATOM_VERSION equ 17 +ATOM_ENCODING equ 18 +ATOM_STANDALONE equ 19 +;[cf] +;[of]:Documentation +;[c] +;[c]Element Map +;[c] +;[c] An element map is an array of 256 values each value correspond to +;[c] an action to take corresponding to the current read char: +;[c] * 1 +;[c] The character is invalid in the current state +;[c] +;[c] * Address % 4 = 0 +;[c] The address of the element map for the next char +;[c] +;[c] * Address % 4 = 1 +;[c] The address of the element class found preceded by the +;[c] remaining chars and the type of class +;[c] e.g. +;[c] "bcd", 0, t, padding, ... +;[c] * t = 0 +;[c] It is a collection, the pointer to the element class +;[c] is at the next 4 byte align. +;[c] * t = 1 +;[c] It is a text element, the text element class is stored +;[c] after the padding. +;[c] +;[c] * Address % 4 = 3 +;[c] Same as previous but all chars have already been read. +;[c] It is used when a name is the prefix of another name. +;[c] e.g.: +;[c] +;[c] +;[c] +;[c] +;[c] +;[c] +;[cf] +;[of]:C Stubs +;[of]:initialize +;[c]Initialize the library +;[c] +;[c] void ax_initialize(malloc, free) +;[c] +;[c]ARGUMENTS +;[c] malloc +;[c] the memory alllocation function +;[c] free +;[c] the free memory function +;[c] +;[c] +_initialize: push ebx + mov eax,[esp+8+0] + mov ebx,[esp+8+4] + call initialize + pop ebx + ret +;[cf] +;[of]:initializeParser +;[c]Initialize the parse context +;[c] +;[c] errorCode = ax_initializeParser(context, chunkSize) +;[c] +;[c]ARGUMENTS +;[c] context +;[c] the parse context. +;[c] chunkSize +;[c] the default size of chunk +;[c] +;[c]RETURN VALUE +;[c] The error code +;[c] +_initializeParser: + push ebp + mov ebp,[esp+8+0] + mov ecx,[esp+8+4] + call initializeParser + pop ebp + ret +;[cf] +;[of]:releaseParser +;[c]Release the parse context +;[c] +;[c] ax_releaseParser(context) +;[c] +;[c]ARGUMENTS +;[c] context +;[c] the parse context. The memory base and memory limit must be +;[c] initialized. +;[c] +_releaseParser: push ebp + mov ebp,[esp+8+0] + call releaseParser + pop ebp + ret +;[cf] +;[of]:parse +;[c]Parse an XML string +;[c] +;[c] Element* ax_parse(context, source, type, strict) +;[c] +;[c]ARGUMENTS +;[c] context +;[c] the parse context. The object must have been initialized. +;[c] source +;[c] the xml to parse +;[c] type +;[c] the expected type of element to parse +;[c] +;[c]RETURN VALUE +;[c] The created element or null if an error occured. +;[c] +_parse: push ebx + push esi + push edi + push ebp + + mov ebp,[esp+20+ 0] + mov esi,[esp+20+ 4] + mov edx,[esp+20+ 8] + mov edi,[esp+20+12] + call parse + + mov [ebp+ParseContext.current],esi + mov [ebp+ParseContext.errorCode],eax + jz .ok + call computeLineColumn + xor eax,eax + jmp .error + +.ok: mov eax,[ebp+ParseContext.root] +.error: pop ebp + pop edi + pop esi + pop ebx + ret +;[c] +;[cf] +;[c] +;[of]:initializeClassParser +;[c]Initialize the class parser +;[c] +;[c] errorCode = ax_initializeClassParser(context) +;[c] +;[c]ARGUMENTS +;[c] context +;[c] the class parser. +;[c] +;[c]RETURN VALUE +;[c] The error code +;[c] +_initializeClassParser: + push ebp + mov ebp,[esp+8+0] + call initializeClassParser + pop ebp + ret +;[cf] +;[of]:releaseClassParser +;[c]Release the class parser +;[c] +;[c] ax_releaseClassParser(context) +;[c] +;[c]ARGUMENTS +;[c] context +;[c] the class parser. +;[c] +_releaseClassParser: + push ebp + mov ebp,[esp+8+0] + call releaseClassParser + pop ebp + ret +;[cf] +;[of]:classFromElement +;[c]Create a class from an element +;[c] +;[c] ElementClass* ax_classFromElement(element, context) +;[c] +;[c]ARGUMENTS +;[c] element +;[c] the xml element describing the class +;[c] context +;[c] the class context. +;[c] +;[c]RETURN VALUE +;[c] The created class or null if an error occured. +;[c] +_classFromElement: + push esi + push edi + push ebp + + mov esi,[esp+16] + mov ebp,[esp+16+4] + call classFromElement + mov [ebp+CreateClassContext.errorCode],eax + jnz .failed + mov eax,[ebp+CreateClassContext.rootClass] + +.error: pop ebp + pop edi + pop esi + ret + +.failed: xor eax,eax + jmp .error +;[c] +;[cf] +;[of]:classFromString +;[c]Create a class from a string +;[c] +;[c] ElementClass* ax_classFromString(string, context) +;[c] +;[c]ARGUMENTS +;[c] string +;[c] the xml element describing the class +;[c] context +;[c] the class context. +;[c] +;[c]RETURN VALUE +;[c] The created class or null if an error occured. +;[c] +_classFromString: + push ebx + push esi + push edi + push ebp + + mov esi,[esp+20+0] + mov ebp,[esp+20+4] + call classFromString + mov [ebp+CreateClassContext.errorCode],eax + jnz .failed + mov eax,[ebp+CreateClassContext.rootClass] + +.error: pop ebp + pop edi + pop esi + pop ebx + ret + +.failed: xor eax,eax + jmp .error +;[cf] +;[cf] +;[of]:Functions +;[of]:initialize +;[c]Initialize the library +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] the allocator function +;[c] ebx +;[c] the free memory function +;[c] +initialize: + mov [mallocFunction],eax + mov [freeFunction],ebx + ret +;[cf] + +;[of]:initializeParser +;[c]Initialize the parse context object +;[c] +;[c]ARGUMENTS +;[c] ebp +;[c] the parse context +;[c] ecx +;[c] chunk size +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] +initializeParser: + xor eax,eax + mov [ebp+ParseContext.chunkSize],ecx + mov [ebp+ParseContext.chunks],eax + mov eax,ecx + jmp newChunk +;[cf] +;[of]:releaseParser +;[c]Release the parse context object +;[c] +;[c]ARGUMENTS +;[c] ebp +;[c] the parse context +;[c] +releaseParser: jmp releaseChunks +;[cf] +;[of]:parse +;[c]parse +;[c] +;[c]ARGUMENTS +;[c] edx +;[c] the type of the root element +;[c] esi +;[c] source +;[c] edi +;[c] strict flag +;[c] ebp +;[c] Parse context +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] esi +;[c] Address of the first byte after the element. +;[c] edi +;[c] ??? +;[c] +parse: mov [ebp+ParseContext.source],esi + mov [ebp+ParseContext.strict],edi + mov [ebp+ParseContext.doctype],1 + + sub eax,eax + mov [ebp+ParseContext.version+Attribute.begin],eax + mov [ebp+ParseContext.version+Attribute.limit],eax + mov [ebp+ParseContext.encoding+Attribute.begin],eax + mov [ebp+ParseContext.encoding+Attribute.limit],eax + + ; Allocate memory for root element + mov edi,[ebp+ParseContext.base] + mov eax,[ebp+ParseContext.limit] + mov ebx,edi + add ebx,[edx+ElementClass.size] + cmp ebx,eax + jae parseChunkFull + mov [ebp+ParseContext.base],ebx + mov [ebp+ParseContext.root],edi + +resumeParseChunkFull: + + ; Clear higher bits of eax + ; All the functions assume that the high bits of eax + ; are always zero. + xor eax,eax + + call readProlog + jnz return + + call readRootElement + jnz return + + ; forbid the doctype + mov [ebp+ParseContext.doctype],0 + + call readMisc + jnz return + + ; error if there is remaining chars + or al,al + jnz invalidChar + + xor eax,eax + ret +;[c] +;[c]Sub-functions +;[c] +;[of]: readRootElement +readRootElement: + cmp al,'<' + jnz notStartTag + +;[of]: Initialize Element + mov eax,[edx+ElementClass.id] + mov [edi+Element.id],eax + xor eax,eax + mov [edi+Element.firstChild],eax + mov [edi+Element.lastChild],eax + mov [edi+Element.nextSibling],eax + + mov ecx,[edx+ElementClass.propertyCount] + lea ebx,[edi+Element.sizeof] + + or ecx,ecx + jz .m0 + + shr ecx,1 + jnc .m2 + mov [ebx+Attribute.begin],eax + mov [ebx+Attribute.limit],eax + jz .m0 + add ebx,Attribute.sizeof + +.m2: shr ecx,1 + jnc .m4 + mov [ebx+Attribute.begin],eax + mov [ebx+Attribute.limit],eax + mov [ebx+Attribute.sizeof+Attribute.begin],eax + mov [ebx+Attribute.sizeof+Attribute.limit],eax + jz .m0 + add ebx,Attribute.sizeof*2 + +.m4: mov [ebx+Attribute.sizeof*0+Attribute.begin],eax + mov [ebx+Attribute.sizeof*0+Attribute.limit],eax + mov [ebx+Attribute.sizeof*1+Attribute.begin],eax + mov [ebx+Attribute.sizeof*1+Attribute.limit],eax + mov [ebx+Attribute.sizeof*2+Attribute.begin],eax + mov [ebx+Attribute.sizeof*2+Attribute.limit],eax + mov [ebx+Attribute.sizeof*3+Attribute.begin],eax + mov [ebx+Attribute.sizeof*3+Attribute.limit],eax + add ebx,Attribute.sizeof*4 + dec ecx + jnz .m4 +.m0: +;[cf] +;[of]: Read Element Name +;[c]Read Element Name +;[c] + mov ebx,edi + mov edi,[edx+ElementClass.name] + mov ecx,[edx+ElementClass.nameLimit] +.loop: cmpsb + jnz invalidTag + cmp edi,ecx + jnz .loop + mov edi,ebx + + movzx eax,byte [esi] + add esi,1 + cmp al,'>' + jz readContent + cmp al, '/' + jz endOfElement + test byte [S + eax], 1 + jz invalidChar +;[cf] +;[of]: Read Attributes +;[c]Read Attributes +;[c] +;[c]Read the next attribute (skip blanks first) +;[c] +nextAttribute: + ; Skip blanks +.sb: movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz .sb + +;[c] +;[c]Read the next attribute (blanks already skipped, first char already read) +;[c] +readAttributes: + ; No more attributes ? + cmp al, '>' + jz readContentOrText + cmp al, '/' + jz endOfElement + +;[c] +;[c]Read and Decode Attribute Name +;[c] +readAttribute: mov ebx,[edx+ElementClass.attributes] + mov ecx,[ebx+eax*4] ; first char already loaded + test ecx,1 + jnz .j2 +.l2: movzx eax,byte [esi] + mov ecx,[ecx+eax*4] + add esi,1 + test ecx,1 + jz .l2 + + test ecx,2 + jnz terminalAttribute +.j2: sub ecx,1 + jz invalidAttribute + align 4 +.l21: movzx eax,byte [esi] + add ecx,1 + add esi,1 + cmp [ecx-1],al + jz .l21 + test byte [ecx-1],255 + jnz invalidAttribute + +commonAttribute: + mov ebx,edi + add ebx,[ecx] + +;[c] +;[c]Skip Blanks and Equal Sign +;[c] + cmp al,'=' ; I'm feeling lucky + jz readAttributeValue ; + + test byte [S + eax], 1 ; Not '=', it MUST be a blank + jz invalidAttribute ; or it is an invalid attribute + +.skipBlank2: movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz .skipBlank2 + + cmp al,'=' + jnz invalidChar + +readAttributeValue: + movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz readAttributeValue + + cmp al,$27 ; ' + jz .value + cmp al,'"' + jnz invalidChar +.value: mov cl,al + +;[c] +;[c]Read and Store Value +;[c] + cmp [ebx+Attribute.begin],0 + jnz attributeDefinedOrIgnored +resumeBecauseIgnored: + mov [ebx+Attribute.begin],esi + mov ch,'&' +.l3: mov al,[esi] + add esi,1 + ;test byte [RAC + eax], 1 ; slower but it would allow + ;jz .l3 ; detection of < in attribute + ;cmp al,'<' ; makes the parser 5% slower + ;jz invalidChar ; + cmp al,ch + jz attributeReference + or al,al + jz unexpectedEnd + cmp al,cl + jnz .l3 + + lea ecx,[esi-1] + mov [ebx+Attribute.limit],ecx +;[c] +endOfAttribute: + ; Read next char + movzx eax,byte [esi] + add esi,1 + + ; Is it a blank ? + test byte [S + eax], 1 + jnz nextAttribute + + ; Is it a closing tag ? + cmp al, '>' + jz readContentOrText + + ; Is it not the end of the element ? + cmp al, '/' + jnz readAttribute + +endOfElement: movzx eax,byte [esi] + add esi,1 + cmp al,'>' + jnz invalidChar + xor eax,eax + ret +;[c] +terminalAttribute: + and ecx,not 2 + jmp commonAttribute +;[c] +attributeDefinedOrIgnored: + mov eax,ebx + sub eax,edi + cmp eax,Element.reserved + jz resumeBecauseIgnored + jmp attributeDefined +;[cf] + +;[of]: Read Content +;[c]Read Content +;[c] +readContentOrText: + ; test if the content is just text + cmp [edx+ElementClass.type],TYPE_TEXT + jz readInnerText +;[c] +readContent: + cmp [edx+ElementClass.type],TYPE_MIXED + jz readPCDATA + mov bl,'<' + +.loop: mov al,[esi] + or al,al + jz unexpectedEnd + add esi,1 + cmp al,bl + jnz .loop + + mov al,[esi] + cmp al, '/' + jnz referenceOrComment + +;[of]:Read Close Tag +readCloseTag: + add esi,1 + + mov edi,[edx+ElementClass.name] + mov ecx,[edx+ElementClass.nameLimit] +.loop: cmpsb + jnz closeTagMismatch + cmp edi,ecx + jnz .loop + + movzx eax,byte [esi] + add esi,1 + cmp al, '>' ; I'm feeling lucky + jnz .skipBlanks4 ; + xor eax,eax + ret + +.skipBlanks4: test byte [S + eax], 1 + jz invalidChar +.skipBlank4: movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz .skipBlank4 + cmp al, '>' + jnz invalidChar + + xor eax,eax ; element successfully read + ret +;[cf] + +referenceOrComment: + cmp al,'!' + jz skipCommentOrCDATA + cmp al,'?' + jz skipContentPI +;[of]:Read Child Element +;[c]Read a child element (may be a text-only element) +;[c] +readChild: add esi,1 +;[c] +;[c]Decode Element Name +;[c] + mov ebx,[edx+ElementClass.elements] + mov ecx,[ebx+eax*4] ; first char already loaded + test ecx,1 + jnz .skip +.loop: movzx eax,byte [esi] + mov ecx,[ecx+eax*4] + add esi,1 + test ecx,1 + jz .loop + +.skip: test ecx,2 + jnz terminalElement + dec ecx + jz invalidElement +.loop2: movzx eax,byte [esi] + add ecx,1 + add esi,1 + cmp [ecx-1],al + jz .loop2 + test byte [ecx-1],255 + jnz invalidElement + + mov bl,[ecx] + +;[of]:Skip Blanks + test byte [S + eax], 1 + jz .eNotBlank1 +.eSkipBlank1: movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz .eSkipBlank1 +.eNotBlank1: +;[cf] + + add ecx,3+1 + and ecx,$FFFFFFFC + test bl,1 + jz readChildElement + +;[c] +;[of]:Read Text +;[c]Read a Text-Only Element +;[c] +;[c] * esi is the source +;[c] * edi is the element +;[c] +;[c] * ecx is the text element descriptor +;[c] * al is the last non blank character in the tag (must be '>') +;[c] +readText: + mov ebx,edi + add ebx,[ecx+TextElementClass.offset] + + cmp al,'/' + jz emptyText + cmp al,'>' + jnz invalidChar + + mov [ebx+Attribute.begin],esi + + movzx eax,byte [esi] + add esi,1 + cmp al,'<' + jz emptyOrCDATAOrPI + or al,al + jz unexpectedEnd + cmp al,'&' + jz textReference + +.loop: movzx eax,byte [esi] + add esi,1 + or al,al + jz unexpectedEnd + cmp al,'&' + jz textReference + cmp al,'<' + jnz .loop + + movzx eax,byte [esi] + cmp al,'!' + jz textCommentOrCDATA + cmp al,'?' + jz textPI + +endOfEmptyText: sub esi,1 + mov [ebx+Attribute.limit],esi + add esi,1 + +endOfText: add esi,1 + cmp al, '/' + jnz invalidChar + + mov ebx,edi + mov edi,[ecx+TextElementClass.begin] + mov ecx,[ecx+TextElementClass.limit] +.loop: cmpsb + jnz tagMismatch + cmp edi,ecx + jnz .loop + mov edi,ebx + +.eSkipBlank2: movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz .eSkipBlank2 + + cmp al,'>' + jz readContent + jmp invalidChar +;[c] +emptyOrCDATAOrPI: + movzx eax,byte [esi] + cmp al,'?' + jz textPI + cmp al,'!' + jnz endOfEmptyText + cmp byte [esi+1],'[' + jnz invalidCharOrComment + cmp byte [esi+2],'C' + jnz invalidChar + cmp byte [esi+3],'D' + jnz invalidChar + cmp byte [esi+4],'A' + jnz invalidChar + cmp byte [esi+5],'T' + jnz invalidChar + cmp byte [esi+6],'A' + jnz invalidChar + cmp byte [esi+7],'[' + jnz invalidChar + add esi,8 + mov [ebx+Attribute.begin],esi + +.loop: movzx eax,byte [esi] + add esi,1 + or al,al + jz unexpectedEnd + cmp al,']' + jnz .loop + movzx eax,byte [esi] + cmp al,']' + jnz .loop + mov al,[esi+1] + cmp al,'>' + jnz .loop + + mov al,[esi+2] + cmp al,'<' + jnz .mixed + + sub esi,1 + mov [ebx+Attribute.limit],esi + add esi,4 + movzx eax,byte [esi] + jmp endOfText +;[c] +;[c]The text starts with a CDATA section but contain something else, +;[c]let 's read it again with the slow method +;[c] +.mixed: mov esi,[ebx+Attribute.begin] + sub esi,9 ; size("' + jnz invalidChar + mov [ebx+Attribute.begin],esi ; any non null ptr is ok + mov [ebx+Attribute.limit],esi + jmp readContent +;[cf] +;[of]:Read a Child Element +;[c]Read a Child Element +;[c] +;[c] * esi source +;[c] * edi parent element +;[c] * ecx the element description in parent +;[c] * edx type of parent +;[c] + +readChildElement: + + push edx + mov edx,[ecx] + + ; Allocate memory + mov ecx,[ebp+ParseContext.base] + mov ebx,[edx+ElementClass.size] + add ebx,ecx + cmp ebx,[ebp+ParseContext.limit] + jae .chunkFull + mov [ebp+ParseContext.base],ebx +.resume: + ; It is an element, not a collection: + ; it must be store in an attribute slot instead of + ; in the list of children. + ; This case should be exceptional, it is placed + ; out of the main flow to avoid breaking the pipeline + cmp [edx+ElementClass.offset],0 + jnz .element + + ; Append element + cmp dword [edi+Element.firstChild],0 + jnz .rce1 + mov [edi+Element.firstChild],ecx +.rce1: mov ebx,[edi+Element.lastChild] + or ebx,ebx + jz .rce2 + mov [ebx+Element.nextSibling],ecx +.rce2: mov [edi+Element.lastChild],ecx + +.resume2: push edi + mov edi,ecx +;[of]: Initialize Element + push eax + mov eax,[edx+ElementClass.id] + mov [edi+Element.id],eax + xor eax,eax + mov [edi+Element.firstChild],eax + mov [edi+Element.lastChild],eax + mov [edi+Element.nextSibling],eax + + mov ecx,[edx+ElementClass.propertyCount] + lea ebx,[edi+Element.sizeof] + + or ecx,ecx + jz .xm0 + + shr ecx,1 + jnc .xm2 + mov [ebx+Attribute.begin],eax + mov [ebx+Attribute.limit],eax + jz .xm0 + add ebx,Attribute.sizeof + +.xm2: shr ecx,1 + jnc .xm4 + mov [ebx+Attribute.begin],eax + mov [ebx+Attribute.limit],eax + mov [ebx+Attribute.sizeof+Attribute.begin],eax + mov [ebx+Attribute.sizeof+Attribute.limit],eax + jz .xm0 + add ebx,Attribute.sizeof*2 + +.xm4: mov [ebx+Attribute.sizeof*0+Attribute.begin],eax + mov [ebx+Attribute.sizeof*0+Attribute.limit],eax + mov [ebx+Attribute.sizeof*1+Attribute.begin],eax + mov [ebx+Attribute.sizeof*1+Attribute.limit],eax + mov [ebx+Attribute.sizeof*2+Attribute.begin],eax + mov [ebx+Attribute.sizeof*2+Attribute.limit],eax + mov [ebx+Attribute.sizeof*3+Attribute.begin],eax + mov [ebx+Attribute.sizeof*3+Attribute.limit],eax + add ebx,Attribute.sizeof*4 + dec ecx + jnz .xm4 + +.xm0: pop eax +;[cf] + call readAttributes + pop edi + pop edx + jz readContent + ret +;[c] +.element: mov ebx,[edx+ElementClass.offset] + cmp [edi+ebx+Attribute.begin],0 + jnz .elementDefined + mov [edi+ebx+Attribute.begin],ecx + jmp .resume2 + +.elementDefined: + pop edx + jmp elementDefined +;[c] +.chunkFull: push eax + push edx + push edi + mov eax,[edx+ElementClass.size] + call extendMemory + mov ecx,edi + pop edi + pop edx + pop eax + jz .resume + pop edx + jmp parseOutOfMemory +;[cf] +;[c] +terminalElement: + add ecx,1 + mov bl,[ecx-3] + +;[of]:Skip Blanks + test byte [S + eax], 1 + jz .eNotBlank1 +.eSkipBlank1: movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz .eSkipBlank1 +.eNotBlank1: +;[cf] + + test bl,1 + jz readChildElement + jmp readText +;[cf] +;[of]:Skip comment +skipCommentOrCDATA: + add esi,1 + movzx eax,byte [esi] + add esi,1 + cmp al,'-' + jz .comment +;[c] +.CDATA: cmp al,'[' + jnz invalidChar + cmp byte [esi],'C' + jnz invalidChar + cmp byte [esi+1],'D' + jnz invalidChar + cmp byte [esi+2],'A' + jnz invalidChar + cmp byte [esi+3],'T' + jnz invalidChar + cmp byte [esi+4],'A' + jnz invalidChar + cmp byte [esi+5],'[' + jnz invalidChar + add esi,6 + +.cd1: movzx eax,byte [esi] + add esi,1 + or al,al + jz unexpectedEnd + cmp al,']' + jnz .cd1 + movzx eax,byte [esi] + cmp al,']' + jnz .cd1 + mov al,[esi+1] + cmp al,'>' + jnz .cd1 + add esi,2 + jmp readContent +;[c] +.comment: call readComment + jnz return + jmp readContent +;[cf] +;[of]:Skip processing instruction +skipContentPI: call readPI + jnz return + jmp readContent +;[cf] +;[c] +;[of]:Read Inner Text +;[c]Read a Text-Only Element +;[c] +;[c] * esi is the source +;[c] * edi is the element +;[c] * edx is the type of the element +;[c] +;[c] * al is the last non blank character in the tag (must be '>') +;[c] +readInnerText: lea ebx,[edi+Element.sizeof] + mov [ebx+Attribute.begin],esi + + mov ecx,'&' * 256 + '<' + + movzx eax,byte [esi] + add esi,1 + cmp al,cl + jz innerEmptyOrCDATAOrPI + or al,al + jz unexpectedEnd + cmp al,ch + jz innerTextReference + +.loop: movzx eax,byte [esi] + add esi,1 + or al,al + jz unexpectedEnd + cmp al,ch + jz innerTextReference + cmp al,cl + jnz .loop + + movzx eax,byte [esi] + cmp al,'!' + jz innerTextCommentOrCDATA + cmp al,'?' + jz innerPI + +innerEndOfEmptyText: + dec esi + mov [ebx+Attribute.limit],esi + inc esi + +innerEndOfText: cmp al, '/' + jnz invalidChar + jmp readCloseTag +;[c] +innerEmptyOrCDATAOrPI: + movzx eax,byte [esi] + cmp al,'?' + jz innerPI + cmp al,'!' + jnz innerEndOfEmptyText + cmp byte [esi+1],'[' + jnz innerInvalidCharOrComment + cmp byte [esi+2],'C' + jnz invalidChar + cmp byte [esi+3],'D' + jnz invalidChar + cmp byte [esi+4],'A' + jnz invalidChar + cmp byte [esi+5],'T' + jnz invalidChar + cmp byte [esi+6],'A' + jnz invalidChar + cmp byte [esi+7],'[' + jnz invalidChar + add esi,8 + mov [ebx+Attribute.begin],esi + +.loop: movzx eax,byte [esi] + add esi,1 + or al,al + jz unexpectedEnd + cmp al,']' + jnz .loop + movzx eax,byte [esi] + cmp al,']' + jnz .loop + mov al,[esi+1] + cmp al,'>' + jnz .loop + + mov al,[esi+2] + cmp al,'<' + jnz .mixed + + sub esi,1 + mov [ebx+Attribute.limit],esi + add esi,4 + movzx eax,byte [esi] + jmp innerEndOfText +;[c] +;[c]The text starts with a CDATA section but contain something else, +;[c]let 's read it again with the slow method +;[c] +.mixed: mov esi,[ebx+Attribute.begin] + sub esi,9 ; size("' + jnz .cd1 + add esi,2 + jmp .decodeContent + +.cd3: call .realloc + jmp .cd2 +;[cf] +;[of]:Skip Comments +.comment: call readComment + jnz .error + jmp .decodeContent +;[cf] +;[of]:Skip PI +.PI: call readPI + jnz .error + jmp .decodeContent +;[cf] +;[cf] +;[of]: decodeReference +decodeReference: + movzx eax,byte [esi] + cmp al,'#' + jz .num + cmp al,'a' + jz .a + cmp al,'l' + jz .l + cmp al,'g' + jz .g + cmp al,'q' + jnz .invalidEntityReference + + ; " +.q: cmp byte [esi+1],'u' + jnz .invalidEntityReference + cmp byte [esi+2],'o' + jnz .invalidEntityReference + cmp byte [esi+3],'t' + jnz .invalidEntityReference + cmp byte [esi+4],';' + jnz .invalidEntityReference + add esi,5 + mov al,'"' + ret + +.num: add esi,1 + xor edx,edx + movzx eax,byte [esi] + add esi,1 + cmp al,'x' + jz .hexa + test byte [digit+eax],1 + jz .invalidChar +.nextDigit: sub al,'0' + imul edx,10 + jc .overflow + add edx,eax + jc .overflow + movzx eax,byte [esi] + add esi,1 + test byte [digit+eax],1 + jnz .nextDigit + cmp al,';' + jnz .invalidEntityReference + mov eax,edx + test edx,$FFFFFF00 + jnz .invalidChar + ret + +.hexa: movzx eax,byte [esi] + add esi,1 + test byte [digit+eax],2 + jz .invalidChar +.nextXDigit: shl edx,4 + jc .overflow + or dl,[xdigit+eax] + movzx eax,byte [esi] + add esi,1 + test byte [digit+eax],2 + jnz .nextXDigit + cmp al,';' + jnz .invalidEntityReference + mov eax,edx + test edx,$FFFFFF00 + jnz .invalidChar + ret + +.a: mov al,[esi+1] + cmp al,'p' + jz .ap + cmp al,'m' + jnz .invalidEntityReference + + ; & +.am: cmp byte [esi+2],'p' + jnz .invalidEntityReference + cmp byte [esi+3],';' + jnz .invalidEntityReference + add esi,4 + mov al,'&' + ret + + ; ' +.ap: cmp byte [esi+2],'o' + jnz .invalidEntityReference + cmp byte [esi+3],'s' + jnz .invalidEntityReference + cmp byte [esi+4],';' + jnz .invalidEntityReference + add esi,5 + mov al,$27 + ret + + ; < +.l: cmp byte [esi+1],'t' + jnz .invalidEntityReference + cmp byte [esi+2],';' + jnz .invalidEntityReference + add esi,3 + mov al,'<' + ret + + ; > +.g: cmp byte [esi+1],'t' + jnz .invalidEntityReference + cmp byte [esi+2],';' + jnz .invalidEntityReference + add esi,3 + mov al,'>' + ret +;[c] +.invalidChar: add esp,4 + pop edi + pop edx + pop ecx + jmp invalidChar +;[c] +.overflow: add esp,4 + pop edi + pop edx + pop ecx + jmp overflow +;[c] +.invalidEntityReference: + add esp,4 + pop edi + pop edx + pop ecx + jmp invalidEntityReference +;[cf] +;[of]: readProlog +;[c]Read the prolog +;[c] +;[c] The time is not critical here, so the code is less optimized: +;[c] - use of subfunctions +;[c] - return error code (instead of direct exit) +;[c] +;[c]ARGUMENTS +;[c] esi +;[c] source +;[c] +;[c]RETURN VALUES +;[c] zf+eax +;[c] error code (zf=0) or current char (zf=1) +;[c] esi +;[c] next source char +;[c] +readProlog: call readXMLDecl + jnz return + jmp readMisc +;[cf] +;[of]: readXMLDecl +;[c]Read the XML declaration +;[c] +;[c]ARGUMENTS +;[c] esi +;[c] next char to read +;[c] +;[c]RETURN VALUES +;[c] zf+eax +;[c] error code +;[c] esi +;[c] next char to read +;[c] +;[c]REMARKS +;[c] If there is no xml-decl, the function just returns the same pointer +;[c] and the ok flag. +;[c] + + struct XDA +.value rd 2 + ends + +readXMLDecl: push edi + sub esp,XDA.sizeof + mov edi,esp + call .goon + lea esp,[esp+XDA.sizeof] + pop edi + ret + +.goon: cmp byte [esi],'<' + jnz ok + cmp byte [esi+1],'?' + jnz ok + cmp byte [esi+2],'x' + jnz ok + cmp byte [esi+3],'m' + jnz ok + cmp byte [esi+4],'l' + jnz ok + add esi,5 + + ; Read version + ; ------------ + call readNextChar + call readBlanks + jnz return + call readAtom + jnz return + cmp ecx,ATOM_VERSION + jnz noVersion + + call readXMLDeclValue + jnz return + + mov ecx,[edi+XDA.value+Attribute.begin] + mov [ebp+ParseContext.version+Attribute.begin],ecx + mov ecx,[edi+XDA.value+Attribute.limit] + mov [ebp+ParseContext.version+Attribute.limit],ecx + + ; Read encoding + ; ------------- + call isXMLDeclEnd + jz ok + call readBlanks + jnz return + call isXMLDeclEnd + jz return + call readAtom + jnz return + cmp ecx,ATOM_ENCODING + jnz .notEncoding + + call readXMLDeclValue + jnz return + + mov ecx,[edi+XDA.value+Attribute.begin] + mov [ebp+ParseContext.encoding+Attribute.begin],ecx + mov ecx,[edi+XDA.value+Attribute.limit] + mov [ebp+ParseContext.encoding+Attribute.limit],ecx + + ; Read standalone + ; --------------- + call isXMLDeclEnd + jz ok + call readBlanks + jnz return + call isXMLDeclEnd + jz ok + call readAtom + jnz return +.notEncoding: cmp ecx,ATOM_STANDALONE + jnz invalidChar + + call readXMLDeclValue + jnz return + + ; Terminate + ; --------- + call isXMLDeclEnd + jz ok + jmp invalidChar + +;[of]:readXMLDeclValue +readXMLDeclValue: + + ; Skip blanks + ; ----------- + call skipBlanks + + ; Skip equals + ; ----------- + cmp al,'=' + jnz invalidChar + call readNextChar + + ; Skip blanks + ; ----------- + call skipBlanks + + ; Skip quote + ; ---------- + cmp al,$27 ; ' + jz .value + cmp al,'"' + jnz invalidChar +.value: mov cl,al + mov [edi+XDA.value+Attribute.begin],esi + +.loopValue: movzx eax,byte [esi] + add esi,1 + or al,al + jz unexpectedEnd + cmp al,' ' ; Let's forbid blanks + jz invalidChar ; + cmp al,cl + jnz .loopValue + lea ecx,[esi-1] + mov [edi+XDA.value+Attribute.limit],ecx + + jmp readNextChar +;[cf] +;[of]:isXMLDeclEnd +isXMLDeclEnd: cmp al,'?' + jnz return + cmp byte [esi],'>' + jnz return + lea esi,[esi+1] + ret +;[cf] +;[cf] +;[of]: readMisc +;[c]Read stuff before or after the root element +;[c] +;[c]ARGUMENTS +;[c] esi +;[c] next char to read +;[c] +;[c]RETURN VALUES +;[c] zf+eax +;[c] error code (zf=0) or current char (zf=1) +;[c] esi +;[c] next char to read +;[c] +readMisc: + ; Skip blanks +.sb: movzx eax,byte [esi] + add esi,1 + test byte [S + eax], 1 + jnz .sb + + cmp al,'<' + jnz .done + + cmp byte [esi],'?' + jnz .notPI + + call readPI + jmp .next + +.notPI: cmp byte [esi],'!' + jnz .done + add esi,1 + + movzx eax,byte [esi] + add esi,1 + cmp al,'-' + jnz .notComment + + call readComment + jmp .next + +.notComment: call readDOCTYPE + +.next: jnz return + jmp .sb + +.done: test eax,0 + ret +;[cf] +;[of]: readComment +;[c]Read a comment +;[c] +;[c]ARGUMENTS +;[c] esi +;[c] points to the 2nd '-' of Node +; | |next +; |next +; | +; | succ +; Node ---------> Node +; | +; |next +; | +; | succ +; Node ---------> Node +; | +; |next +; . +; . + +;[cf] +;[of]:Definitions + struct Node +.next rd 1 +.succ rd 1 +.char rb 1 +.shared rb 1 + rb 2 +.index rd 1 +.collectionClass rd 1 +.nameBegin rd 1 +.nameLimit rd 1 + ends +;[cf] +;[c] +;[of]:findOrCreateNode +;[c]Find or create a node +;[c] +;[c]ARGUMENTS +;[c] esi +;[c] the parent node or nil +;[c] al +;[c] the char +;[c] +;[c]RETURN VALUES +;[c] zf +;[c] 0 if error +;[c] eax +;[c] error code +;[c] esi +;[c] the new parent node +;[c] edi +;[c] the found or created node +;[c] +;[c]REMARKS +;[c] If the node already exists, the shared flag is set. +;[c] +findOrCreateNode: + + call findNode + jz .notFound + + mov [edi+Node.shared],1 + jmp .ok + + ; Allocate a node +.notFound: push eax + call allocateNode + pop edx + jnz .error + + ; Append node + call appendNode + + ; Initialize node + xor eax,eax + mov [edi+Node.next],eax + mov [edi+Node.succ],eax + mov [edi+Node.char],dl + mov [edi+Node.shared],al + mov [edi+Node.index],-1 + mov [edi+Node.collectionClass],eax + +.ok: xor eax,eax +.error: ret +;[cf] +;[of]:allocateNode +;[c]Allocates a node +;[c] +;[c]ARGUMENTS +;[c] ebp +;[c] the tree builder local variables +;[c] +;[c]RETURN VALUES +;[c] zf +;[c] 0 if not enough memory +;[c] eax +;[c] error code +;[c] edi +;[c] the node +;[c] +allocateNode: mov ecx,4 + mov eax,Node.sizeof + mov edx,[ebp+TreeBuilder.context] + jmp allocateMemory +;[cf] +;[of]:appendNode +;[c]Append a node +;[c] +;[c]ARGUMENTS +;[c] esi +;[c] parent node +;[c] edi +;[c] node to append to parent +;[c] +;[c]RETURN VALUES +;[c] esi +;[c] parent node +;[c] edi +;[c] node to append +;[c] +;[c]REMARKS +;[c] if the parent node is nil (i.e. empty), edi becomes the parent. +;[c] +appendNode: call lastNode + jz .empty + mov [esi+Node.next],edi + ret +.empty: mov esi,edi + ret +;[cf] +;[of]:findNode +;[c]Find a node +;[c] +;[c]ARGUMENTS +;[c] al +;[c] char +;[c] esi +;[c] parent node +;[c] +;[c]RETURN VALUES +;[c] edi +;[c] search node or nil +;[c] zf +;[c] 1 if not found +;[c] +findNode: mov edi,esi + jmp .first + +.next: cmp al,[edi+Node.char] + jz .done + mov edi,[edi+Node.next] +.first: or edi,edi + jnz .next + +.done: or edi,edi + ret +;[cf] +;[of]:lastNode +;[c]Returns the last node +;[c] +;[c]ARGUMENTS +;[c] esi +;[c] parent node +;[c] +;[c]RETURN VALUES +;[c] esi +;[c] the last node +;[c] zf +;[c] 1 if the list of nodes is empty +;[c] +lastNode: or esi,esi + jnz .first + ret +.next: mov esi,eax +.first: mov eax,[esi+Node.next] + or eax,eax + jnz .next + or esi,esi + ret +;[cf] +;[cf] +;[cf] + +;[of]: newElementClass +;[c]Create a new element class +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] source element +;[c] ebx +;[c] is element +;[c] ecx +;[c] context +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] ebx +;[c] the new element class +;[c] +newElementClass: + push esi + push edi + mov esi,eax + + ; + ; Allocate memory for element class + name + ; + mov eax,[esi+Element.sizeof+Attribute.limit] + sub eax,[esi+Element.sizeof+Attribute.begin] + add eax,ElementClass.sizeof+1 + mov edx,ecx + mov ecx,4 + call allocateMemory + jnz .error + + ; + ; Reset offset + ; + ; the offset is set to 0 if the element is a collection, + ; and it is temporary set to 1 if it is an element, it + ; is just a flag now, but it will replaced by an offset + ; later. + ; + mov [edi+ElementClass.offset],ebx + mov [edi+ElementClass.shared],0 + mov [edi+ElementClass.status],UNRESOLVED + + ; + ; Setup type + ; + lea eax,[esi+Element.sizeof+ATTR_TYPE*Attribute.sizeof] + mov ebx,TYPE_MIXED + lea ecx,[mixedValue] + call compareAttributeValue + jz .found + mov ebx,TYPE_CONTAINER + lea ecx,[textValue] + call compareAttributeValue + jnz .found + mov ebx,TYPE_TEXT +.found: mov [edi+ElementClass.type],ebx + + ; + ; Copy and Set Name + ; + push esi + lea eax,[edi+ElementClass.sizeof] + mov [edi+ElementClass.name],eax + push edi + mov ecx,[esi+Element.sizeof+Attribute.limit] + mov esi,[esi+Element.sizeof+Attribute.begin] + sub ecx,esi + mov edi,eax + rep movsb + mov esi,edi + xor eax,eax + stosb + pop edi + mov [edi+ElementClass.nameLimit],esi + pop esi + + ; + ; Setup id + ; + mov eax,[esi+Element.sizeof+ATTR_ID*Attribute.sizeof+Attribute.begin] + mov ebx,[esi+Element.sizeof+ATTR_ID*Attribute.sizeof+Attribute.limit] + call toInteger + jnz .error + mov [edi+ElementClass.id],ebx + + xor eax,eax + mov ebx,edi +.error: pop edi + pop esi + ret +;[cf] +;[of]: copyElementClass +;[c]Copy an element class +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] source class +;[c] ebx +;[c] context +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] ebx +;[c] the new element class +;[c] +copyElementClass: + push esi + push edi + mov esi,eax + + ; + ; Allocate memory for element class + ; + mov eax,ElementClass.sizeof + mov edx,ebx + mov ecx,4 + call allocateMemory + jnz .error + + mov ebx,edi + mov ecx,ElementClass.sizeof / 4 + rep movsd + + xor eax,eax +.error: pop edi + pop esi + ret +;[cf] +;[cf] +;[cf] + +;[of]:Utility Functions +;[of]:compareAttributeValue +;[c]Compare the value of an attribute +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] the attribute +;[c] ecx +;[c] the value (zero terminated) +;[c] +;[c]RETURN VALUES +;[c] zf +;[c] 1 if equal +;[c] +compareAttributeValue: + push esi + push edi + + mov edi,ecx + mov esi,[eax+Attribute.begin] + mov ecx,[eax+Attribute.limit] + sub ecx,esi + jz .done +.next: cmpsb + jnz .diff + sub ecx,1 + jnz .next + +.done: cmp byte [edi],0 + +.diff: pop edi + pop esi + ret +;[cf] +;[of]:compareAttributes +;[c]Compare two attributes +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] the first attribute +;[c] ebx +;[c] the second attribute +;[c] +;[c]RETURN VALUES +;[c] zf +;[c] 1 if equal +;[c] +compareAttributes: + push esi + push edi + mov esi,[eax+Attribute.begin] + mov edi,[ebx+Attribute.begin] + + ; Compare length + mov ecx,[eax+Attribute.limit] + mov edx,[ebx+Attribute.limit] + sub ecx,esi + sub edx,edi + cmp ecx,edx + jnz .diff + + repz cmpsb +.diff: + pop edi + pop esi + ret +;[cf] +;[of]:toInteger +;[c]Converts a string to an integer +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] the string to parse +;[c] ebx +;[c] the end of string +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] ebx +;[c] integer value +;[c] +toInteger: push esi + push edi + mov esi,eax + mov edi,ebx + xor eax,eax + jmp .first + +.loop: movzx ecx,byte [esi] + cmp cl,'0' + jc .error + cmp cl,'9'+1 + jnc .error + inc esi + mov edx,10 + imul eax,edx + sub cl,'0' + add eax,ecx +.first: cmp esi,edi + jnz .loop + + mov ebx,eax + xor eax,eax + +.done: pop edi + pop esi + ret +;[c] +.error: mov eax,RC_INVALID_ID + or eax,eax + jmp .done +;[cf] +;[cf] +;[of]:Memory +;[of]:allocateMemory +;[c]Allocates a memory block +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] size +;[c] ecx +;[c] alignment +;[c] edx +;[c] context +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] edi +;[c] the object +;[c] +allocateMemory: mov edi,[edx+MemoryContext.base] + sub ecx,1 + add edi,ecx + not ecx + and edi,ecx + add eax,edi + cmp eax,[edx+MemoryContext.limit] + jnc .chunkFull + mov [edx+MemoryContext.base],eax + xor eax,eax + ret +;[c] +.chunkFull: push edx + push ebp + mov ebp,edx + sub eax,edi + call extendMemory ; let's assume that alignment is ok + pop ebp + pop edx + ret +;[cf] +;[of]:extendMemory +;[c]Extend memory +;[c] +;[c]When there is not enough memory available, a new chunk is created +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] size +;[c] ebp +;[c] the parse context +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] edi +;[c] the allocated memory buffer +;[c] +extendMemory: push eax + mov ecx,[ebp+MemoryContext.chunkSize] + add eax,ecx + call newChunk + pop ecx + jnz .error + + mov edi,[ebp+MemoryContext.base] + add ecx,edi + mov [ebp+MemoryContext.base],ecx + + xor eax,eax +.error: ret +;[cf] +;[of]:releaseChunks +;[c]Release the memory handled by the memory context +;[c] +;[c]ARGUMENTS +;[c] ebp +;[c] the context +;[c] +releaseChunks: push ebx + mov eax,[ebp+MemoryContext.chunks] + or eax,eax + jz .done +.loop: mov ebx,[eax] + call freeChunk + mov eax,ebx + or eax,eax + jnz .loop +.done: pop ebx + ret +;[cf] +;[of]:newChunk +;[c]Create a new chunk of memory +;[c] +;[c]ARGUMENTS +;[c] ebp +;[c] the parse context +;[c] eax +;[c] the size of chunk +;[c] +;[c]RETURN VALUES +;[c] eax+zf +;[c] error code +;[c] +newChunk: mov ecx,eax + add eax,HEADER_SIZE ; size for link + push ecx + push eax + call [mallocFunction] + add esp,4 + pop ecx + or eax,eax + jz .outOfMemory + mov edx,[ebp+MemoryContext.chunks] + mov [eax],edx + mov [ebp+MemoryContext.chunks],eax + add eax,HEADER_SIZE + add ecx,eax + mov [ebp+MemoryContext.base],eax + mov [ebp+MemoryContext.limit],ecx + + xor eax,eax + ret +;[c] +.outOfMemory: mov eax,RC_MEMORY + or eax,eax + ret +;[cf] +;[of]:freeChunk +;[c]Free a chunk +;[c] +;[c]ARGUMENTS +;[c] eax +;[c] the chunk +;[c] +freeChunk: push eax + call [freeFunction] + add esp,4 + ret +;[cf] +;[cf] + +;[of]:Data + align 4 + +;[of]:S +;[c]The blank map +;[c] +;[c] Flag for each character: +;[c] - 1 for blank characters (9, 10, 13, 32) +;[c] - 0 for other characters +;[c] +S: db 0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;[cf] +;[of]:RAC +;[c]Regular Attribute Chars +;[c] +;[c] Flag for each character: +;[c] - 1 for special chars (" ' & \0) +;[c] - 0 for other characters +;[c] +RAC: db 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;[cf] +;[of]:terminalChar +;[c]Any zero char is a terminator for an attribute name or an element name +;[c] +terminalChar: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0 ; -. + db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 ; : + db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1 ; _ + db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +;[cf] +;[of]:digit +;[c]Two flags for each chars: +;[c] - bit 0 for decimal chars +;[c] - bit 1 for hexadecimal chars +;[c] +digit: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0 + db 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;[cf] +;[of]:xdigit +;[c]Hexadecimal value of a char, assuming that the char is a valid +;[c]hexadecimal digit. +;[c] +xdigit: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0 + db 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;[cf] +;[of]:noElement / noAttribute +;[c]The default map for element without child elements (attribute only elements). +;[c] +noAttribute: +noElement: + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +;[cf] +;[of]:PubidChar +;[c]Valid characters for PubidLiteral +;[c] +PubidChar: db 0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1 + db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1 + db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + db 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;[cf] +;[of]:invalidClass +;[c]This special class is used to ignore unknown elements when +;[c]parsing in non strict mode. +;[c] +invalidClass: + dd Element.reserved ; store as ignored + dd invalidName + dd invalidName+1 + dd Element.sizeof + 0 * Attribute.sizeof + dd 0 ; null id + dd TYPE_CONTAINER + dd 0 ; no child + dd 0 ; no element + dd noAttribute + dd noElement +;[cf] + +;[of]:Schema Class +;[c]Schema Class +;[c] +SchemaClass: dd 0 + dd schemaName + dd schemaName+6 + dd Element.sizeof + dd schemaId + dd TYPE_CONTAINER + dd 0 + dd 0 + dd noAttribute + dd schemaMap + +;[of]:Attribute Class +;[c]Attribute Class +;[c] +attributeClass: dd 0 + dd attributeName + dd attributeName+9 + dd Element.sizeof + 2 * Attribute.sizeof + dd attributeId + dd TYPE_CONTAINER + dd 2 + dd 0 + dd nameIgnoreAttr + dd noElement + +;[cf] +;[of]:Text Class +;[c]Text Class +;[c] +textClass: dd 0 + dd textName + dd textName+4 + dd Element.sizeof + 2 * Attribute.sizeof + dd textId + dd TYPE_CONTAINER + dd 2 + dd 0 + dd nameIgnoreAttr + dd noElement + +;[cf] +;[of]:Document Class +documentClass: dd 0 + dd documentName + dd documentName+8 + dd Element.sizeof + 4 * Attribute.sizeof + dd documentId + dd TYPE_CONTAINER + dd 4 + dd 0 + dd nameAndTypeAttr + dd elementMap +;[cf] +;[of]:Collection Class +collectionClass: + dd 0 + dd collectionName + dd collectionName+10 + dd Element.sizeof + 4 * Attribute.sizeof + dd collectionId + dd TYPE_CONTAINER + dd 4 + dd 0 + dd nameAndTypeAttr + dd elementMap +;[cf] +;[of]:Group Class +groupClass: + dd 0 + dd groupName + dd groupName+5 + dd Element.sizeof + 4 * Attribute.sizeof + dd groupId + dd TYPE_CONTAINER + dd 4 + dd 0 + dd nameAndTypeAttr + dd elementMap +;[cf] +;[of]:Element Class +elementClass: + dd 0 + dd elementName + dd elementName+7 + dd Element.sizeof + 4 * Attribute.sizeof + dd elementId + dd TYPE_CONTAINER + dd 4 + dd 0 + dd nameAndTypeAttr + dd elementMap +;[cf] +;[of]:Reference Class +referenceClass: + dd 0 + dd referenceName + dd referenceName+9 + dd Element.sizeof + 2 * Attribute.sizeof + dd referenceId + dd TYPE_CONTAINER + dd 2 + dd 0 + dd nameIgnoreAttr + dd noElement +;[cf] +;[of]:Include Class +includeClass: + dd 0 + dd includeName + dd includeName+7 + dd Element.sizeof + 1 * Attribute.sizeof + dd includeId + dd TYPE_CONTAINER + dd 1 + dd 0 + dd nameAttr + dd noElement +;[cf] + +;[of]:Element maps + align 4 +schemaMap: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,.c+1,.d+1,.e+1,1,.g+1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + +.c: align 4 + db "ollection",0,0 + align 4 + dd collectionClass + +.d: align 4 + db "ocument",0,0 + align 4 + dd documentClass + +.e: align 4 + db "lement",0,0 + align 4 + dd elementClass + +.g: align 4 + db "roup",0,0 + align 4 + dd groupClass + + align 4 +elementMap: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,.a+1,1,.c+1,1,.e+1,1,1,1,.i+1,1,1,1,1,1,1 + dd 1,1,.r+1,1,.t+1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + + align 4 +.a: db "ttribute",0,0 + align 4 + dd attributeClass + + align 4 +.t: db "ext",0,0 + align 4 + dd textClass + +.c: align 4 + db "ollection",0,0 + align 4 + dd collectionClass + +.e: align 4 + db "lement",0,0 + align 4 + dd elementClass + +.i: align 4 + db "nclude",0,0 + align 4 + dd includeClass + +.r: align 4 + db "eference",0,0 + align 4 + dd referenceClass +;[cf] +;[of]:name= + align 4 +nameAttr: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,.name+1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + + align 4 +.name: db "ame",0 + dd Element.sizeof + 0 * Attribute.sizeof + +;[cf] +;[of]:name= ignore= + align 4 +nameIgnoreAttr: + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,.ignore+1,1,1,1,1,.name+1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + + align 4 +.name: db "ame",0 + dd Element.sizeof + 0 * Attribute.sizeof + + align 4 +.ignore: db "gnore",0 + dd Element.sizeof + 1 * Attribute.sizeof + +;[cf] +;[of]:name= ignore= id= type= + + align 4 +nameAndTypeAttr: + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,.i,1,1,1,1,.name+1,1 + dd 1,1,1,1,.type+1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + +.i: dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,.id+1,1,1,.ignore+1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + dd 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + + align 4 +.name: db "ame",0 + dd Element.sizeof + 0 * Attribute.sizeof + + align 4 +.ignore db "nore",0 + dd Element.sizeof + 1 * Attribute.sizeof + + align 4 +.type: db "ype",0 + dd Element.sizeof + 2 * Attribute.sizeof + + align 4 +.id: db 0 + dd Element.sizeof + 3 * Attribute.sizeof +;[cf] + +;[of]:Element Names +schemaName db "schema",0 +documentName db "document",0 +attributeName db "attribute",0 +textName db "text",0 +collectionName db "collection",0 +elementName db "element",0 +referenceName db "reference",0 +includeName db "include",0 +groupName db "group",0 +invalidName db "?",0 + +textValue db "text",0 +mixedValue db "mixed",0 + +yes db "yes",0 +no db "no",0 +;[cf] +;[cf] +;[of]:Atoms +atomTable dd DOCTYPEName + dd ELEMENTName + dd ATTLISTName + dd PCDATAName + dd IMPLIEDName + dd REQUIREDName + dd FIXEDName + dd NDATAName + + dd CDATAName + dd IDName + dd IDREFName + dd IDREFSName + dd ENTITYName + dd ENTITIESName + dd NMTOKENName + dd NMTOKENSName + dd NOTATIONName + + dd versionName + dd encodingName + dd standaloneName + dd 0 + +DOCTYPEName db "DOCTYPE",0 +ELEMENTName db "ELEMENT",0 +ATTLISTName db "ATTLIST",0 +PCDATAName db "PCDATA",0 +IMPLIEDName db "IMPLIED",0 +REQUIREDName db "REQUIRED",0 +FIXEDName db "FIXED",0 +NDATAName db "NDATA",0 + +CDATAName db "CDATA",0 +IDName db "ID",0 +IDREFName db "IDREF",0 +IDREFSName db "IDREFS",0 +ENTITYName db "ENTITY",0 +ENTITIESName db "ENTITIES",0 +NMTOKENName db "NMTOKEN",0 +NMTOKENSName db "NMTOKENS",0 +NOTATIONName db "NOTATION",0 + +versionName db "version",0 +encodingName db "encoding",0 +standaloneName db "standalone",0 +;[cf] +;[cf] +;[of]:BSS +section '.asmdata' writeable + +mallocFunction rd 1 +freeFunction rd 1 + +;[cf] diff --git a/core/XML_Parser/src/elf.asm b/core/XML_Parser/src/elf.asm new file mode 100644 index 00000000..c8a6d7d8 --- /dev/null +++ b/core/XML_Parser/src/elf.asm @@ -0,0 +1,19 @@ +;[c]asm-xml.asm - Asm XML Parser +;[c] +;[c]Compile this file with fasm. +;[c] +format ELF + +include "asm-xml.asm" + +;[c] +;[c]Public Functions +;[c] +public _initialize as "ax_initialize" +public _initializeParser as "ax_initializeParser" +public _releaseParser as "ax_releaseParser" +public _parse as "ax_parse" +public _initializeClassParser as "ax_initializeClassParser" +public _releaseClassParser as "ax_releaseClassParser" +public _classFromElement as "ax_classFromElement" +public _classFromString as "ax_classFromString" diff --git a/core/XML_Parser/src/win32.asm b/core/XML_Parser/src/win32.asm new file mode 100644 index 00000000..a31effec --- /dev/null +++ b/core/XML_Parser/src/win32.asm @@ -0,0 +1,19 @@ +;[c]asm-xml.asm - Asm XML Parser +;[c] +;[c]Compile this file with fasm. +;[c] +format MS COFF + +include "asm-xml.asm" + +;[c] +;[c]Public Functions +;[c] +public _initialize as "_ax_initialize" +public _initializeParser as "_ax_initializeParser" +public _releaseParser as "_ax_releaseParser" +public _parse as "_ax_parse" +public _initializeClassParser as "_ax_initializeClassParser" +public _releaseClassParser as "_ax_releaseClassParser" +public _classFromElement as "_ax_classFromElement" +public _classFromString as "_ax_classFromString" -- cgit v1.2.3