changeset 7760:c211a946f136 octave-forge

fix check of input arguments; support for STATA files versuions less than 114; remove trailing blanks
author schloegl
date Wed, 24 Nov 2010 21:28:59 +0000
parents 6d5f67bc6c0f
children 031e12c82fae
files extra/NaN/src/xptopen.cpp
diffstat 1 files changed, 243 insertions(+), 243 deletions(-) [+]
line wrap: on
line diff
--- a/extra/NaN/src/xptopen.cpp	Wed Nov 24 18:44:09 2010 +0000
+++ b/extra/NaN/src/xptopen.cpp	Wed Nov 24 21:28:59 2010 +0000
@@ -1,17 +1,17 @@
 //-------------------------------------------------------------------
-//   C-MEX implementation of kth element - this function is part of the NaN-toolbox. 
+//   C-MEX implementation of kth element - this function is part of the NaN-toolbox.
 //
 //   usage: x = xptopen(filename)
 //   usage: x = xptopen(filename,'r')
 //		read filename and return variables in struct x
 
 //   usage: xptopen(filename,'w',x)
-//		save fields of struct x in filename  
+//		save fields of struct x in filename
 
 //   usage: x = xptopen(filename,'a',x)
-//		append fields of struct x to filename  
+//		append fields of struct x to filename
 //
-//   References: 
+//   References:
 //
 //   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
@@ -34,11 +34,11 @@
 // References:
 // [1]	TS-140 THE RECORD LAYOUT OF A DATA SET IN SAS TRANSPORT (XPORT) FORMAT
 //	http://support.sas.com/techsup/technote/ts140.html
-// [2] IBM floating point format 
+// [2] IBM floating point format
 //	http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture
 // [3] see http://old.nabble.com/Re%3A-IBM-integer-and-double-formats-p20428979.html
 // [4] STATA File Format
-//	http://www.stata.com/help.cgi?dta 
+//	http://www.stata.com/help.cgi?
 //	http://www.stata.com/help.cgi?dta_113
 //-------------------------------------------------------------------
 
@@ -62,11 +62,11 @@
   #if (MX_API_VER<=0x07020000)
     typedef int mwSize;
     typedef int mwIndex;
-  #endif 
-#endif 
+  #endif
+#endif
 
 #define NaN  		(0.0/0.0)
-#define fix(m)     	(m<0 ? ceil(m) : floor(m))	
+#define fix(m)     	(m<0 ? ceil(m) : floor(m))
 #define max(a,b)	(((a) > (b)) ? (a) : (b))
 #define min(a,b)	(((a) < (b)) ? (a) : (b))
 
@@ -74,7 +74,7 @@
 #ifdef __linux__
 /* use byteswap macros from the host system, hopefully optimized ones ;-) */
 #include <byteswap.h>
-#endif 
+#endif
 
 #ifdef _WIN32
 #define __LITTLE_ENDIAN 1234
@@ -143,20 +143,20 @@
 double tm_time2gdf_time(struct tm *t);
 
 /*
-	compare first n characters of two strings, ignore case  
+	compare first n characters of two strings, ignore case
  */
 int strncmpi(const char* str1, const char* str2, size_t n)
-{	
+{
 	unsigned int k=0;
 	int r=0;
 	while (!r && str1[k] && str2[k] && (k<n)) {
 		r = tolower(str1[k]) - tolower(str2[k]);
-		k++; 
-	}	
-	return(r); 	 	
+		k++;
+	}
+	return(r);
 }
 
