#include "xstcl.h" #include "xscf.h" #include #include #include "fitsio.h" #include /* need direct access to xspec's MEM fortran dynamic memory 'common block' */ /* for the function udmArray. these defines are taken from udmget.c */ #ifdef m88k #define MEM mem__ #endif #ifdef __APPLE__ #define MEM mem_ #endif #ifdef __hpux #define MEM mem_ #endif #ifdef linux #define MEM mem_ #endif #ifdef sun #define MEM mem_ #endif #ifdef NeXT #define MEM mem #endif #ifdef ultrix #define MEM mem_ #endif #ifdef __osf__ #define MEM mem_ #endif #ifdef __sgi #define MEM mem_ #endif #ifdef VMS #define MEM mem #endif #ifdef __CYGWIN32__ #define MEM mem_ #endif FILE* script; extern int MEM; int isNumber(const char* testString) { int status = 1; float test = 0.; status = sscanf(testString,"%f",&test); return status; } int isInteger(const char* testString) { const char* ptr = testString; const char* pfirst = NULL; int status = 1; int n = 0; n = strlen (testString); while (*ptr == ' ') ++ptr; pfirst = ptr; while (*(testString + n) == ' ') --n; if (n == 0) return 0; while ( ptr < testString + n ) { if ( (ptr == pfirst && (*ptr == '-' || *ptr == '+') ) || isdigit((int)*ptr) ) ++ptr; else { status = 0; break; } } return status; } /* * xspec specific function for returning a pointer of the correct type from * the udmget fortran accessible dynamic memory system. * */ void * udmArray(const char* code) { void* arrayPtr = NULL; int offset = 0; offset = getUdmOffset(code); /* see getUdmOffset.f for an explanation of the following * * one difference between this and the udmget code is there is no * "element size" multiplication since &MEM is cast to the correct type. * thus the compiler takes care of getting the offset size right. */ if ( strpbrk(code,"gil") != NULL ) { arrayPtr = (int *)&MEM + (offset - 1); } else { /* want a floating point result */ arrayPtr = (float *)&MEM + (offset - 1); } /* there's no possibility of any other values for code getting here as getUdmOffset.f checks for this and calls abort if this happens. */ return arrayPtr; } /* * squeeze blank spaces out of an input string. Replaces Xparse routine xsquez. * currently used in parameter setting procedures. * */ void squeezeString(char** string) { char* outString = (char *)calloc(strlen(*string)+1,sizeof(char)); char* ptr = NULL; int i = 0; ptr = *string; while (ptr < *string + strlen(*string)) { if (*ptr != ' ') { outString[i] = *ptr; i++; } ptr++; } outString[i] = '\0'; strcpy(*string, outString); free (outString); return; } char* returnDelimitedArgument(char** string,const char* delim) { char* arg=NULL; unsigned int n = 0; unsigned int lenArg = 0; /* a non-destructive version of strtok. Returns a pointer to an empty string (not a NULL) if the delimiter is not found, and returns a NULL if the input string is of zero size. */ if ( (n = strlen(*string)) == 0) return arg; while( **string == ' ') {(*string)++;} /* strip leading blanks */ if ( (lenArg = strcspn(*string,delim) ) != 0) { arg = (char *)malloc((lenArg+1)*sizeof(char)); strncpy(arg,*string,lenArg); arg[lenArg] = '\0'; *string += MIN(lenArg+1,strlen(*string)); } else { if (strlen(*string) == 0) arg = NULL; else { (*string)++; arg = malloc(sizeof(char)); strcpy(arg,""); } } return arg; } /* * * Adds spaces in between string tokens if required. * */ void spaceString(char** string) { char* end = NULL; char* begintmp = NULL; char* tmpString = NULL; begintmp = (char*)calloc(256,sizeof(char)); end = *string + strlen(*string); tmpString = begintmp; while (*string < end) { if (strchr("+-",**string) != NULL) { if ( strchr("edED",*(*string-1)) == NULL) { if ( *(*string-1) != ' ') { *tmpString = ' '; tmpString++; } } } if (strchr("*/",**string) != NULL) { *tmpString = ' '; tmpString++; } *tmpString = **string; tmpString++; (*string)++; } *tmpString = '\0'; strcpy(*string,begintmp); free(begintmp); return; } /* * Checks that a real number expressed in a string has a valid exponent. * This routine is probably redundant because of the newer isNumber function, * so this may be quickly deprecated. */ int checkExponent(char* string) { char* strPtr = string; int status = 0; while (strPtr < string + strlen(string)-1) { if ( strchr("edED",*strPtr) != NULL) { if ( ( (strchr("+-",*(strPtr+1)) != NULL) && !isdigit(*(strPtr+2)) ) || (strchr("+-",*(strPtr+1)) == NULL) && !isdigit(*(strPtr+1)) ) { status = -1; break; } } strPtr++; } return status; } int newFileName(const char* type, const char* name, const char* name2, char* newfile) { /* replacement for fortran routine rplfil, which prompts the user for a new filename for an auxiliary or response file if none is provided in a FITS data file. This needs to be in C to have access to the global executingScript variable, so that this function may have different behaviour when xspec is run interactively. modified so that for auxiliary files both the data filename and the auxiliary filename are written. The latter is the name2 argument. newfile is the only output. It must be allocated by fortran. */ int status = 0; int i = 0; char* promptString = NULL; char* errString = NULL; struct stat* statbuf; promptString = (char *)malloc(64*sizeof(char)); errString = (char *)malloc((strlen(name) + 128)*sizeof(char)); statbuf = (struct stat*)malloc(sizeof(struct stat)); if ( strstr(type,"data") != NULL ) { sprintf(errString,"Error: cannot read data file %s",name); } else if (strstr(type,"model") != NULL) { sprintf(errString,"Error: cannot read table model file %s", name); } else { sprintf(errString,"Error: cannot read %s file %s for data file %s",type,name2,name); } XWRITE(errString,5); if (executingScript) { return -2; } else { /* newfile is allocated in the fortran calling function */ int n = 0; newfile[0] = '\0'; sprintf(promptString," Replacement file (enter 'none' to return to XSPEC> prompt): "); xs_tcl_read(promptString, newfile, &status); n = strlen(newfile); /* strip trailing blanks */ while (strchr(" \t",newfile[n-1]) != NULL) { newfile[n-1] = '\0'; n--; } if ( !( strncmp(newfile,"/*",2) || newfile[0] == '/' && strlen(newfile) == 1 || strncasecmp(newfile,"none",4) ) ) { if ( stat(newfile,statbuf) < 0 ) { if ( strncasecmp(newfile,"none",4)) { sprintf(errString,"Error: cannot open file %s",newfile); XWRITE(errString,5); strcpy(newfile,"none"); } status = 1; } } } free(statbuf); free(promptString); free(errString); return status; } int checkForFileOpen(const char* fileName, const char* mode) { struct stat* test = (struct stat*) malloc(sizeof(struct stat)); int isNotPresent = 0; int isAccessible = 0; FILE* testForOpen = NULL; isNotPresent = stat(fileName,test); if ( testForOpen = fopen(fileName,mode) ) { isAccessible = 1; fclose(testForOpen); } if ( isNotPresent ) unlink(fileName); free (test); return isAccessible; }