git » fp-git.git » commit eaef517

o Solved several bugs

author ecalot
2003-12-08 13:26:20 UTC
committer ecalot
2003-12-08 13:26:20 UTC
parent 74a019c053f59d7a7b463bebaca48add59363c37

o Solved several bugs
o Changed interfaces to adapt them to the new command line syntax
o Added .so unix library support

PR/src/console/main.c +265 -107
PR/src/lib/actions/classify.c +1 -1
PR/src/lib/actions/export.c +19 -12
PR/src/lib/actions/import.c +71 -54
PR/src/lib/layers/disk.c +29 -11
PR/src/lib/pr.c +265 -107
PR/src/lib/xml/search.c +21 -0
PR/src/xml.c +5 -1

diff --git a/PR/src/console/main.c b/PR/src/console/main.c
index b5eb371..0bce2ad 100644
--- a/PR/src/console/main.c
+++ b/PR/src/console/main.c
@@ -39,11 +39,15 @@ pr.c: Main source file for Princed Resources
 	 MID Sound format development
 	  Christian Lundheim
 
+	 Resources.xml edition
+	  Steven Fayers
+
  Note:
   DO NOT remove this copyright notice
 */
 
 //Headers
+#include <stdio.h>
 #include <string.h>
 
 #include "pr.h"
@@ -54,30 +58,59 @@ pr.c: Main source file for Princed Resources
 #include "compile.h"
 #include "tasks.h"
 
-#include "bmp.h"
-#include "memory.h"
-#include "disk.h"
+#include "memory.h" /* getMemory, free */
+#include "disk.h"      /* getFileNameFromPath */
+
+#ifndef DLL
+ #ifdef UNIX
+  #include <stduni.h>
+ #else
+  #include "getopt.h"
+ #endif
+#endif
+
 
 //functions
 
-int prExportDat(char* vDatFile, char* vDirName, char* vResFile) {
-	return prExportDatOpt(vDatFile,vDirName,vResFile,3);
+int prExportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
+	return prExportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL,"");
 }
 
-int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
+int prExportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName,const char* datAuthor, const char* backupExtension) {
 	/*
+		Arguments:
+			char* vDatFile        - full Path to the dat file;
+			                        if file use it, if dir, perform it for
+			                        all files
+			char* vDirName        - full Path to the extracting folder
+			                        (doesn't need to exist)
+			char* vResFile        - full Path to the resources XML file
+			                        (resources.xml by default)
+			                        No NULL
+			char opt              - program options, see below
+			char * vDatFileName   - name of the file to be extracted
+			                        NULL means predict it from vDatFile
+			const char* datAuthor - Author's name when extracting PLV's,
+			                        NULL is default
+			const char* backupExtension
+			                      - If backup_flag is set, the string to attach
+			                        to the backup files
+
 		Options:
-			0 - none
-			1 - extract
-			2 - update resources (rebuild resources list)
-			3 - 1&2
-			4 - use raw file if extraction
-			5 - 1&4
-			8 - Don't save
+			unknown_flag   - generate the unknown file without performing
+                       any extraction
+			raw_flag       - uses raw format
+			verbose_flag   - explain what is being done
+x			recursive_flag - searches for all dat files (only if vDatFile
+			                 is not a dat file and vDatFileName is NULL)
+x			force_flag     - default option, you cannot disable it,
+			                 so please make a backup of your files
+x			backup_flag    - backup your files
+
 
 		Return values:
 			00 Ok
-			-1 Error accesing the file DAT
+			-1 Error accessing the file DAT
 			-2 Memory error in extraction
 			-3 Invalid DAT file
 			-4 XML Parse error
@@ -85,24 +118,55 @@ int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
 			-6 XML Attribute not recognized
 			-7 XML File not found
 	*/
+
+	//Declare variables
 	tResource* r[MAX_RES_COUNT];
 	int a;
+	const char defaultXmlFile[]=RES_XML_RESOURC_XML;
 
-	a=parseFile     (vResFile,vDatFile,r);
-	if (a<0) return a-3;
-	a=extract(vDatFile, vDirName,r,opt);
-	return a;
+	//Set default values
+	if (vResFile==NULL) vResFile=defaultXmlFile;
+	if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile);
+
+	//Parse XML and extract the file
+	a=parseFile     (vResFile,vDatFileName,r);
+	if (a<0) return a-3; //parsing errors
+	a=extract(vDatFile, vDirName,r,opt,vDatFileName);
+	printf("-3 es error: %d\n",a);
+	return a; //extracting errors/no errors
 }
 
-int prImportDat(char* vDatFile, char* vDirName, char* vResFile) {
-	return prImportDatOpt(vDatFile,vDirName,vResFile,1);
+int prImportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
+	return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,"");
 }
 
-int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
+int prImportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName, const char* backupExtension) {
 	/*
+		Arguments:
+			char* vDatFile        - full Path to the dat file;
+			                        if file use it, if dir, perform it for
+			                        all files
+			char* vDirName        - full Path to the extracting folder
+			                        (doesn't need to exist)
+			char* vResFile        - full Path to the resources XML file
+			                        (resources.xml by default)
+			                        No NULL
+			char opt              - program options, see below
+			char * vDatFileName   - name of the file to be extracted
+			                        NULL means predict it from vDatFile
+			const char* backupExtension
+			                      - If backup_flag is set, the string to attach
+			                        to the backup files
+
 		Options:
-			0 - use raw files
-			1 - read data type
+			raw_flag       - uses raw format
+			verbose_flag   - explain what is being done
+x			recursive_flag - searches for all dat files (only if vDatFile
+			                 is not a dat file and vDatFileName is NULL)
+x			force_flag     - default option, you cannot disable it,
+			                 so please make a backup of your files
+x			backup_flag    - backup your files
+
 
 		Return values:
 			-1 DAT File couldn't be open for writing
@@ -113,118 +177,212 @@ int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
 			00 File succesfully compiled
 			positive number: number of missing files
 	*/
-	tResource*    r[MAX_RES_COUNT];
+
+	//Declare variables
+	tResource* r[MAX_RES_COUNT];
 	int a;
-	a=parseFile     (vResFile,vDatFile,r);
+	const char defaultXmlFile[]=RES_XML_RESOURC_XML;
+
+	//Set default values
+	if (vResFile==NULL) vResFile=defaultXmlFile;
+	if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile);
+
+	//Parser XML and compile files
+	a=parseFile     (vResFile,vDatFileName,r);
 	if (a<0) return a-1;
