// matwrite version history // 0.81 First test release // 0.82 Fixed some stability issues // Some improved code efficiency // Changed some error messages/codes // 0.90 User can now group variables to export as a matrix // Now reading names from local macro #include "stplugin.h" #include #include #include #include #include #include #include //#define DEBUG // my matFile class to write MAT-file level 4 files // these will be compatible with any MATLAB version class matFile { public: matFile() { thisRep=1; } bool matOpen(char *fileName, char fileMode[4]) { fp = fopen(fileName,fileMode); if (fp==NULL) return true; else return false; } bool matClose() { if (fclose(fp)) return true; else return false; } bool matWrite(char *matName, const ST_double *data, int row, int col, int rep) { typedef struct { long type; long mrows; long ncols; long imagf; long namelen; } matHeader; int mn = row*col; int writtenCheck = mn; size_t written=0; //to evaluate success if (thisRep==1) { matHeader thisHeader; thisHeader.type = 0000; thisHeader.mrows = row; thisHeader.ncols = col*rep; thisHeader.imagf = 0; thisHeader.namelen = strlen(matName) + 1; writtenCheck += 1 + thisHeader.namelen; written += fwrite(&thisHeader, sizeof(matHeader), 1, fp); written += fwrite(matName, sizeof(char), thisHeader.namelen, fp); } written += fwrite(data, sizeof(ST_double), mn, fp); if (thisRep0) { for(i=0; i < SF_nvars(); i++) { ST_double *arrayDouble = new ST_double[SF_nobs()]; if (newMat) { if (i>0) token = strtok(NULL, " "); //check whether a matlab legal variable name switch (matlabLegal(token)) { case 1: strcpy(buf, "variable name "); strcat(buf, token); strcat(buf, " is a reserved MATLAB word\n"); SF_error(buf); error = 198; break; case 2: strcpy(buf, "variable "); strcat(buf, token); strcat(buf, " has an illegal variable name\n"); SF_error(buf); SF_error("variable names must begin with a letter\n"); error = 198; break; case 3: strcpy(buf, "variable "); strcat(buf, token); strcat(buf, " has an illegal variable name\n"); SF_error(buf); SF_error("variable names can only contain underscores and alphanumeric characters\n"); error = 198; break; default: break; } if (error) { delete [] token; delete [] allNames; delete [] file; delete [] arrayDouble; arrayDouble = NULL; return(error); //invalid name } if (thisMat<=matCount) { matColumn = atoi(strtok(NULL, " ")); thisMat++; } else matColumn = 1; n = 1; thiswarn = false; } //if newMat if (n0) { for(j = SF_in1(); j <= SF_in2(); j++) { if(SF_ifobs(j)) { if (rc = SF_vdata(i+1,j,&arrayDouble[m])) return rc; if (SF_is_missing(arrayDouble[m])) { arrayDouble[m] = inf; if (!thiswarn) { strcpy(buf, "warning: "); strcat(buf, token); strcat(buf, " contains missing values\n"); SF_display(buf); thiswarn = true; #ifdef DEBUG strcpy(buf," MISSING,"); fwrite(buf,sizeof(char),strlen(buf) + 1,debuglog); #endif DEBUG } } m++; } } if (m>0) { if (pMat.matWrite(token,arrayDouble,m,1,matColumn)) { strcpy(buf,"error creating variable "); strcat(buf,token); strcpy(buf,"\n"); SF_error(buf); delete [] token; delete [] allNames; delete [] file; delete [] arrayDouble; arrayDouble = NULL; return(198); //invalid syntax } #ifdef DEBUG strcpy(buf," SAVED.\n"); fwrite(buf,sizeof(char),strlen(buf) + 1,debuglog); #endif DEBUG delete [] arrayDouble; arrayDouble = NULL; } //if m>0 } //if SF_nobs>0 } // nvars loop if (m==0) SF_display("warning: no observations\n"); } // if nvars>0 int nMat = 0; int index = 0; token = strtok(NULL, " "); while( token != NULL ) { if (SF_col(token)==0) { if (SF_row(token)==0) { strcpy(buf,"warning: matrix "); strcat(buf,token); strcat(buf," does not exist\n"); SF_display(buf); } if (SF_row(token)==1) { strcpy(buf,"warning: matrix "); strcat(buf,token); strcat(buf," has zero dimension\n"); SF_display(buf); } } else { switch (matlabLegal(token)) { case 1: strcpy(buf, "matix name "); strcat(buf, token); strcat(buf, " is a reserved MATLAB word\n"); SF_error(buf); error = 198; break; case 2: strcpy(buf, "matrix "); strcat(buf, token); strcat(buf, " has an illegal variable name\n"); SF_error(buf); SF_error("matrix names must begin with a letter\n"); error = 198; break; case 3: strcpy(buf, "matrix "); strcat(buf, token); strcat(buf, " has an illegal variable name\n"); SF_error(buf); SF_error("matrix names can only contain underscores and alphanumeric characters\n"); error = 198; break; default: break; } //switch if (error) { delete [] token; delete [] allNames; delete [] file; return(error); } ST_double *arrayDouble = new ST_double[SF_col(token)*SF_row(token)]; thiswarn = false; nMat++; for (j=1;j<=SF_row(token);j++) { for (k=1;k<=SF_col(token);k++) { index = j + (k-1)*SF_row(token) - 1; if (rc = SF_mat_el(token,j,k,&arrayDouble[index])) return rc; if (SF_is_missing(arrayDouble[index])) { arrayDouble[index] = inf; if (!thiswarn) { strcpy(buf, "warning: matrix "); strcat(buf, token); strcat(buf, " contains missing values\n"); SF_display(buf); thiswarn = true; } } } } pMat.matWrite(token,arrayDouble,SF_row(token),SF_col(token),1); delete [] arrayDouble; arrayDouble = NULL; } //else token = strtok(NULL, " "); } //while delete [] token; delete [] allNames; #ifdef DEBUG strcpy(buf,"Closing MAT-file...\n"); fwrite(buf,sizeof(char),strlen(buf) + 1,debuglog); #endif DEBUG if (pMat.matClose()) { SF_error("can't close MAT-file\n"); error = 608; } if (SF_nvars()==0 && nMat==0) { SF_error("no variables or matrices exported\n"); if (rc = remove(file)) { strcpy(buf,"can't delete file "); strcat(buf,file); strcat(buf,"\n"); SF_error(buf); } error = 198; } if (m==0 && nMat==0) { SF_error("no observations and no matrices exported\n"); if (rc = remove(file)) { strcpy(buf,"can't delete file "); strcat(buf,file); strcat(buf,"\n"); SF_error(buf); } error = 198; } //success! #ifdef DEBUG strcpy(buf,"Completed.\n"); fwrite(buf,sizeof(char),strlen(buf) + 1,debuglog); fclose(debuglog); #endif DEBUG delete [] file; return(error); } //STDLL stata_call int matlabLegal(char *varname) { const char reserved[] = " break case catch continue else endif end for function global if otherwise persistent return switch try while "; int unsigned i; int error = 0; char *thisvarname = new char[strlen(varname)+3]; strcpy(thisvarname," "); strcat(thisvarname,varname); strcat(thisvarname," "); //reserved word? if (strstr(reserved,thisvarname)) error = 1; //initial character if (!isalpha(thisvarname[1])) error = 2; //all other characters must be alphanumeric or underscore //not sure why first condition is not capturing "£" // not sure if this works properly... if (strlen(thisvarname)>1) { for (i=2;i