-void mexFunction(int POutputCount,  mxArray* POutput[], int PInputCount, const mxArray *PInputs[]) 
+void mexFunction(int POutputCount,  mxArray* POutput[], int PInputCount, const mxArray *PInputs[])
 {
 	const char L1[] = "HEADER RECORD*******LIBRARY HEADER RECORD!!!!!!!000000000000000000000000000000  ";
 	const char L2[] = "SAS     SAS     SASLIB 6.06     bsd4.2                          13APR89:10:20:06";
@@ -169,18 +169,18 @@
 	const char LO[] = "HEADER RECORD*******OBS     HEADER RECORD!!!!!!!000000000000000000000000000000  ";
 
 	const  char DATEFORMAT[] = "%d%b%y:%H:%M:%S";
-	char   *fn = NULL; 
-	char   Mode[3] = "r"; 
-	FILE   *fid; 	
+	char   *fn = NULL;
+	char   Mode[3] = "r";
+	FILE   *fid;
 	size_t count = 0, NS = 0, HeadLen0=80*8, HeadLen2=0, sz2 = 0, M=0;
 	char   H0[HeadLen0];
 	char   *H2 = NULL;
 	char 	SWAP = 0;
-	
+
 	// check for proper number of input and output arguments
-	if ( PInputCount > 0 && mxGetClassID(PInputs[1])==mxCHAR_CLASS) {
+	if ( PInputCount > 0 && mxGetClassID(PInputs[0])==mxCHAR_CLASS) {
 		size_t buflen = (mxGetM(PInputs[0]) * mxGetN(PInputs[0]) * sizeof(mxChar)) + 1;
-		fn = (char*)malloc(buflen); 
+		fn = (char*)malloc(buflen);
 		mxGetString(PInputs[0], fn, buflen);
 	}
 	else {
@@ -196,7 +196,7 @@
 		mexPrintf("\nThe SAS-XPT format stores Date/Time as numeric value counting the number of days since 1960-01-01.\n\n");
 		return;
 	}
-	if ( PInputCount > 1) 
+	if ( PInputCount > 1)
 	if (mxGetClassID(PInputs[1])==mxCHAR_CLASS && mxGetNumberOfElements(PInputs[1])) {
 		mxGetString(PInputs[1],Mode,3);
 		Mode[2]=0;
@@ -205,23 +205,23 @@
 	fid = fopen(fn,Mode);
 	if (fid < 0) {
 	        mexErrMsgTxt("Error XPTOPEN: cannot open file\n");
-	}	
+	}
 
 	if (Mode[0]=='r' || Mode[0]=='a' ) {
 
-		count += fread(H0,1,80*8,fid);		
+		count += fread(H0,1,80*8,fid);
 		enum FileFormat {
 			noFile, unknown, ARFF, SASXPT, SPSS, STATA
 		};
 		enum FileFormat TYPE; 		/* type of file format */
-		uint8_t		LittleEndian;   /* 1 if file is LittleEndian data format and 0 for big endian data format*/  
+		uint8_t		LittleEndian;   /* 1 if file is LittleEndian data format and 0 for big endian data format*/
 
-		TYPE = unknown; 
+		TYPE = unknown;
 		if (!memcmp(H0,"$FL2@(#) SPSS DATA FILE",27) || !memcmp(H0,"$FL2@(#) PASW STATISTICS DATA FILE",27)) {
 		/*
-			SPSS file format 
+			SPSS file format
 		*/
-			TYPE = SPSS;	
+			TYPE = SPSS;
 			switch (*(uint32_t*)(H0+64)) {
 			case 0x00000002:
 			case 0x00000003:
@@ -237,11 +237,11 @@
 		    		NS = b_endian_i32(*(uint32_t*)(H0+68));
 		    		M  = b_endian_i32(*(uint32_t*)(H0+80));
 			    	break;
-			default: 
-				TYPE = unknown;   	
+			default:
+				TYPE = unknown;
 			}
 			NS = *(int32_t*)(H0+80);
-			M  = *(int32_t*)(H0+80); 
+			M  = *(int32_t*)(H0+80);
 			if (SWAP) {
 				NS = bswap_32(NS);
 				M  = bswap_32(M);
@@ -249,14 +249,14 @@
 			HeadLen0 = 184;
 			char *H2 = (char*)malloc(NS*32);
 			size_t c2 = 0;
-			
+
 			/*
-				Read Variable SPSS header		
+				Read Variable SPSS header
 			*/
 			int ns = 0;
-			const char **ListOfVarNames = (const char**)malloc((NS+1) * sizeof(char*)); 
-			char *VarNames   = (char*)malloc((NS+1) * sizeof(char) * 9); 
-			double *MISSINGS = (double*)malloc((NS+1) * sizeof(double)); 
+			const char **ListOfVarNames = (const char**)malloc((NS+1) * sizeof(char*));
+			char *VarNames   = (char*)malloc((NS+1) * sizeof(char) * 9);
+			double *MISSINGS = (double*)malloc((NS+1) * sizeof(double));
 			for (uint32_t k=0; k<NS; k++) {
 				int32_t rec_type, type, FlagHasLabel, FlagMissing;
 				c2 += fread(&rec_type,1,4,fid);
@@ -268,7 +268,7 @@
 					rec_type     = bswap_32(rec_type);
 					type         = bswap_32(type);
 					FlagHasLabel = bswap_32(FlagHasLabel);
-				}	
+				}
 				if (rec_type != 2) ;//error('invalid SPSS file');
 				c2 += fread(VarNames+9*ns,1,8,fid);
 				VarNames[9*ns+8] = 0;
@@ -277,19 +277,19 @@
 					int32_t LenLabel;
 					c2 += fread(&LenLabel,1,4,fid);
 					if (SWAP) LenLabel = bswap_32(LenLabel);
-					if (LenLabel%4) LenLabel += 4 - LenLabel % 4; 
+					if (LenLabel%4) LenLabel += 4 - LenLabel % 4;
 					fseek(fid,LenLabel,SEEK_CUR);
 				}
-				if (FlagMissing) 
+				if (FlagMissing)
 					c2 += fread(MISSINGS+ns,1,8,fid);
-					
+
 				if (type != -1) ns++;
 			}
 
 
 			NS = ns;
 			mxArray **R = (mxArray**) mxMalloc(NS * sizeof(mxArray*));
-			/* ToDo: 
+			/* ToDo:
 				EXTRACT data
 			*/
 
@@ -298,12 +298,12 @@
 			for (uint32_t k = 0; k < NS; k++) {
 				 mxSetField(POutput[0], 0, ListOfVarNames[k], R[k]);
 			}
-			
+
 			if (MISSINGS) 	    free(MISSINGS);
 			if (VarNames) 	    free(VarNames);
 			if (ListOfVarNames) free(ListOfVarNames);
 			if (H2) 	    free(H2);
-		}  
+		}
 
 		if (TYPE == SPSS) {
 /*
@@ -323,15 +323,15 @@
 - Data record.
 
 */			;
-		}	
-		else if ((H0[0]==113 || H0[0]==114) && (H0[1]==1 || H0[1]==2) && H0[2]==1 && H0[3]==0) { 
+		}
+		else if ((H0[0]>=0x6e || H0[0]<=114) && (H0[1]==1 || H0[1]==2) && H0[2]==1 && H0[3]==0) {
 		/*
 			STATA File Format
-			http://www.stata.com/help.cgi?dta 
+			http://www.stata.com/help.cgi?dta
 			http://www.stata.com/help.cgi?dta_113
 		*/
 			TYPE = STATA;
-			// Header 119 bytes 	
+			// Header 119 bytes
 	    		LittleEndian = H0[1]==2;
 	    		if (LittleEndian) {
 	    			NS = l_endian_u16(*(uint16_t*)(H0+4));
@@ -342,65 +342,65 @@
 	    			M  = b_endian_u32(*(uint32_t*)(H0+6));
 	    		}
 
-	    		// Descriptors 
-	    		int fmtlen = (H0[0]==113) ? 12 : 49; 
+	    		// Descriptors
+	    		int fmtlen = (H0[0]==113) ? 12 : 49;
 	    		fseek(fid,109,SEEK_SET);
 	    		size_t HeadLen2 = 2+NS*(1+33+2+fmtlen+33+81);
 			char *H1 = (char*)malloc(HeadLen2);
-			fread(H1,1,HeadLen2,fid); 
+			HeadLen2 = fread(H1,1,HeadLen2,fid);
 
 			// expansion fields
 			char typ; int32_t len,c;
 			char flagSWAP = (((__BYTE_ORDER == __BIG_ENDIAN) && LittleEndian) || ((__BYTE_ORDER == __LITTLE_ENDIAN) && !LittleEndian));
-			do { 
+			do {
 				fread(&typ,1,1,fid);
 				fread(&len,4,1,fid);
-				if (flagSWAP) bswap_32(len); 
+				if (flagSWAP) bswap_32(len);
 				fseek(fid,len,SEEK_CUR);
-			} while (len);				
+			} while (len);
 			uint8_t *typlist = (uint8_t*)H1;
 
 /*
 			char *varlist = H1+NS;
 			char *srtlist;
-			char *fmtlist = H1+NS*36+2;			
-			char *lbllist = H1+NS*(36+fmtlen)+2;			
+			char *fmtlist = H1+NS*36+2;
+			char *lbllist = H1+NS*(36+fmtlen)+2;
 */
-		
+
 			mxArray **R = (mxArray**) mxMalloc(NS*sizeof(mxArray*));
 			size_t *bi = (size_t*) malloc((NS+1)*sizeof(size_t*));
-			const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*)); 
+			const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*));
 			bi[0] = 0;
 			for (size_t k = 0; k < NS; k++) {
 				size_t sz;
 				ListOfVarNames[k] = H1+NS+33*k;
 				switch (typlist[k]) {
-				case 0xfb: sz = 1; break; 
-				case 0xfc: sz = 2; break; 
-				case 0xfd: sz = 4; break; 
-				case 0xfe: sz = 4; break; 
+				case 0xfb: sz = 1; break;
+				case 0xfc: sz = 2; break;
+				case 0xfd: sz = 4; break;
+				case 0xfe: sz = 4; break;
 				case 0xff: sz = 8; break;
 				otherwise: sz = typlist[k];
-				} 
+				}
 				bi[k+1] = bi[k]+sz;
 			}