-	a=compile (vDatFile, vDirName,r,opt);
+	a=compile (vDatFile, vDirName,r,opt,vDatFileName);
 	return a;
 }
 
+
+/*******************************************************
+                    M A I N   P R O G R A M
+       *******************************************************/
+
+
+
 //Main program
 #ifndef DLL
 void syntax() {
-	printf(PR_TEXT_SYNTAX);
+	printf(PARSING_HELP);
 }
 
-int main(int argc, char* argv[]) {
+int prMain(int option, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor) {
 
 	//declare variables
-	char dir[260]=".";
 	int returnValue=1;
-	int option;
-	int i;
 
-#ifdef UNIX
-	if (argc==2) { //CGI support
+	//Do CGI tasks
+	if (option&cgi_flag) {
+		option&=(~classify_flag);
 		printf(PR_CGI_TEXT1);
-		printf(PR_CGI_TEXT2,prVerifyDatType(argv[1]));
-		return 1;
+		if (option==cgi_flag) {
+			printf(PR_CGI_TEXT2,prVerifyDatType(datfile));
+			return 1;
+		} else {
+			option=help_flag;
+		}
 	}
-#endif
 
 	printf(PR_ABOUT);
 
-	//Verify syntax
-	if ((argc<3)||(argc>4)||(argv[2][0])!='-') {
+	//If bad syntax or help screen requested
+	if (option&help_flag) {
 		syntax();
 		return -1;
 	}
-	if (argc==4 ) {
-		if (strlen(argv[3])<(260-1)) sprintf(dir,argv[3]);
+
+	if ((datfile==NULL)||option&version_flag) { //TODO use the recursive option and/or generic datfile
+		return -1;
 	}
 
 	//do selected tasks
-	switch (argv[2][1]) {
-		case 'e':
-		case 'x': {// file.dat --> extracted files + resource.xml
-			char array[8][29]={
-				"Ok",
-				"Error accesing the file DAT", /* DAT or extracted */
-				"Memory error in extraction",
-				"Invalid DAT file",
-				"XML Parse error",
-				"Memory error in parsing",
-				"XML Attribute not recognized",
-				"XML File not found"};
-			option=1;
-			for (i=2;argv[2][i];i++) {
-				switch (argv[2][i]) {
-					case 'n':option&=0xFE;break;
-					case 'r':option|=0x04;break;
-					default:printf(PR_TEXT_SKIPING,argv[2][i]);break;
-				}
-			}
-			printf("Extracting '%s' to '%s' with %d\r\n",argv[1],dir,option);
-			returnValue=prExportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option);
+	if (option&export_flag) {
+		char* array[]={
+			"Ok",
+			"Error accessing the file DAT", /* DAT or extracted */
+			"Memory error in extraction",
+			"Invalid DAT file",
+			"XML Parse error",
+			"Memory error in parsing",
+			"XML Attribute not recognized",
+			"XML File not found"};
+		printf("Extracting '%s' to '%s' with %04x\r\n",datfile,dirName,option);
+		returnValue=prExportDatOpt(datfile,dirName,resFile,option,NULL,datAuthor,extension);
+		printf(PR_TEXT_RESULT,array[-returnValue],returnValue);
+	}	else if (option&classify_flag) {
+		char* array[]={
+			"Memory error",
+			"File not found or no access error",
+			"Not a valid POP1 DAT file",
+			"Levels file",
+			"Graphic file with an image in the first valid entry (not common)",
+			"Waves/Digital sound file",
+			"Midis file",
+			"Valid DAT file with Undefined content",
+			"Graphic file with a palette in the first valid entry (common)",
+			"PC Speaker dat file",
+			"\0","\0","\0",
+			"Pop2 dat files"};
+		printf("Classifing '%s'\r\n",datfile);
+		returnValue=prVerifyDatType(datfile);
+		printf(PR_TEXT_RESULT,array[2+returnValue],returnValue);
+	}	else if (option&import_flag) {
+		char* array[]={
+			"File succesfully compiled",
+			"DAT File couldn't be open for writing",
+			"XML Parse error",
+			"No memory",
+			"XML Attribute not recognized",
+			"XML File not found"};
+		printf("Compiling '%s' from '%s' with %04x\r\n",datfile,dirName,option);
+		returnValue=prImportDatOpt(datfile,dirName,resFile,option,NULL,extension);
+		if (returnValue<=0) {
 			printf(PR_TEXT_RESULT,array[-returnValue],returnValue);
-		}	break;
-		case 'd': {// get type of file.dat
-			char array[14][65]={
-				"Memory error",
-				"File not found or no access error",
-				"Not a valid POP1 DAT file",
-				"Levels file",
-				"Graphic file with an image in the first valid entry (not common)",
-				"Waves/Digital sound file",
-				"Midis file",
-				"Valid DAT file with Undefined content",
-				"Graphic file with a palette in the first valid entry (common)",
-				"PC Speaker dat file",
-				"\0","\0","\0",
-				"Pop2 dat files"};
-			printf("Classifing '%s'\r\n",argv[1]);
-			returnValue=prVerifyDatType(argv[1]);
-			printf(PR_TEXT_RESULT,array[2+returnValue],returnValue);
-		}	break;
-		case 'c': { // extracted files + resource.xml --> files.dat
-			char array[6][39]={
-				"File succesfully compiled",
-				"DAT File couldn't be open for writing",
-				"XML Parse error",
-				"No memory",
-				"XML Attribute not recognized",
-				"XML File not found"};
-			option=1;
-				for (i=2;argv[2][i];i++) {
-					switch (argv[2][i]) {
-						case 'r':option&=0xFE;break;
-						default:printf(PR_TEXT_SKIPING,argv[2][i]);break;
-					}
-				}
-			printf("Compiling '%s' from '%s' with %d\r\n",argv[1],dir,option);
-			returnValue=prImportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option);
-			if (returnValue>=0) {
-				printf(PR_TEXT_RESULT,array[-returnValue],returnValue);
-			} else {
-				printf(PR_TEXT_RESULT_ERR,returnValue);
-			}
-		} break;
-		default:
-			syntax();
-			return -1;
+		} else {
+			printf(PR_TEXT_RESULT_ERR,returnValue);
+		}
+	} else {
+		syntax();
+		return -1;
 	}
 	return returnValue;
 }
 
+int main (int argc, char **argv) {
+	//declare variables
+	char  datFileName[MAX_FILENAME_SIZE]; //TODO add
+	char  dirName[MAX_FILENAME_SIZE]=".";
+	char  extension[MAX_EXTENSION_SIZE]=DEFAULT_BACKUP_EXTENSION;
+	char  resFile[MAX_FILENAME_SIZE]=RES_XML_RESOURC_XML;
+	char* datFilePath;
+	char* datAuthor=NULL;
+	int   c;
+	int   flag=0;
+
+	//Parse options
+	while (1) {
+
+		static struct option long_options[] = PARSING_OPTIONS;
+
+		/* getopt_long stores the option index here. */
+		int option_index = 0;
+		c = getopt_long (argc, argv, PARSING_CHARS,long_options,&option_index);
+
+		/* Detect the end of the options. */
+		if (c == -1) break;
+
+		switch (c) {
+				case 'c':
+					flag|=import_flag;
+					if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'd':
+					flag|=force_flag;
+					break;
+				case 'x':
+				case 'e':
+					flag|=export_flag;
+					if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'b':
+					flag|=backup_flag;
+					if (optarg) strncpy(extension,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'f':
+					flag|=force_flag;
+					break;
+				case 'g':
+					flag|=cgi_flag;
+					break;
+				case 'm':
+					strncpy(resFile,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'r':
+					flag|=raw_flag;
+					break;
+				case 'R':
+					flag|=force_flag;
+					break;
+				case 't': {
+					int size;
+					size=strlen(optarg)+1;
+					datAuthor=getMemory(size);
+					memcpy(datAuthor,optarg,size);
+				}	break;
+				case 'v':
+					flag|=verbose_flag;
+					break;
+				case 1:
+					flag|=version_flag;
+					break;
+				case 2:
+					flag|=unknown_flag;
+					break;
+				default:
+					flag|=help_flag;
+		}
+	}
+
+	if (optind < argc) {
+		datFilePath=argv[optind];
+	} else {
+		datFilePath=NULL;
+	}
+
+	if (!flag) flag=help_flag;
+
+	//Run main program
+	prMain(flag,extension,dirName,resFile,datFilePath,datFileName,datAuthor);
+
+	//Free memory and exit
+	if (datAuthor!=NULL) free(datAuthor);
+  return 0;
+}
+
+#endif
+
+#ifdef SO
+//When compiling in Unix SO libraries
+void start() {}
 #endif
diff --git a/PR/src/lib/actions/classify.c b/PR/src/lib/actions/classify.c
index b4acd7b..2782d0f 100644
--- a/PR/src/lib/actions/classify.c
+++ b/PR/src/lib/actions/classify.c
@@ -40,7 +40,7 @@ tasks.c: Princed Resources : Other DAT file handling tasks
 |                    Get the type of a DAT file                 |
 \***************************************************************/
 
-int prVerifyDatType(char* vFiledat) {
+int prVerifyDatType(const char* vFiledat) {
 
 	//Variables
 	FILE*              fp;
diff --git a/PR/src/lib/actions/export.c b/PR/src/lib/actions/export.c
index aee1e56..de67bed 100644
--- a/PR/src/lib/actions/export.c
+++ b/PR/src/lib/actions/export.c
@@ -43,6 +43,7 @@ extract.c: Princed Resources : DAT Extractor
 #include "bmp.h"
 #include "wav.h"
 #include "pal.h"
+#include "plv.h"
 #include "mid.h"
 
 /***************************************************************\
@@ -66,7 +67,7 @@ extract.c: Princed Resources : DAT Extractor
 		5 - 1&4
 */
 
-int extract(char* vFiledat,char* vDirExt, tResource* r[], char task) {
+int extract(const char* vFiledat,const char* vDirExt, tResource* r[], int task, const char* vDatFileName) {
 
 	//Variables
 	char          vFileext[260];
@@ -136,33 +137,36 @@ int extract(char* vFiledat,char* vDirExt, tResource* r[], char task) {
 			ok=ok&&fread(data,size,1,fp);
 			if (!ok) return -3;
 
-			//For the moment rebuilt option will be comented
-//	task|=2;
-
 			//set resource information on this index entry
 			if (r[id]==NULL) {
 				r[id]=(tResource*)malloc(sizeof(tResource));
 				if (r[id]==NULL) return -2; //no memory
 				r[id]->path=NULL;
 				r[id]->palAux=NULL;
+				r[id]->desc=NULL;
+				r[id]->title=NULL;
 				r[id]->palette=0;
-				(*(r[id])).size=(unsigned short int)size;
-				(*(r[id])).offset=(unsigned short)offset;
-				(*(r[id])).type=verifyHeader(data,(unsigned short int)size);
-			} else {
+				r[id]->number=0;
+				r[id]->size=(unsigned short int)size;
+				r[id]->offset=(unsigned short)offset;
+				r[id]->type=verifyHeader(data,(unsigned short int)size);
+			} else { //If resource type is invalid or 0, the type will be decided by PR
 				if (!(r[id]->type)) r[id]->type=verifyHeader(data,(unsigned short int)size);
 			}
 
-			if (task&1) { //If "extract to file" is set
+			if (!(task&unknown_flag)) { //If unknown flag is set do nothing but generate the unknown.xml file
 				//select type
-				if (task&4) (*(r[id])).type=0; //If "extract as raw" is set type is 0
+				if (task&raw_flag) (*(r[id])).type=0; //If "extract as raw" is set type is 0
 
 
 				//save file
 				getFileName(vFileext,vDirExt,r[id],id,vFiledat);
+				if (task&verbose_flag) printf("Extracting '%s'...\n",getFileNameFromPath(vFileext));
 
-				switch ((*(r[id])).type) {
+				switch (r[id]->type) {
 					case 1:
+						ok=ok&&mFormatExtractPlv(data,vFileext,size,r[id]->number,vDatFileName,r[id]->title,r[id]->desc);
+						break;
 					case 5:
 					case 0: //Raw files
 						ok=ok&&writeData(data,1,vFileext,size); //Ignore checksum
@@ -209,12 +213,15 @@ int extract(char* vFiledat,char* vDirExt, tResource* r[], char task) {
 		}
 		fclose(fp);
 
-		//Free allocated palettes
+		//Free allocated palettes and descriptions
 		for (id=0;id<MAX_RES_COUNT;id++) {
 			if (r[id]!=NULL) {
 				if (r[id]->palAux!=NULL) {
 					free (r[id]->palAux);
 				}
+				if (r[id]->desc!=NULL) {
+					free (r[id]->palAux);
+				}
 			}
 		}
 
diff --git a/PR/src/lib/actions/import.c b/PR/src/lib/actions/import.c
index ce1e860..fd4fff6 100644
--- a/PR/src/lib/actions/import.c
+++ b/PR/src/lib/actions/import.c
@@ -42,6 +42,7 @@ compile.c: Princed Resources : DAT Compiler
 #include "mid.h"
 #include "wav.h"
 #include "pal.h"
+#include "plv.h"
 #include "disk.h"
 #include "pr.h"
 
@@ -49,10 +50,13 @@ compile.c: Princed Resources : DAT Compiler
 |                  Dat compiling primitives                     |
 \***************************************************************/
 
-char mBeginDatFile(FILE* *fp,char* vFile) {
-	//opens a file and reserves space for the headers
-	*fp=fopen(vFile,"wb");
-	if (*fp!=NULL) {
+char mBeginDatFile(FILE* *fp,const char* vFile) {
+	/*
+		Opens safely a dat file for writing mode and
+		reserves space for the headers
+	*/
+
+	if (writeOpen(vFile,fp)) {
 		fseek(*fp,6,SEEK_SET);
 		return 1;
 	} else {
@@ -61,61 +65,69 @@ char mBeginDatFile(FILE* *fp,char* vFile) {
 }
 
 void mAddFileToDatFile(FILE* fp, char* data, int size) {
-	//calculates the checksum of a file
-	unsigned char checksum=0;
-	int k;
-	for (k=0;k<size;k++) checksum+=data[k];
+	/*
+		Adds a data resource to a dat file keeping
+		abstratly the checksum verifications
+	*/
+
+	//Declare variables
+	int            k        = size;
+	unsigned char  checksum = 0;
+	unsigned char* data2    = data;
+
+	//calculates the checksum
+	while (k--) checksum+=*(data2++);
 	checksum=~checksum;
+
 	//writes the checksum and the data content
 	fwrite(&checksum,1,1,fp);
 	fwrite(data,size,1,fp);
 }
 
-void mSetEndFile(FILE* fp,int sizeOfIndex) {
-	//sets the headers
-	short int size1,zero,size2;
-	fseek(fp,0,SEEK_END);
-	size1=ftell(fp)-(size2=sizeOfIndex);
-	zero=0;
-	fseek(fp,0,SEEK_SET);
-	fwrite(&size1,2,1,fp);
-	fwrite(&zero,2,1,fp);
-	fwrite(&size2,2,1,fp);
-	fclose(fp);
-}
-
-int mCreateIndexInDatFile(FILE* fp, tResource* r[]) {
-	//Add extra text at the end of the file
-	unsigned short int i=0;
-	unsigned short int junk=0;
-	unsigned short int tot=0;
-	int k=2;
-	int pos=ftell(fp);
+void mSetEndFile(FILE* fp, tResource* r[]) {
+	/*
+		Closes a dat file filling the index and other structures
+	*/
+	unsigned short int i=1;
+	unsigned short int totalItems=0;
+	unsigned short int size2=2;
+	unsigned long  int size1=ftell(fp);
 
-	fwrite(&tot,2,1,fp);
-	for (;i!=MAX_RES_COUNT;i++) { //TODO: add define MAX_RES_COUNT
+	//Write index
+	fwrite(&totalItems,2,1,fp); //Junk total items count to reserve 2 bytes
+	for (;i!=MAX_RES_COUNT;i++) {
 		if (r[i]!=NULL) {
-				//the file is in the archive, so I'll add it to the index
-				k+=8;
-				tot++;
-				fwrite(&i,2,1,fp);
-				fwrite(&((*r[i]).offset),2,1,fp);
-				fwrite(&junk,2,1,fp);
-				fwrite(&((*r[i]).size),2,1,fp);
+			//the file is in the archive, so I'll add it to the index
+			size2+=8;
+			totalItems++;
+			fwrite(&i,2,1,fp);
+			fwrite(&((*r[i]).offset),4,1,fp);
+			fwrite(&((*r[i]).size),2,1,fp);
 		}
 	}
-	fseek(fp,pos,SEEK_SET);
-	fwrite(&tot,2,1,fp);
-	return k;
+	fseek(fp,size1,SEEK_SET);
+	fwrite(&totalItems,2,1,fp); //Definitive total items count
+
+	//Write first 6 bytes header
+	fseek(fp,0,SEEK_SET);
+	fwrite(&size1,4,1,fp);
+	fwrite(&size2,2,1,fp);
+
+	//Closes the file and flushes the buffer
+	fclose(fp);
 }
 
 //Format detection function (private function, not in header file)
 char mAddCompiledFileToDatFile(FILE* fp,unsigned char** data, tResource *res) {
-	switch ((*res).type) {
+	//return 1 if ok, 0 if error
+	switch (res->type) {
+		case 1: //compile levels
+			return mFormatCompilePlv(*data,fp,res);
 		case 2: //compile bitmap
 			return mFormatCompileBmp(*data,fp,res);
 		case 3: //compile wave
 			return mFormatCompileWav(*data,fp,res);
+		case 7: //compile pcs
 		case 4: //compile midi
 			return mFormatCompileMid(*data,fp,res);
 		case 6: //compile palette
@@ -123,7 +135,6 @@ char mAddCompiledFileToDatFile(FILE* fp,unsigned char** data, tResource *res) {
 			if (!mImportPalette(data,&((*res).size))) {
 				return 0;
 			}
-		case 1:
 		case 5:
 		default:
 			mAddFileToDatFile(fp,*data,(*res).size);
@@ -136,7 +147,7 @@ char mAddCompiledFileToDatFile(FILE* fp,unsigned char** data, tResource *res) {
 |                    M A I N   F U N C T I O N                  |
 \***************************************************************/
 
-int compile(char* vFiledat, char* vDirExt, tResource* r[], char opt) {
+int compile(const char* vFiledat, const char* vDirExt, tResource* r[], int opt, const char* vDatFileName) {
 	/*
 		Return values:
 			-1 File couldn't be open for writing
@@ -148,7 +159,7 @@ int compile(char* vFiledat, char* vDirExt, tResource* r[], char opt) {
 	char vFileext[200];
 	int ok=0;
 	unsigned char* data;
-	unsigned short int i=0;
+	unsigned short int i=1;
 
 	if (!mBeginDatFile(&fp,vFiledat)) {
 		return -1; //File couldn't be open
@@ -158,19 +169,25 @@ int compile(char* vFiledat, char* vDirExt, tResource* r[], char opt) {
 
 	for (;i!=MAX_RES_COUNT;i++) {
 		if (r[i]!=NULL) {
-				getFileName(vFileext,vDirExt,r[i],i,vFiledat);
-				//the file is in the archive, so I'll add it to the main dat body
-				if ((*r[i]).size=mLoadFileArray(vFileext,&data)) {
-					(*r[i]).offset=(unsigned short)ftell(fp);
-					if (!mAddCompiledFileToDatFile(fp,&data,r[i])) {
-						ok++;
-					}
-					free(data);
-				} else {
+			if (opt&raw_flag) r[i]->type=0; //compile from raw
+			getFileName(vFileext,vDirExt,r[i],i,vDatFileName);
+			//the file is in the archive, so I'll add it to the main dat body
+			if (r[i]->size=mLoadFileArray(vFileext,&data)) {
+				r[i]->offset=(unsigned short)ftell(fp);
+				if (!mAddCompiledFileToDatFile(fp,&data,r[i])) {
+					if (opt&verbose_flag) printf("'%s' has errors, skipped\n",getFileNameFromPath(vFileext));
 					ok++;
+				} else {
+					if (opt&verbose_flag) printf("'%s' succesfully compiled\n",getFileNameFromPath(vFileext));
 				}
+				free(data);
+			} else {
+				if (opt&verbose_flag) printf("'%s' not open, skipped\n",getFileNameFromPath(vFileext));
+				ok++;
+			}
 		}
 	}
-	mSetEndFile(fp,mCreateIndexInDatFile(fp,r));
+	mSetEndFile(fp,r);
+	if (opt&verbose_flag) printf("Compilation done\n");
 	return ok;
 }
diff --git a/PR/src/lib/layers/disk.c b/PR/src/lib/layers/disk.c
index 31da622..b0a25a8 100644
--- a/PR/src/lib/layers/disk.c
+++ b/PR/src/lib/layers/disk.c
@@ -55,21 +55,23 @@ disk.c: Princed Resources : Disk Access & File handling functions
 \***************************************************************/
 
 //Repair folders
-void repairFolders(char* a) {
+const char *repairFolders(const char* a) {
 	int i,k;
+	static char result[260];
 
-	for (i=0,k=0;a[i];) {
+	for (i=0,k=0;a[i]&&(k<260);) {
 		if (isDirSep(a,i)) {
-			a[k]=DIR_SEPARATOR;
+			result[k]=DIR_SEPARATOR;
 			i++;
 			while (isDirSep(a,i)) i++;
 		} else {
-			a[k]=a[i];
+			result[k]=a[i];
 			i++;
 		}
 		k++;
 	}
-	a[k]=0;
+	result[k]=0;
+	return result;
 }
 
 
@@ -102,7 +104,7 @@ int makebase(const char* p) {
 	return a;
 }
 
-char writeOpen(char* vFileext, FILE* *fp) {
+char writeOpen(const char* vFileext, FILE* *fp) {
 	/*
 		Opens vFileext for write access
 		 if the path does't exist it is created
@@ -115,12 +117,13 @@ char writeOpen(char* vFileext, FILE* *fp) {
 		 0 if error
 		 1 if ok
 	*/
+	const char* file;
 
 	//Create base dir and save file
-	repairFolders(vFileext);
-	if (makebase(vFileext)) return 0;
+	file=repairFolders(vFileext);
+	makebase(file);
 
-	return ((*fp=fopen(vFileext,"wb"))!=NULL);
+	return ((*fp=fopen(file,"wb"))!=NULL);
 }
 
 
@@ -166,7 +169,7 @@ int mLoadFileArray(const char* vFile,unsigned char** array) {
 	int  aux;
 
 	//Open the file
-	if ((fp=fopen(vFile,"rb"))==NULL) {
+	if ((fp=fopen(repairFolders(vFile),"rb"))==NULL) {
 		return 0;
 	} else {
 		//get file size
@@ -199,7 +202,7 @@ char mSaveRaw(const char* vFile,const unsigned char* output, int size) {
   FILE * pFile;
 
 	if (!size) return 0;
-  if ((pFile=fopen(vFile,"wb"))==NULL) return 0;
+  if (!writeOpen(vFile,&pFile)) return 0;
 
   fwrite (output, 1, size, pFile);
   fclose (pFile);
@@ -238,5 +241,20 @@ char mDiskVealidateFileHeader(unsigned char* text, int size, FILE* fp) {
 	return (i==size); //0 if the compare for was stopped before end reached
 }
 
+const char* getFileNameFromPath(const char* path) {
+	/*
+		If you give a path you get the filename,
+		if you give a filename, you get the same filename
+	*/
+	int size;
+	size=strlen(path);
+	while (size) {
+		if (isDirSep(path,size)) {
+			return path+size+1;
+		}
+		size--;
+	}
+	return path;
+}
 
 
diff --git a/PR/src/lib/pr.c b/PR/src/lib/pr.c
index b5eb371..0bce2ad 100644
--- a/PR/src/lib/pr.c
+++ b/PR/src/lib/pr.c
@@ -39,11 +39,15 @@ pr.c: Main source file for Princed Resources
 	 MID Sound format development
 	  Christian Lundheim
 
+	 Resources.xml edition
+	  Steven Fayers
+
  Note:
   DO NOT remove this copyright notice
 */
 
 //Headers
+#include <stdio.h>
 #include <string.h>
 
 #include "pr.h"
@@ -54,30 +58,59 @@ pr.c: Main source file for Princed Resources
 #include "compile.h"
 #include "tasks.h"
 
-#include "bmp.h"
-#include "memory.h"
-#include "disk.h"
+#include "memory.h" /* getMemory, free */
+#include "disk.h"      /* getFileNameFromPath */
+
+#ifndef DLL
+ #ifdef UNIX
+  #include <stduni.h>
+ #else
+  #include "getopt.h"
+ #endif
+#endif
+
 
 //functions
 
-int prExportDat(char* vDatFile, char* vDirName, char* vResFile) {
-	return prExportDatOpt(vDatFile,vDirName,vResFile,3);
+int prExportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
+	return prExportDatOpt(vDatFile,vDirName,vResFile,0,NULL,NULL,"");
 }
 
-int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
+int prExportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName,const char* datAuthor, const char* backupExtension) {
 	/*
+		Arguments:
+			char* vDatFile        - full Path to the dat file;
+			                        if file use it, if dir, perform it for
+			                        all files
+			char* vDirName        - full Path to the extracting folder
+			                        (doesn't need to exist)
+			char* vResFile        - full Path to the resources XML file
+			                        (resources.xml by default)
+			                        No NULL
+			char opt              - program options, see below
+			char * vDatFileName   - name of the file to be extracted
+			                        NULL means predict it from vDatFile
+			const char* datAuthor - Author's name when extracting PLV's,
+			                        NULL is default
+			const char* backupExtension
+			                      - If backup_flag is set, the string to attach
+			                        to the backup files
+
 		Options:
-			0 - none
-			1 - extract
-			2 - update resources (rebuild resources list)
-			3 - 1&2
-			4 - use raw file if extraction
-			5 - 1&4
-			8 - Don't save
+			unknown_flag   - generate the unknown file without performing
+                       any extraction
+			raw_flag       - uses raw format
+			verbose_flag   - explain what is being done
+x			recursive_flag - searches for all dat files (only if vDatFile
+			                 is not a dat file and vDatFileName is NULL)
+x			force_flag     - default option, you cannot disable it,
+			                 so please make a backup of your files
+x			backup_flag    - backup your files
+
 
 		Return values:
 			00 Ok
-			-1 Error accesing the file DAT
+			-1 Error accessing the file DAT
 			-2 Memory error in extraction
 			-3 Invalid DAT file
 			-4 XML Parse error
@@ -85,24 +118,55 @@ int prExportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
 			-6 XML Attribute not recognized
 			-7 XML File not found
 	*/
+
+	//Declare variables
 	tResource* r[MAX_RES_COUNT];
 	int a;
+	const char defaultXmlFile[]=RES_XML_RESOURC_XML;
 
-	a=parseFile     (vResFile,vDatFile,r);
-	if (a<0) return a-3;
-	a=extract(vDatFile, vDirName,r,opt);
-	return a;
+	//Set default values
+	if (vResFile==NULL) vResFile=defaultXmlFile;
+	if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile);
+
+	//Parse XML and extract the file
+	a=parseFile     (vResFile,vDatFileName,r);
+	if (a<0) return a-3; //parsing errors
+	a=extract(vDatFile, vDirName,r,opt,vDatFileName);
+	printf("-3 es error: %d\n",a);
+	return a; //extracting errors/no errors
 }
 
-int prImportDat(char* vDatFile, char* vDirName, char* vResFile) {
-	return prImportDatOpt(vDatFile,vDirName,vResFile,1);
+int prImportDat(const char* vDatFile, const char* vDirName, const char* vResFile) {
+	return prImportDatOpt(vDatFile,vDirName,vResFile,0,NULL,"");
 }
 
-int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
+int prImportDatOpt(const char* vDatFile, const char* vDirName, const char* vResFile,int opt,const char* vDatFileName, const char* backupExtension) {
 	/*
+		Arguments:
+			char* vDatFile        - full Path to the dat file;
+			                        if file use it, if dir, perform it for
+			                        all files
+			char* vDirName        - full Path to the extracting folder
+			                        (doesn't need to exist)
+			char* vResFile        - full Path to the resources XML file
+			                        (resources.xml by default)
+			                        No NULL
+			char opt              - program options, see below
+			char * vDatFileName   - name of the file to be extracted
+			                        NULL means predict it from vDatFile
+			const char* backupExtension
+			                      - If backup_flag is set, the string to attach
+			                        to the backup files
+
 		Options:
-			0 - use raw files
-			1 - read data type
+			raw_flag       - uses raw format
+			verbose_flag   - explain what is being done
+x			recursive_flag - searches for all dat files (only if vDatFile
+			                 is not a dat file and vDatFileName is NULL)
+x			force_flag     - default option, you cannot disable it,
+			                 so please make a backup of your files
+x			backup_flag    - backup your files
+
 
 		Return values:
 			-1 DAT File couldn't be open for writing
@@ -113,118 +177,212 @@ int prImportDatOpt(char* vDatFile, char* vDirName, char* vResFile,char opt) {
 			00 File succesfully compiled
 			positive number: number of missing files
 	*/
-	tResource*    r[MAX_RES_COUNT];
+
+	//Declare variables
+	tResource* r[MAX_RES_COUNT];
 	int a;
-	a=parseFile     (vResFile,vDatFile,r);
+	const char defaultXmlFile[]=RES_XML_RESOURC_XML;
+
+	//Set default values
+	if (vResFile==NULL) vResFile=defaultXmlFile;
+	if (vDatFileName==NULL) vDatFileName=getFileNameFromPath(vDatFile);
+
+	//Parser XML and compile files
+	a=parseFile     (vResFile,vDatFileName,r);
 	if (a<0) return a-1;
-	a=compile (vDatFile, vDirName,r,opt);
+	a=compile (vDatFile, vDirName,r,opt,vDatFileName);
 	return a;
 }
 
+
+/*******************************************************
+                    M A I N   P R O G R A M
+       *******************************************************/
+
+
+
 //Main program
 #ifndef DLL
 void syntax() {
-	printf(PR_TEXT_SYNTAX);
+	printf(PARSING_HELP);
 }
 
-int main(int argc, char* argv[]) {
+int prMain(int option, const char* extension,const char* dirName,const char* resFile,const char* datfile, const char* datfilename,const char* datAuthor) {
 
 	//declare variables
-	char dir[260]=".";
 	int returnValue=1;
-	int option;
-	int i;
 
-#ifdef UNIX
-	if (argc==2) { //CGI support
+	//Do CGI tasks
+	if (option&cgi_flag) {
+		option&=(~classify_flag);
 		printf(PR_CGI_TEXT1);
-		printf(PR_CGI_TEXT2,prVerifyDatType(argv[1]));
-		return 1;
+		if (option==cgi_flag) {
+			printf(PR_CGI_TEXT2,prVerifyDatType(datfile));
+			return 1;
+		} else {
+			option=help_flag;
+		}
 	}
-#endif
 
 	printf(PR_ABOUT);
 
-	//Verify syntax
-	if ((argc<3)||(argc>4)||(argv[2][0])!='-') {
+	//If bad syntax or help screen requested
+	if (option&help_flag) {
 		syntax();
 		return -1;
 	}
-	if (argc==4 ) {
-		if (strlen(argv[3])<(260-1)) sprintf(dir,argv[3]);
+
+	if ((datfile==NULL)||option&version_flag) { //TODO use the recursive option and/or generic datfile
+		return -1;
 	}
 
 	//do selected tasks
-	switch (argv[2][1]) {
-		case 'e':
-		case 'x': {// file.dat --> extracted files + resource.xml
-			char array[8][29]={
-				"Ok",
-				"Error accesing the file DAT", /* DAT or extracted */
-				"Memory error in extraction",
-				"Invalid DAT file",
-				"XML Parse error",
-				"Memory error in parsing",
-				"XML Attribute not recognized",
-				"XML File not found"};
-			option=1;
-			for (i=2;argv[2][i];i++) {
-				switch (argv[2][i]) {
-					case 'n':option&=0xFE;break;
-					case 'r':option|=0x04;break;
-					default:printf(PR_TEXT_SKIPING,argv[2][i]);break;
-				}
-			}
-			printf("Extracting '%s' to '%s' with %d\r\n",argv[1],dir,option);
-			returnValue=prExportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option);
+	if (option&export_flag) {
+		char* array[]={
+			"Ok",
+			"Error accessing the file DAT", /* DAT or extracted */
+			"Memory error in extraction",
+			"Invalid DAT file",
+			"XML Parse error",
+			"Memory error in parsing",
+			"XML Attribute not recognized",
+			"XML File not found"};
+		printf("Extracting '%s' to '%s' with %04x\r\n",datfile,dirName,option);
+		returnValue=prExportDatOpt(datfile,dirName,resFile,option,NULL,datAuthor,extension);
+		printf(PR_TEXT_RESULT,array[-returnValue],returnValue);
+	}	else if (option&classify_flag) {
+		char* array[]={
+			"Memory error",
+			"File not found or no access error",
+			"Not a valid POP1 DAT file",
+			"Levels file",
+			"Graphic file with an image in the first valid entry (not common)",
+			"Waves/Digital sound file",
+			"Midis file",
+			"Valid DAT file with Undefined content",
+			"Graphic file with a palette in the first valid entry (common)",
+			"PC Speaker dat file",
+			"\0","\0","\0",
+			"Pop2 dat files"};
+		printf("Classifing '%s'\r\n",datfile);
+		returnValue=prVerifyDatType(datfile);
+		printf(PR_TEXT_RESULT,array[2+returnValue],returnValue);
+	}	else if (option&import_flag) {
+		char* array[]={
+			"File succesfully compiled",
+			"DAT File couldn't be open for writing",
+			"XML Parse error",
+			"No memory",
+			"XML Attribute not recognized",
+			"XML File not found"};
+		printf("Compiling '%s' from '%s' with %04x\r\n",datfile,dirName,option);
+		returnValue=prImportDatOpt(datfile,dirName,resFile,option,NULL,extension);
+		if (returnValue<=0) {
 			printf(PR_TEXT_RESULT,array[-returnValue],returnValue);
-		}	break;
-		case 'd': {// get type of file.dat
-			char array[14][65]={
-				"Memory error",
-				"File not found or no access error",
-				"Not a valid POP1 DAT file",
-				"Levels file",
-				"Graphic file with an image in the first valid entry (not common)",
-				"Waves/Digital sound file",
-				"Midis file",
-				"Valid DAT file with Undefined content",
-				"Graphic file with a palette in the first valid entry (common)",
-				"PC Speaker dat file",
-				"\0","\0","\0",
-				"Pop2 dat files"};
-			printf("Classifing '%s'\r\n",argv[1]);
-			returnValue=prVerifyDatType(argv[1]);
-			printf(PR_TEXT_RESULT,array[2+returnValue],returnValue);
-		}	break;
-		case 'c': { // extracted files + resource.xml --> files.dat
-			char array[6][39]={
-				"File succesfully compiled",
-				"DAT File couldn't be open for writing",
-				"XML Parse error",
-				"No memory",
-				"XML Attribute not recognized",
-				"XML File not found"};
-			option=1;
-				for (i=2;argv[2][i];i++) {
-					switch (argv[2][i]) {
-						case 'r':option&=0xFE;break;
-						default:printf(PR_TEXT_SKIPING,argv[2][i]);break;
-					}
-				}
-			printf("Compiling '%s' from '%s' with %d\r\n",argv[1],dir,option);
-			returnValue=prImportDatOpt(argv[1],dir,RES_XML_RESOURC_XML,(char)option);
-			if (returnValue>=0) {
-				printf(PR_TEXT_RESULT,array[-returnValue],returnValue);
-			} else {
-				printf(PR_TEXT_RESULT_ERR,returnValue);
-			}
-		} break;
-		default:
-			syntax();
-			return -1;
+		} else {
+			printf(PR_TEXT_RESULT_ERR,returnValue);
+		}
+	} else {
+		syntax();
+		return -1;
 	}
 	return returnValue;
 }
 
+int main (int argc, char **argv) {
+	//declare variables
+	char  datFileName[MAX_FILENAME_SIZE]; //TODO add
+	char  dirName[MAX_FILENAME_SIZE]=".";
+	char  extension[MAX_EXTENSION_SIZE]=DEFAULT_BACKUP_EXTENSION;
+	char  resFile[MAX_FILENAME_SIZE]=RES_XML_RESOURC_XML;
+	char* datFilePath;
+	char* datAuthor=NULL;
+	int   c;
+	int   flag=0;
+
+	//Parse options
+	while (1) {
+
+		static struct option long_options[] = PARSING_OPTIONS;
+
+		/* getopt_long stores the option index here. */
+		int option_index = 0;
+		c = getopt_long (argc, argv, PARSING_CHARS,long_options,&option_index);
+
+		/* Detect the end of the options. */
+		if (c == -1) break;
+
+		switch (c) {
+				case 'c':
+					flag|=import_flag;
+					if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'd':
+					flag|=force_flag;
+					break;
+				case 'x':
+				case 'e':
+					flag|=export_flag;
+					if (optarg) strncpy(dirName,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'b':
+					flag|=backup_flag;
+					if (optarg) strncpy(extension,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'f':
+					flag|=force_flag;
+					break;
+				case 'g':
+					flag|=cgi_flag;
+					break;
+				case 'm':
+					strncpy(resFile,optarg,MAX_FILENAME_SIZE);
+					break;
+				case 'r':
+					flag|=raw_flag;
+					break;
+				case 'R':
+					flag|=force_flag;
+					break;
+				case 't': {
+					int size;
+					size=strlen(optarg)+1;
+					datAuthor=getMemory(size);
+					memcpy(datAuthor,optarg,size);
+				}	break;
+				case 'v':
+					flag|=verbose_flag;
+					break;
+				case 1:
+					flag|=version_flag;
+					break;
+				case 2:
+					flag|=unknown_flag;
+					break;
+				default:
+					flag|=help_flag;
+		}
+	}
+
+	if (optind < argc) {
+		datFilePath=argv[optind];
+	} else {
+		datFilePath=NULL;
+	}
+
+	if (!flag) flag=help_flag;
+
+	//Run main program
+	prMain(flag,extension,dirName,resFile,datFilePath,datFileName,datAuthor);
+
+	//Free memory and exit
+	if (datAuthor!=NULL) free(datAuthor);
+  return 0;
+}
+
+#endif
+
+#ifdef SO
+//When compiling in Unix SO libraries
+void start() {}
 #endif
diff --git a/PR/src/lib/xml/search.c b/PR/src/lib/xml/search.c
index b3aa2b5..90f8203 100644
--- a/PR/src/lib/xml/search.c
+++ b/PR/src/lib/xml/search.c
@@ -82,6 +82,7 @@ void workTag(const tTag* t, tResource* r[]) {
 	int i;
 
 	id=(unsigned short)ptoi(t->value);
+	if (!id) return; //If there was not id or id contained wrong values, skip
 
 	//Process tag and copy values to resource
 	//Create Resource
@@ -97,6 +98,26 @@ void workTag(const tTag* t, tResource* r[]) {
 	}
 	if (i==8) 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
+	r[id]->number=(unsigned char)ptoi(t->number); //Transforms the char* levelnumer/number attribute into a char value, if error, demo level is used
+
+	//Title and description (only supported in level plv format
+	if (t->desc!=NULL) {
+		size=strlen(t->desc)+1;
+		r[id]->desc=(char*)malloc(size);
+		if (r[id]->desc==NULL) return;
+		memcpy(r[id]->desc,t->desc,size);
+	} else {
+		r[id]->desc=NULL;
+	}
+
+	if (t->name!=NULL) {
+		size=strlen(t->name)+1;
+		r[id]->title=(char*)malloc(size);
+		if (r[id]->title==NULL) return;
+		memcpy(r[id]->title,t->name,size);
+	} else {
+		r[id]->title=NULL;
+	}
 
 	//get external and copy it to the resource path
 	if (t->external!=NULL) {
diff --git a/PR/src/xml.c b/PR/src/xml.c
index 5f91923..0d46aba 100644
--- a/PR/src/xml.c
+++ b/PR/src/xml.c
@@ -77,6 +77,7 @@ tTag* getTagStructure() {
 	t->type=NULL;
 	t->value=NULL;
 	t->version=NULL;
+	t->number=NULL;
 
 	return t;
 }
@@ -95,6 +96,7 @@ void freeTagStructure(tTag* t) {
 	freeAllocation(t->type);
 	freeAllocation(t->value);
 	freeAllocation(t->version);
+	freeAllocation(t->number);
 	free(t);
 }
 
@@ -118,6 +120,8 @@ int attribFill(char* attr,char* val, tTag* t) {
 	FillAttr(t->type,"type");
 	FillAttr(t->value,"value");
 	FillAttr(t->version,"version");
+	FillAttr(t->number,"levelnumber"); //levelnumber is a number alias
+	FillAttr(t->number,"number");
 
 	return 0;
 }
@@ -448,7 +452,7 @@ void showTag(int n,tTag* t) {
 
 #endif
 
-tTag* parseXmlFile(char* vFile,int* error) {
+tTag* parseXmlFile(const char* vFile,int* error) {
 	/* error may take the following values:
 		-1 Parse error
 		-2 No memory