git » fp-git.git » commit 0941ec1

o Added new modules

author ecalot
2003-11-04 01:13:10 UTC
committer ecalot
2003-11-04 01:13:10 UTC
parent cd1271acf659215e288f86684a8a6f489e70267c

o Added new modules

PR/src/lib/layers/disk.c +185 -0
PR/src/lib/xml/search.c +145 -0
PR/src/xml.c +503 -0

diff --git a/PR/src/lib/layers/disk.c b/PR/src/lib/layers/disk.c
new file mode 100644
index 0000000..0975346
--- /dev/null
+++ b/PR/src/lib/layers/disk.c
@@ -0,0 +1,185 @@
+/*  Princed V3 - Prince of Persia Level Editor for PC Version
+    Copyright (C) 2003 Princed Development Team
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    The authors of this program may be contacted at http://forum.princed.com.ar
+*/
+
+/*
+disk.c: Princed Resources : Disk Access & File handling functions
+\xaf\xaf\xaf\xaf\xaf\xaf
+ Copyright 2003 Princed Development Team
+  Created: 29 Oct 2003
+
+  Author: Enrique Calot <ecalot.cod@princed.com.ar>
+  Version: 1.00 (2003-Oct-29)
+
+ Note:
+  DO NOT remove this copyright notice
+*/
+
+//Defines
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "pr.h"
+#include "disk.h"
+#ifdef UNIX
+	#include <sys/types.h>
+	#include <sys/stat.h>
+	#define defmkdir(a) mkdir (a,(mode_t)0755)
+#else
+	#include <direct.h>
+	#define defmkdir(a) mkdir (a)
+#endif
+
+#define isDirSep(a,i) ((a[i]=='\\')||(a[i]=='/'))
+
+/***************************************************************\
+|              Disk Access & File handling functions            |
+\***************************************************************/
+
+//Repair folders
+void repairFolders(char* a) {
+	int i,k;
+
+	for (i=0,k=0;a[i];) {
+		if (isDirSep(a,i)) {
+			a[k]=DIR_SEPARATOR;
+			i++;
+			while (isDirSep(a,i)) i++;
+		} else {
+			a[k]=a[i];
+			i++;
+		}
+		k++;
+	}
+	a[k]=0;
+}
+
+
+//Create base directory of a file
+int makebase(const char* p) {
+	/*
+		Creates the base directory of the given file "p"
+		Returns 0 if created
+		Returns -1 if an error occurred
+
+		Note: if the base dir already exists it will return -1!
+	*/
+
+	//Declare variables
+	int i,a;
+	int size;
+	char* aux;
+
+	//Initialize variables
+	aux=(char*)malloc(size=(strlen(p)+1));
+	memset(aux,0,size);
+
+	//Make directories
+	for (i=0;i<size;i++) {
+		if (p[i]==DIR_SEPARATOR) a=defmkdir(aux);
+		aux[i]=p[i];
+	}
+	free(aux);
+
+	return a;
+}
+
+char writeData(const unsigned char* data, int ignoreChars, char* vFileext, int size) {
+	/*
+		Creates vFileext and saves data in it. In case the directory doesn't
+		exist it will be created.
+
+		Data is read from ignoreChars to size.
+		Example:
+			if data="123456789", ignoreChars=3, size=8
+			saved file will contain "45678"
+
+		Returns
+		 0 if error
+		 1 if ok
+	*/
+
+	//Declare variables
+	FILE* target;
+	char  ok;
+
+	//Verify parameters
+	size-=ignoreChars;
+	if (size<=0) return 0;
+
+	//Create base dir and save file
+	repairFolders(vFileext);
+	makebase(vFileext);
+
+	ok=((target=fopen(vFileext,"wb"))!=NULL);
+	ok=ok&&fwrite(data+ignoreChars,size,1,target);
+	ok=ok&&(!fclose(target));
+	return ok;
+}
+
+int mLoadFileArray(const char* vFile,unsigned char** array) {
+	/*
+		Using the string in vFile, it opens the file and returns the
+		number of bytes	in it and the content of the file in array.
+		In case the file couldn't be open or memory allocated returns 0.
+	*/
+
+	//declare variables
+	FILE *fp;
+	int  aux;
+
+	//Open the file
+	if ((fp=fopen(vFile,"rb"))==NULL) {
+		return 0;
+	} else {
+		//get file size
+		fseek(fp,0,SEEK_END);
+		aux=ftell(fp);
+		if ( !aux || (aux>SIZE_OF_FILE) || ( ((*array=(char*)malloc(sizeof(char)*aux))==NULL) ) ) {
+			//if the file was null or bigger than the max size or couldn't allocate the file in memory
+			fclose(fp);
+			return 0;
+		} else {
+			//if the filewas succesfully open
+			fseek(fp,0,SEEK_SET);
+			aux=fread (*array,1,aux,fp);
+			fclose(fp);
+			return aux;
+		}
+	}
+}
+
+//TODO make a #define mSaveRaw(f,d,s) writeData(d,0,f,s)
+char mSaveRaw(const char* vFile,const unsigned char* output, int size) {
+	/*
+		Using the given string in vFile, it opens the file and saves the
+		first "size" bytes from the "output" in it.
+		In case the file couldn't be open or there was no size returns 0,
+		otherways returns 1.
+	*/
+
+  FILE * pFile;
+
+	if (!size) return 0;
+  if ((pFile=fopen(vFile,"wb"))==NULL) return 0;
+
+  fwrite (output, 1, size, pFile);
+  fclose (pFile);
+  return 1;
+}
diff --git a/PR/src/lib/xml/search.c b/PR/src/lib/xml/search.c
new file mode 100644
index 0000000..c3c4a0b
--- /dev/null
+++ b/PR/src/lib/xml/search.c
@@ -0,0 +1,145 @@
+/*  Princed V3 - Prince of Persia Level Editor for PC Version
+    Copyright (C) 2003 Princed Development Team
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    The authors of this program may be contacted at http://forum.princed.com.ar
+*/
+
+/*
+xmlsearch.c: Princed Resources : specific xml handling functions
+\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf
+ Copyright 2003 Princed Development Team
+  Created: 23 Oct 2003
+
+  Author: Enrique Calot <ecalot.cod@princed.com.ar>
+  Version: 1.01 (2003-Oct-25)
+
+ Note:
+  DO NOT remove this copyright notice
+*/
+
+/***************************************************************\
+|                  I M P L E M E N T A T I O N                  |
+\***************************************************************/
+#include <stdio.h> /* only on debugging purposes */
+
+//Includes
+#include "xml.h"
+#include "resources.h"
+#include "xmlsearch.h"
+#include <string.h>
+#include <stdlib.h>
+
+/****************************************************************\
+|                   Tag Tree Searching Functions                 |
+\****************************************************************/
+
+#define ptoi(p) ((p!=NULL)?atoi(p):0)
+
+tTag* searchTree(tTag* t,const char* datFile, const char* id) {
+	/* tTag*
+		tag pointer if found
+		NULL if not found
+	*/
+	tTag* children;
+	tTag* result;
+
+	if (t!=NULL) {
+		if (((t->file)!=NULL)&&((t->value)!=NULL)) {
+			if ((equalsIgnoreCase(t->file,datFile))&&(equalsIgnoreCase(t->value,id))) {
+				return t;
+			}
+		}
+		children=t->child;
+
+		while (children!=NULL) {
+			if (NULL!=(result=searchTree(children,datFile,id))) {
+				return result;
+			}
+			children=children->next;
+		}
+	}
+	return NULL;
+}
+
+void workTag(const tTag* t, tResource* r[]) {
+	//Declare variables
+	unsigned short id;
+	unsigned short size;
+
+	id=(unsigned short)ptoi(t->value);
+
+	//Process tag and copy values to resource
+	//Create Resource
+	if (r[id]!=NULL) return;
+	r[id]=(tResource*)malloc(sizeof(tResource));
+	if (r[id]==NULL) return;
+
+	//Get type and palette from tag
+	//TODO: send it to a define
+	if (t->itemtype==NULL) {
+		r[id]->type=0;
+	} else if (equalsIgnoreCase(t->itemtype,"image")) {
+		r[id]->type=2;
+	} else if (equalsIgnoreCase(t->itemtype,"palette")) {
+		r[id]->type=6;
+	} else if (equalsIgnoreCase(t->itemtype,"level")) {
+		r[id]->type=1;
+	} else if (equalsIgnoreCase(t->itemtype,"wave")) {
+		r[id]->type=3;
+	} else if (equalsIgnoreCase(t->itemtype,"midi")) {
+		r[id]->type=4;
+	} else if (equalsIgnoreCase(t->itemtype,"unknown")) {
+		r[id]->type=5;
+	} else if (equalsIgnoreCase(t->itemtype,"pcspeaker")) {
+		r[id]->type=7;
+	} else if (equalsIgnoreCase(t->itemtype,"raw")) {
+		r[id]->type=0;
+	}	else {
+		r[id]->type=(char)atoi(t->itemtype); //If error it returns 0 and the verifyHeader will try to detect the type
+	}
+	r[id]->palette=(unsigned short)ptoi(t->palette); //Transforms the char* palette into a short ID value, if 0 or error no palette is needed
+
+	//get external and copy it to the resource path
+	if (t->external!=NULL) {
+		size=strlen(t->external)+1;
+		r[id]->path=(char*)malloc(size);
+		if (r[id]->path!=NULL) memcpy(r[id]->path,t->external,size);
+	} else {
+		r[id]->path=NULL;
+	}
+}
+
+void workTree(const tTag* t,const char* datFile, tResource* r[]) {
+	/*
+		Runs workTag for each matching tag
+	*/
+	tTag* children;
+
+	if (t!=NULL) {
+		if (t->file!=NULL) {
+			if (equalsIgnoreCase(t->file,datFile)) {
+				workTag(t,r);
+			}
+		}
+		children=t->child;
+
+		while (children!=NULL) {
+			workTree(children,datFile,r);
+			children=children->next;
+		}
+	}
+}
diff --git a/PR/src/xml.c b/PR/src/xml.c
new file mode 100644
index 0000000..8bc291b
--- /dev/null
+++ b/PR/src/xml.c
@@ -0,0 +1,503 @@
+/*  Princed V3 - Prince of Persia Level Editor for PC Version
+    Copyright (C) 2003 Princed Development Team
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    The authors of this program may be contacted at http://forum.princed.com.ar
+*/
+
+/*
+xml.c: Princed Resources : xml handling functions
+\xaf\xaf\xaf\xaf\xaf
+ Copyright 2003 Princed Development Team
+  Created: 23 Oct 2003
+
+  Author: Enrique Calot <ecalot.cod@princed.com.ar>
+  Version: 1.01 (2003-Oct-25)
+
+ Note:
+  DO NOT remove this copyright notice
+*/
+
+/***************************************************************\
+|                  I M P L E M E N T A T I O N                  |
+\***************************************************************/
+
+//Includes
+#include "xml.h"
+#include "disk.h"
+#include "pr.h"
+#include <string.h>
+#include <stdio.h> /* Included only for XML specific attribute code */
+#include <stdlib.h>
+
+/****************************************************************\
+|                   Tag Tree Handling Functions                  |
+\****************************************************************/
+
+//private defines
+#define IsSpace(c) ((c==' ')||(c==9))||(c=='\n')||(c=='\r')
+#define IsChar(c) ((('a'<=c)&&(c<='z'))||(('A'<=c)&&(c<='Z'))||(c=='_')||(c=='-')||(c=='?'))
+
+#define Separate while (IsSpace(*i)) i++
+#define NextWord(i) while (IsChar(*(i))) (i)++
+
+#define FillAttr(a,b) if (equalsIgnoreCase(attr,b)) { if ((a)!=NULL) free(a); (a)=(val); return 1;}
+#define freeAllocation(m) if ((m)!=NULL) free(m)
+
+#define ParseError return -1
+
+tTag* getTagStructure() {
+	//initializes
+	tTag* t;
+	t=(tTag*)malloc(sizeof(tTag));
+	if (t==NULL) return NULL;
+
+	t->child=NULL;
+	t->next=NULL;
+	t->tag=NULL;
+	t->desc=NULL;
+	t->external=NULL;
+	t->file=NULL;
+	t->itemtype=NULL;
+	t->name=NULL;
+	t->palette=NULL;
+	t->type=NULL;
+	t->value=NULL;
+	t->version=NULL;
+
+	return t;
+}
+
+void freeTagStructure(tTag* t) {
+	if (t==NULL) return;
+	freeTagStructure(t->child);
+	freeTagStructure(t->next);
+	freeAllocation(t->tag);
+	freeAllocation(t->desc);
+	freeAllocation(t->external);
+	freeAllocation(t->file);
+	freeAllocation(t->itemtype);
+	freeAllocation(t->name);
+	freeAllocation(t->palette);
+	freeAllocation(t->type);
+	freeAllocation(t->value);
+	freeAllocation(t->version);
+	free(t);
+}
+
+int attribFill(char* attr,char* val, tTag* t) {
+	/*
+		0: attribute mismatch
+		1: ok
+	*/
+
+	if (equalsIgnoreCase(attr,"?")) {
+		free(val);
+		return 1;
+	}
+
+	FillAttr(t->desc,"desc");
+	FillAttr(t->external,"external");
+	FillAttr(t->file,"file");
+	FillAttr(t->itemtype,"itemtype");
+	FillAttr(t->name,"name");
+	FillAttr(t->palette,"palette");
+	FillAttr(t->type,"type");
+	FillAttr(t->value,"value");
+	FillAttr(t->version,"version");
+
+	return 0;
+}
+
+/****************************************************************\
+|                     Other Modules Functions                    |
+\****************************************************************/
+
+//Taken from parser.c
+
+int equalsIgnoreCase(const char s1[],const char s2[]) {
+	int i=0;
+	for (;((s1[i]&0xDF)==(s2[i]&0xDF))&&s1[i];i++);
+	return !(s1[i]||s2[i]);
+}
+
+/****************************************************************\
+|                       XML Parsing Functions                    |
+\****************************************************************/
+
+//Parse text functions
+int parseNext(char** pString, tTag* tag) {
+	/*
+	  -3 Attribute not recognized
+	  -2 No memory
+		-1 Parse error
+		0  if continue
+		1  if tag end
+		2  if end
+	*/
+
+	char* start;
+	char* attribute;
+	char* value;
+	char aux[MAX_VALUE_SIZE];
+	int size;
+	char* i=*pString;
+
+	Separate;
+
+	if (*i=='>') {
+		*pString=i+1;
+		return 2;
+	}
+	if (*i=='/') {
+		i++;
+		Separate;
+		if (*i=='>') {
+			*pString=i+1;
+			return 1;
+		} else {
+			ParseError;
+		}
+	}
+
+	start=i;
+	NextWord(i);
+	if (start==i) ParseError;
+	if (*i==0)    ParseError;
+
+	if (!(IsSpace(*i)||(*i=='=')||(*i=='>'))) ParseError;
+
+	size=(long int)i-(long int)start; //Note: casted to long for portability with 64 bits architectures
+	attribute=(char*)malloc((1+size));
+	if (attribute==NULL) return -2;
+	memcpy(attribute,start,size);
+	attribute[size]=0;
+
+	if (*i=='=') {
+		int k=0;
+		//It's a text attribute
+		i++;
+		if (*i!='"') ParseError;
+		i++;
+		//Parse until the next "
+		for(start=i; (k<MAX_VALUE_SIZE)&&(*i!='"')&&(*i!=0) ;i++) {
+			aux[k]=*i;
+			if (aux[k]=='\\') {
+				i++;
+				switch (*i) {
+					case 'n':
+						aux[k]='\n';
+						break;
+					case 'r':
+						aux[k]='\r';
+						break;
+					case 't':
+						aux[k]='\t';
+						break;
+					default:
+						aux[k]=*i;
+						break;
+				}
+			}
+			k++;
+		}
+		if ((*i)!='"') {
+			free(attribute);
+			ParseError;
+		}
+		i++;
+		value=(char*)malloc((k+1));
+		if (value==NULL) {
+			free(attribute);
+			return -2;
+		}
+		memcpy(value,aux,k);
+		value[k]=0;
+	} else {
+		//It's a boolean attribute, I'll define it
+		value=(char*)malloc((1));
+		if (value==NULL) {
+			free(attribute);
+			return -2;
+		}
+		value[0]=0;
+	}
+
+	if (!(attribFill(attribute,value,tag))) {
+		free(attribute);
+		return -3;
+	}
+	free(attribute);
+	*pString=i;
+	return 0;
+}
+
+
+int getNextTag(char** pString, char** value) {
+	/*
+	  -2 No memory
+		-1 Parse error
+		0  if next item is a tag
+		1  if it was a text
+		2  if next item closes a tag
+		3  End of document
+		4  if there was no text
+	*/
+	char* i=*pString;
+	int   result;
+	char* start;
+	char  size;
+
+	Separate;
+
+	if (*i=='<') {
+		//it is a tag
+		i++;
+		Separate;
+		if (*i=='/') {
+			result=2;
+			i++;
+		} else {
+			if ((*i=='!')||(*i=='?')) {
+				while ((*i)&&((*i)!='>')) i++;
+				if (!(*i)) ParseError;
+				i++;
+				if (!(*i)) return 3;
+				result=getNextTag(&i,value);
+				*pString=i;
+				return result;
+			} else {
+				result=0;
+			}
+		}
+		start=i;
+		NextWord(i);
+		if (start==i) ParseError;
+		if (*i==0)    ParseError;
+		i++;
+
+		size=(char)((long int)i-(long int)start); //Note: casted to long for portability with 64 bits architectures
+		*value=(char*)malloc((size));
+		if (*value==NULL) return -2;
+		memcpy(*value,start,size-1);
+		(*value)[size-1]=0;
+		*pString=i-(!result);
+		return result;
+	}
+	start=i;
+	while ((*i)&&((*i)!='<')) i++;
+	if (!(*i)) return 3;
+	if (start==i) return 4;
+	size=(char)((long int)i-(long int)start); //Note: casted to long for portability with 64 bits architectures
+	*value=(char*)malloc((1+size));
+	if (*value==NULL) return -2;
+	memcpy(*value,start,size);
+	//memset(*value,0,size);
+	(*value)[size]=0;
+	*pString=i;
+	return 1;
+}
+
+//Parse Tree functions
+tTag* makeTree(char** p,char* name, int* error,tTag* father) {
+	/* *error
+		-3 Attribute not recognized
+	  -2 No memory
+		-1 Parse error
+		0  if next item is a tag
+	*/
+
+	tTag* tag;
+	tTag* children=NULL;
+	char* value;
+	int result;
+
+	tag=getTagStructure();
+	tag->tag=name;
+
+	while (!((*error)=parseNext(p, tag)));
+
+	if ((*error)<0) return NULL; //Fatal error
+	/*	(*error)
+			1  if tag end
+			2  if end
+	*/
+	if ((*error)==1) {
+		*error=0; //No errors, end of the tag in the same tag <tag />
+		return tag;
+	}
+
+	//In case there are some empty attributes, they may be inherited
+	//BEGIN specific xml tag inheritance
+	{
+		int x;
+		char* str;
+		//TODO: use macros
+		//TotalInheritance(tag->palette,father->palette);
+		if ((tag->palette==NULL)&&(father->palette!=NULL)) {
+			x=strlen(father->palette)+1;
+			tag->palette=(char*)malloc(x);
+			memcpy(tag->palette,father->palette,x);
+		}
+		//TotalInheritance(file);
+		if ((tag->file==NULL)&&(father->file!=NULL)) {
+			x=strlen(father->file)+1;
+			tag->file=(char*)malloc(x);
+			memcpy(tag->file,father->file,x);
+		}
+		//TotalInheritance(itemtype);
+		if ((tag->itemtype==NULL)&&(father->itemtype!=NULL)) {
+			x=strlen(father->itemtype)+1;
+			tag->itemtype=(char*)malloc(x);
+			memcpy(tag->itemtype,father->itemtype,x);
+		}
+		//PartialConcatInheritance(tag->external,father->external,tag->value);
+		if ((tag->value==NULL)||(tag->external!=NULL)) {
+			//Make sure externals do exist
+			if (father->external==NULL) {father->external=(char*)malloc(1);*(father->external)=0;}
+			if (tag->external==NULL) {tag->external=(char*)malloc(1);*(tag->external)=0;}
+
+			//Create new variable
+			x=strlen(father->external)+strlen(tag->external)+2;
+			str=(char*)malloc(x);
+			if (str==NULL) {*error=2;return NULL;}
+
+			//Set variable and destroy old variables
+			sprintf(str,"%s%c%s",father->external,DIR_SEPARATOR,tag->external);
+			free(tag->external);
+			if ((*(father->external))==0) free(father->external);
+			tag->external=str;
+			memcpy(tag->external,str,x);
+		}
+	}
+	//END specific xml tag inheritance
+	//Parse Child tags
+	while (1) {
+		(*error)=getNextTag(p, &value);
+		if ((*error)<0) return NULL; //Fatal error
+		/*	(*error)
+				0  if next item is a tag
+				1  if it was a text
+				2  if next item closes a tag
+				3  End of document
+				4  if there was no text
+		*/
+		result=(*error);
+		switch (result) {
+			case 0:
+				if (children==NULL) {
+					tag->child=makeTree(p,value,error,tag);
+					children=tag->child;
+				} else {
+					children->next=makeTree(p,value,error,tag);
+					children=children->next;
+				}
+				if (*error) return NULL;
+				//Add error handling
+				break;
+			case 1:
+				if (tag->name!=NULL) free(tag->name);
+				tag->name=value;
+				break;
+			case 2:
+				//"no errors" or "a wrong tag is closed"
+				*error=-(!(equalsIgnoreCase(value,tag->tag)));
+				free(value);
+				return tag;
+			case 3:
+				*error=-1; //this tag wasn't closed
+				return tag;
+				break;
+		}
+	}
+	return NULL;
+}
+
+#if 0
+
+void showTag(int n,tTag* t) {
+	int a;
+	tTag* children;
+
+	for(a=0;a<n;a++) printf ("  ");
+	if (t!=NULL) {
+		printf("%s (%s)\n",t->tag,t->desc);
+		children=t->child;
+
+		while (children!=NULL) {
+			showTag(n+1,children);
+			children=children->next;
+		}
+	} else {
+		printf("None\n");
+	}
+}
+
+#endif
+
+tTag* parseXmlFile(char* vFile,int* error) {
+	/* error may take the following values:
+		-1 Parse error
+		-2 No memory
+		-3 Attribute not recognized
+		-4 File not found
+		0  no errors
+	*/
+	char* p;
+	char* l;
+	char* value=NULL;
+	tTag* tag;
+	tTag* father;
+
+	if (!mLoadFileArray(vFile,(unsigned char**)(&l))) {
+		*error=-4; //File not open
+		return NULL;
+	}
+	p=l;
+
+	*error=getNextTag(&p, &value);
+	if ((*error)<0) {
+		free(l);
+		return NULL; //Fatal error will stop the execusion of the parsing
+	}
+
+	father=getTagStructure();
+	tag=makeTree(&p,value,error,father);
+
+	if (*error) {
+		freeTagStructure(tag);
+		free(l);
+		free(father);
+		return NULL;
+	}
+	*error=getNextTag(&p, &value);
+	free(l);
+	if (*error<0) {
+		freeTagStructure(tag);
+		free(father);
+		return NULL; //Fatal error will stop the execusion of the parsing
+	}
+	if (*error==3) {
+		*error=0;
+		free(father);
+		return tag;
+	} else {
+		freeTagStructure(tag);
+		free(father);
+		*error=-1;
+		return NULL;
+	}
+}