-			
-			// data 
+
+			// data
 			uint8_t *data = (uint8_t *) malloc(bi[NS] * M);
 			fread(data, bi[NS], M, fid);
-			
+
 			char *f = (char*)malloc(bi[NS]+1);
 			for (size_t k = 0; k < NS; k++) {
 				switch (typlist[k]) {
-				case 0xfb: 
-					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); 
+				case 0xfb:
+					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL);
 					for (size_t m = 0; m < M; m++) {
 						int8_t d = *(int8_t*)(data+bi[k]+m*bi[NS]);
 						((double*)mxGetData(R[k]))[m] = (d>100) ? NaN : d;
 					}
-					break; 
-				case 0xfc: 
-					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); 
+					break;
+				case 0xfc:
+					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL);
 					if (flagSWAP) for (size_t m = 0; m < M; m++) {
 						int16_t d = (int16_t) bswap_16(*(uint16_t*)(data+bi[k]+m*bi[NS]));
 						((double*)mxGetData(R[k]))[m] = (d>32740) ? NaN : d;
@@ -409,9 +409,9 @@
 						int16_t d = *(int16_t*)(data+bi[k]+m*bi[NS]);
 						((double*)mxGetData(R[k]))[m] = (d>32740) ? NaN : d;
 					}
-					break; 
-				case 0xfd: 
-					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); 
+					break;
+				case 0xfd:
+					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL);
 					if (flagSWAP) for (size_t m = 0; m < M; m++) {
 						int32_t d = (int32_t)bswap_32(*(uint32_t*)(data+bi[k]+m*bi[NS]));
 						((double*)mxGetData(R[k]))[m] = (d>2147483620) ? NaN : d;
@@ -420,20 +420,20 @@
 						int32_t d = *(int32_t*)(data+bi[k]+m*bi[NS]);
 						((double*)mxGetData(R[k]))[m] = (d>2147483620) ? NaN : d;
 					}
-					break; 
-				case 0xfe: 
-					R[k] = mxCreateNumericMatrix(M, 1, mxSINGLE_CLASS, mxREAL); 
+					break;
+				case 0xfe:
+					R[k] = mxCreateNumericMatrix(M, 1, mxSINGLE_CLASS, mxREAL);
 					if (flagSWAP) for (size_t m = 0; m < M; m++) {
-						((uint32_t*)mxGetData(R[k]))[m] = bswap_32(*(uint32_t*)(data+bi[k]+m*bi[NS]));;  
+						((uint32_t*)mxGetData(R[k]))[m] = bswap_32(*(uint32_t*)(data+bi[k]+m*bi[NS]));;
 					}
 					else for (size_t m = 0; m < M; m++) {
-						((uint32_t*)mxGetData(R[k]))[m] = *(uint32_t*)(data+bi[k]+m*bi[NS]);  
+						((uint32_t*)mxGetData(R[k]))[m] = *(uint32_t*)(data+bi[k]+m*bi[NS]);
 					}
-					break; 
-				case 0xff: 
-					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); 
+					break;
+				case 0xff:
+					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL);
 					if (flagSWAP) for (size_t m = 0; m < M; m++) {
-						((uint64_t*)mxGetData(R[k]))[m] = bswap_64(*(uint64_t*)(data+bi[k]+m*bi[NS]));  
+						((uint64_t*)mxGetData(R[k]))[m] = bswap_64(*(uint64_t*)(data+bi[k]+m*bi[NS]));
 					}
 					else for (size_t m = 0; m < M; m++) {
 						((uint64_t*)mxGetData(R[k]))[m] = *(uint64_t*)(data+bi[k]+m*bi[NS]);
@@ -446,13 +446,13 @@
 						memcpy(f, data+bi[k]+m*bi[NS], sz);
 						f[sz] = 0;
 						mxSetCell(R[k], m, mxCreateString(f));
-					}	
-				} 
+					}
+				}
 			}
-			if (f) free(f); 
+			if (f) free(f);
 			if (H1) free(H1);
 			if (bi) free(bi);
-			
+
 			/* convert into output */
 			POutput[0] = mxCreateStructMatrix(1, 1, NS, ListOfVarNames);
 			for (size_t k = 0; k < NS; k++) {
@@ -466,23 +466,23 @@
 		/*
 			 ARFF
 		*/
-			TYPE = ARFF;	
+			TYPE = ARFF;
 			rewind(fid);
 
 			char *H1 = NULL;
 			count = 0;
-			size_t ns = 0; 
+			size_t ns = 0;
 			char *vartyp = NULL;
 			char **datestr = NULL;
-			const char **ListOfVarNames = NULL; 
+			const char **ListOfVarNames = NULL;
 			mxArray **R = NULL;
 			size_t m = 0;
-			
+
 			while (!feof(fid)) {
 				HeadLen0 = max(1024,HeadLen0*2);
 				H1 = (char*)realloc(H1,HeadLen0);
 				count += fread(H1+count,1,HeadLen0-count-1,fid);
-			} 
+			}
 			H1[count]   = 0;
 
 			switch (H1[count-1]) {
@@ -490,21 +490,21 @@
 			case 0x0d:
 				H1[count]   = 0;
 				break;
-			default:	
+			default:
 				H1[count]   = 0x0a;
 			}
 			H1[count+1] = 0;
 
 			char *line = strtok(H1,"\x0a\0x0d");
 
-			int status = 0; 
+			int status = 0;
 			while (line) {
 
-				if (!strncmpi(line,"@relation",9)) {	
+				if (!strncmpi(line,"@relation",9)) {
 					status = 1;
-				}					
+				}
 
-				else if (status == 1 && !strncmpi(line,"@attribute",10)) {	
+				else if (status == 1 && !strncmpi(line,"@attribute",10)) {
 					if (ns<=NS) {
 						ns = max(16, ns*2);
 						ListOfVarNames = (const char**)realloc(ListOfVarNames,ns*sizeof(char*));
@@ -519,27 +519,27 @@
 					line[k++]=0;
 					while (isspace(line[k])) k++;
 					p2 = line+k;
-					
+
 					ListOfVarNames[NS] = p1;
 					if      (!strncmpi(p2,"numeric",7)) {
-						vartyp[NS] = 1; 
-					}	 
-					else if (!strncmpi(p2,"integer",7)) {					
-						vartyp[NS] = 2; 
+						vartyp[NS] = 1;
+					}
+					else if (!strncmpi(p2,"integer",7)) {
+						vartyp[NS] = 2;
 					}
-					else if (!strncmpi(p2,"real",4)) {	 	
-						vartyp[NS] = 3; 
+					else if (!strncmpi(p2,"real",4)) {
+						vartyp[NS] = 3;
 					}
-					else if (!strncmpi(p2,"string",6)) {					
-						vartyp[NS] = 4; 
+					else if (!strncmpi(p2,"string",6)) {
+						vartyp[NS] = 4;
 					}
 					else if (!strncmpi(p2,"{",1)) {
-						vartyp[NS] = 5; 
-					}	
-					else if (!strncmpi(p2,"date",4)) {				
-						vartyp[NS] = 6; 
+						vartyp[NS] = 5;
+					}
+					else if (!strncmpi(p2,"date",4)) {
+						vartyp[NS] = 6;
 						datestr = (char**)realloc(datestr,(NS+1)*sizeof(char*));
-						p2+=4; 
+						p2+=4;
 						while (isspace(*p2)) p2++;
 						datestr[NS] = p2;
 						if (p2[0]==34) {
@@ -549,51 +549,51 @@
 						}
 					}
 					else if (!strncmpi(p2,"relational",10)) {
-						vartyp[NS] = 7; 
+						vartyp[NS] = 7;
 					}
-					else vartyp[NS] = 99; 
-					
+					else vartyp[NS] = 99;
+
 					NS++;
-				}	
+				}
 
-				else if (status == 1 && !strncmpi(line,"@data",5)) {	
+				else if (status == 1 && !strncmpi(line,"@data",5)) {
 					status = 2;
-					char *p = line; 
-					while (*p) p++;  // goto end of current line  
+					char *p = line;
+					while (*p) p++;  // goto end of current line
 					p++; 		   // skip \x00
-					M = 0; 
+					M = 0;
 					while (*p) {
 						if (p[0]==0x0a || p[0]==0x0d) {
 							// count number of <CR>
 							M++;
-							// skip next char (deals with <CR><NL>) 
-							p+=2;  
+							// skip next char (deals with <CR><NL>)
+							p+=2;
 						}
 						else p++;
 					}
 					for (size_t k=0; k<NS; k++) {
-						if (vartyp[k]==4 || vartyp[k]==5) 
+						if (vartyp[k]==4 || vartyp[k]==5)
 							R[k] = mxCreateCellMatrix(M, 1);
 						else
 							R[k] = mxCreateDoubleMatrix(M, 1, mxREAL);
-					}		
+					}
 				}
-				
+
 				else if (status == 2) {
 
-					size_t p = 0,k; 
-					for (ns = 0; ns<NS; ns++) { 
-						// read next token 
-						while (isspace(line[p])) p++; 
+					size_t p = 0,k;
+					for (ns = 0; ns<NS; ns++) {
+						// read next token
+						while (isspace(line[p])) p++;
 						if (line[p]==39) {
 							p++; k=p;
 							while (line[k]!=39 && line[k]) k++;
 							// if (!line[k]) ; // error
 							line[k++] = 0;
-						} 
+						}
 						else
 							k=p;
-						while (line[k] != ',' && line[k] != 0) k++; 
+						while (line[k] != ',' && line[k] != 0) k++;
 						line[k] = 0;
 
 						if (vartyp[ns] < 4) {
@@ -607,7 +607,7 @@
 							size_t kk[6],n=0, N=strlen(datestr[ns]);
 							char T0[6][5];
 							char ix = 0;
-							struct tm t; 
+							struct tm t;
 
 							for (n=0; n < N; n++) {
 								switch (datestr[ns][n]) {
@@ -629,13 +629,13 @@
 								case 's':
 									ix = 5;
 									break;
-								default: 
-									ix = 99;	
-								}	
+								default:
+									ix = 99;
+								}
 
 								if (ix < 6) {
 									T0[ix][kk[ix]++] = line[p+n];
-								}	
+								}
 							}
 							for (n=0; n<6; n++) {
 								T0[n][kk[n]] = 0;
@@ -650,11 +650,11 @@
 							*(mxGetPr(R[ns])+m) = tm_time2gdf_time(&t);
 						}
 						p = k+1;
-					} 
+					}
 					m++;
 				}
 				line = strtok(NULL, "\x0a\x0d");
-			}			
+			}
 
 			/* convert into output */
 			POutput[0] = mxCreateStructMatrix(1, 1, NS, ListOfVarNames);
@@ -666,49 +666,49 @@
 			if (vartyp) free(vartyp);
 			if (datestr) free(datestr);
 			if (H1) free(H1);
-		}	
+		}
 
 		else if (!memcmp(H0,"HEADER RECORD*******LIBRARY HEADER RECORD!!!!!!!000000000000000000000000000000",78)) {
 		/*
 			 SAS Transport file format (XPORT)
 		*/
-			TYPE = SASXPT;	
-			
+			TYPE = SASXPT;
+
 			/* TODO: sanity checks */
 
-			char tmp[5]; 
-			memcpy(tmp,H0+7*80+54,4); 
+			char tmp[5];
+			memcpy(tmp,H0+7*80+54,4);
 			tmp[4] = 0;
 			NS = atoi(tmp);
-		
+
 			char *tmp2;
-			sz2 = strtoul(H0+4*80-6, &tmp2, 10); 
-			 
+			sz2 = strtoul(H0+4*80-6, &tmp2, 10);
+
 			HeadLen2 = NS*sz2;
-			if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80; 	
+			if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80;
 
 			/* read namestr header, and header line "OBS" */
 			H2 = (char*) realloc(H2, HeadLen2+81);
-			count  += fread(H2,1,HeadLen2+80,fid);		
+			count  += fread(H2,1,HeadLen2+80,fid);
 
-			/* size of single record */ 		
+			/* size of single record */
 			size_t pos=0, recsize = 0, POS = 0;
-			for (size_t k = 0; k < NS; k++) 
+			for (size_t k = 0; k < NS; k++)
 				recsize += b_endian_u16(*(int16_t*)(H2+k*sz2+4));
 
-			/* read data section */			 
-			size_t szData = 0; 
-			uint8_t *Data = NULL; 
+			/* read data section */
+			size_t szData = 0;
+			uint8_t *Data = NULL;
 			while (!feof(fid)) {
 				size_t szNew = max(16,szData*2);
 				Data         = (uint8_t*)realloc(Data,szNew);
 				szData      += fread(Data+szData,1,szNew-szData,fid);
 			}
-		
-			M = szData/recsize; 			
+
+			M = szData/recsize;
 
 			mxArray **R = (mxArray**) mxMalloc(NS*sizeof(mxArray*));
-			const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*)); 
+			const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*));
 			char *VarNames = (char*)malloc(NS * 9);
 
 			for (size_t k = 0; k < NS; k++) {
@@ -718,26 +718,26 @@
 				int n = k*sz2+8;
 				int flagDate = (!memcmp(H2+n+48,"DATE    ",8) || !memcmp(H2+n+48,"MONNAME ",8));
 				do {
-					VarNames[pos++] = H2[n];	
-				} while (isalnum(H2[++n]) && (n < k*sz2+16));	
-			
+					VarNames[pos++] = H2[n];
+				} while (isalnum(H2[++n]) && (n < k*sz2+16));
+
 
 				VarNames[pos++] = 0;
 
 				if ((*(int16_t*)(H2+k*sz2)) == b_endian_u16(1) && (*(int16_t*)(H2+k*sz2+4)) == b_endian_u16(8) ) {
 					// numerical data
-					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); 
+					R[k] = mxCreateDoubleMatrix(M, 1, mxREAL);
 					for (size_t m=0; m<M; m++) {
 						double d = xpt2d(b_endian_u64(*(uint64_t*)(Data+m*recsize+POS)));
 
 //						if (flagDate) d += 715876;  // add number of days from 0000-Jan-01 to 1960-Jan-01
 
 						*(mxGetPr(R[k])+m) = d;
-							
+
 					}
 				}
 				else if ((*(int16_t*)(H2+k*sz2)) == b_endian_u16(2)) {
-					// character string 
+					// character string
 					R[k] = mxCreateCellMatrix(M, 1);
 					char *f = (char*)malloc(maxlen+1);
 					for (size_t m=0; m<M; m++) {
@@ -754,29 +754,29 @@
 			for (size_t k = 0; k < NS; k++) {
 				 mxSetField(POutput[0], 0, ListOfVarNames[k], R[k]);
 			}
-	
+
 			if (VarNames) 	    free(VarNames);
 			if (ListOfVarNames) free(ListOfVarNames);
-			if (Data)	    free(Data); 
+			if (Data)	    free(Data);
 			/* end of reading SAS format */
 		}
-			
+
 		else {
 			fclose(fid);
 			mexErrMsgTxt("file format not supported");
-			return; 
+			return;
 		}
 
 
-		
+
 	}
 
 //	if (Mode[0]=='w' || Mode[0]=='a' ) {
 	if (Mode[0]=='w') {
-	
-		NS += mxGetNumberOfFields(PInputs[2]);	
 
-		// generate default (fixed) header	
+		NS += mxGetNumberOfFields(PInputs[2]);
+
+		// generate default (fixed) header
 		if (Mode[0]=='w') {
 			memset(H0,' ',80*8);
 			memcpy(H0,L1,strlen(L1));
@@ -788,61 +788,61 @@
 
 			memcpy(H0+80*7,L8,strlen(L8));
 		}
-		
+
 		time_t t;
-		time(&t); 
+		time(&t);
 		char tt[20];
 		strftime(tt, 17, DATEFORMAT, localtime(&t));
-		memcpy(H0+80*2-16,tt,16);		
-		memcpy(H0+80*2,tt,16);		
-		memcpy(H0+80*5+8,fn,min(8,strcspn(fn,".\x00")));		
-		memcpy(H0+80*5+32,"XPTOPEN.MEX (OCTAVE/MATLAB)",27);		
-		memcpy(H0+80*6-16,tt,16);		
-		memcpy(H0+80*6,tt,16);		
-		 
+		memcpy(H0+80*2-16,tt,16);
+		memcpy(H0+80*2,tt,16);
+		memcpy(H0+80*5+8,fn,min(8,strcspn(fn,".\x00")));
+		memcpy(H0+80*5+32,"XPTOPEN.MEX (OCTAVE/MATLAB)",27);
+		memcpy(H0+80*6-16,tt,16);
+		memcpy(H0+80*6,tt,16);
+
 		char tmp[17];
-		sprintf(tmp,"%04i", NS);	// number of variables 
+		sprintf(tmp,"%04i", NS);	// number of variables
 		memcpy(H0+80*7+54, tmp, 4);
-		
+
 		if (sz2==0) sz2 = 140;
-		if (sz2 < 136)  
+		if (sz2 < 136)
 			mexErrMsgTxt("error XPTOPEN: incorrect length of namestr field");
 
 		/* generate variable NAMESTR header */
 		HeadLen2 = NS*sz2;
-		if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80; 	
+		if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80;
 		H2 = (char*) realloc(H2,HeadLen2);
 		memset(H2,0,HeadLen2);
-		
+
 		mwIndex M = 0;
 		mxArray **F = (mxArray**) mxMalloc(NS*sizeof(mxArray*));
 		char **Fstr = (char**) malloc(NS*sizeof(char*));
 		size_t *MAXLEN = (size_t*) malloc(NS*sizeof(size_t*));
 		for (int16_t k = 0; k < NS; k++) {
 			Fstr[k] = NULL;
-			MAXLEN[k]=0; 
+			MAXLEN[k]=0;
 			F[k] = mxGetFieldByNumber(PInputs[2],0,k);
 			if (k==0) M = mxGetM(F[k]);
 			else if (M != mxGetM(F[k])) {
-				if (H2) free(H2); 
-				if (F)  free(F); 
+				if (H2) free(H2);
+				if (F)  free(F);
 				mexErrMsgTxt("Error XPTOPEN: number of elements (rows) do not fit !!!");
 			}
-			
-			if (mxIsChar(F[k])) { 
+
+			if (mxIsChar(F[k])) {
 				*(int16_t*)(H2+k*sz2) = b_endian_u16(2);
 				*(int16_t*)(H2+k*sz2+4) = b_endian_u16(mxGetN(F[k]));
 			}
 			else if (mxIsCell(F[k])) {
-				size_t maxlen = 0;  
-				for (mwIndex m = 0; m<M; m++) {	
-					mxArray *f = mxGetCell(F[k],m);			
+				size_t maxlen = 0;
+				for (mwIndex m = 0; m<M; m++) {
+					mxArray *f = mxGetCell(F[k],m);
 					if (mxIsChar(f) || mxIsEmpty(f)) {
 						size_t len = mxGetNumberOfElements(f);
 						if (maxlen<len) maxlen = len;
-					} 
+					}
 				}
-				Fstr[k] = (char*) malloc(maxlen+1);	
+				Fstr[k] = (char*) malloc(maxlen+1);
 				*(int16_t*)(H2+k*sz2) = b_endian_u16(2);
 				*(int16_t*)(H2+k*sz2+4) = b_endian_u16(maxlen);
 				MAXLEN[k] = maxlen;
@@ -850,7 +850,7 @@
 			else {
 				*(int16_t*)(H2+k*sz2) = b_endian_u16(1);
 				*(int16_t*)(H2+k*sz2+4) = b_endian_u16(8);
-			}	 
+			}
 			*(int16_t*)(H2+k*sz2+6) = b_endian_u16(k);
 			strncpy(H2+k*sz2+8,mxGetFieldNameByNumber(PInputs[2],k),8);
 		}
@@ -866,9 +866,9 @@
 					// numeric
 					uint64_t u64 = b_endian_u64(d2xpt(*(mxGetPr(F[k])+m)));
 					count += fwrite(&u64, 1, 8, fid);
-				}	
+				}
 
-/*				else if (mxIsChar(F[k])) { 
+/*				else if (mxIsChar(F[k])) {
 					*(int16_t*)(H2+k*sz2) = b_endian_u16(2);
 					*(int16_t*)(H2+k*sz2+4) = b_endian_u16(mxGetN(F[k]));
 				}
@@ -877,37 +877,37 @@
 					size_t maxlen = MAXLEN[k];
 					mxArray *f = mxGetCell(F[k],m);
 					mxGetString(f, Fstr[k], maxlen+1);
-					count += fwrite(Fstr[k], 1, maxlen, fid); 
+					count += fwrite(Fstr[k], 1, maxlen, fid);
 				}
 			}
 		}
 /*
-		// padding to full multiple of 80 byte: 
+		// padding to full multiple of 80 byte:
 		// FIXME: this might introduce spurios sample values
 		char d = count%80;
-		while (d--) fwrite("\x20",1,1,fid);	
+		while (d--) fwrite("\x20",1,1,fid);
 */
-		// free memory 
-		for (size_t k=0; k<NS; k++) if (Fstr[k]) free(Fstr[k]); 
-		if (Fstr)   free(Fstr); 
-		if (MAXLEN) free(MAXLEN); 
-		Fstr = NULL; 
+		// free memory
+		for (size_t k=0; k<NS; k++) if (Fstr[k]) free(Fstr[k]);
+		if (Fstr)   free(Fstr);
+		if (MAXLEN) free(MAXLEN);
+		Fstr = NULL;
 	}
-	fclose(fid); 
-	
-	if (H2) free(H2); 
+	fclose(fid);
+
+	if (H2) free(H2);
 	H2 = NULL;
-	
-	return; 
+
+	return;
 }
 
 
 /*
-	XPT2D converts from little-endian IBM to little-endian IEEE format 
+	XPT2D converts from little-endian IBM to little-endian IEEE format
 */
 
 double xpt2d(uint64_t x) {
-	// x is little-endian 64bit IBM floating point format 
+	// x is little-endian 64bit IBM floating point format
 	char c = *((char*)&x+7) & 0x7f;
 	uint64_t u = x;
 	*((char*)&u+7)=0;
@@ -918,33 +918,33 @@
 
 #elif __BYTE_ORDER==__LITTLE_ENDIAN
 
-#if DEBUG 
+#if DEBUG
 	mexPrintf("xpt2d(%016Lx): [0x%x]\n",x,c);
 #endif
 
-	// missing values 
-	if ((c==0x2e || c==0x5f || (c>0x40 && c<0x5b)) && !u ) 
+	// missing values
+	if ((c==0x2e || c==0x5f || (c>0x40 && c<0x5b)) && !u )
 		return(NaN);
-	
+
 	int s,e;
 	s = *(((char*)&x) + 7) & 0x80;		// sign
 	e = (*(((char*)&x) + 7) & 0x7f) - 64;	// exponent
-	*(((char*)&x) + 7) = 0; 		// mantisse x 
+	*(((char*)&x) + 7) = 0; 		// mantisse x
 
-#if DEBUG 
+#if DEBUG
 	mexPrintf("%x %x %016Lx\n",s,e,x);
-#endif 
+#endif
 
 	double y = ldexp(x, e*4-56);
 	if (s) return(-y);
 	else   return( y);
 
-#endif 
+#endif
 }
 
 
 /*
-	D2XPT converts from little-endian IEEE to little-endian IBM format 
+	D2XPT converts from little-endian IEEE to little-endian IBM format
 */
 
 uint64_t d2xpt(double x) {
@@ -958,29 +958,29 @@
 
 #elif __BYTE_ORDER==__LITTLE_ENDIAN
 
-	if (x != x) return(0x2eLL << 56);	// NaN - not a number 
+	if (x != x) return(0x2eLL << 56);	// NaN - not a number
 
 	if (fabs(x) == 1.0/0.0) return(0x5fLL << 56); 	// +-infinity
 
-	if (x == 0.0) return(0); 
+	if (x == 0.0) return(0);
 
-	if (x > 0.0) s=0; 
+	if (x > 0.0) s=0;
 	else s=1;
 
-	x = frexp(x,&e); 
+	x = frexp(x,&e);
 
-#if DEBUG 
+#if DEBUG
 	mexPrintf("d2xpt(%f)\n",x);
-#endif 
+#endif
 	// see http://old.nabble.com/Re%3A-IBM-integer-and-double-formats-p20428979.html
 	m = *(uint64_t*) &x;
 	*(((char*)&m) + 6) &= 0x0f; //
-	if (e) *(((char*)&m) + 6) |= 0x10; // reconstruct implicit leading '1' for normalized numbers 
+	if (e) *(((char*)&m) + 6) |= 0x10; // reconstruct implicit leading '1' for normalized numbers
 	m <<= (3-(-e & 3));
 	*(((char*)&m) + 7)  = s ? 0x80 : 0;
 	e = (e + (-e & 3)) / 4 + 64;
-	
-	if (e >= 128) return(0x5f); // overflow 
+
+	if (e >= 128) return(0x5f); // overflow
 	if (e < 0) {
 		uint64_t h = 1<<(4*-e - 1);
 		m = m / (2*h) + (m & h && m & (3*h-1) ? 1 : 0);
@@ -988,32 +988,32 @@
 	}
 	return (((uint64_t)e)<<56 | m);
 
-#endif 
+#endif
 
-} 
+}
 
 
 double tm_time2gdf_time(struct tm *t) {
-	/* based Octave's datevec.m 
-	it referes Peter Baum's algorithm at http://vsg.cape.com/~pbaum/date/date0.htm 
-	but the link is not working anymore as of 2008-12-03. 
+	/* based Octave's datevec.m
+	it referes Peter Baum's algorithm at http://vsg.cape.com/~pbaum/date/date0.htm
+	but the link is not working anymore as of 2008-12-03.
 
 	Other links to Peter Baum's algorithm are
 	http://www.rexswain.com/b2mmddyy.rex
 	http://www.dpwr.net/forums/index.php?s=ecfa72e38be61327403126e23aeea7e5&showtopic=4309
 	*/
-	
+
 	int Y,M,s; //h,m,
-	double D; 
-		
-	D = t->tm_mday; 
-	M = t->tm_mon+1; 
+	double D;
+
+	D = t->tm_mday;
+	M = t->tm_mon+1;
 	Y = t->tm_year+1900;
-		
+
 	// Set start of year to March by moving Jan. and Feb. to previous year.
   	// Correct for months > 12 by moving to subsequent years.
   	Y += fix ((M-14.0)/12);
-  
+
   	const int monthstart[] = {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
 	// Lookup number of days since start of the current year.
   	D += monthstart[t->tm_mon % 12] + 60;
@@ -1023,9 +1023,9 @@
   	D += 365*Y + floor (Y/4) - floor (Y/100) + floor (Y/400);
 
   	// Add fraction representing current second of the day.
-  	s = t->tm_hour*3600 + t->tm_min*60 + t->tm_sec; 
+  	s = t->tm_hour*3600 + t->tm_min*60 + t->tm_sec;
 
-	// s -= timezone;	
+	// s -= timezone;
 	return(D + s/86400.0);
 }