/***************************************************************************** * File: pds_util.c * Programmer: Dorian Winterfeld * Anne Raugh * Institution: PDS/Small Bodies Node * niversity of Maryland * Date: Feb. 20, 1995 * Last Revision: * Abstract: Support routines for PDS to FITS translator program. * Description: This file contains all the miscilenious support routine * used by other modules. ******************************************************************************/ #include #include #include #include #include #include "pds_util.h" #include "pdserror.h" #include "fits_obj.h" #include "pds.h" /* global variables */ extern FILE *FITS_file; /* Pointer to FITS file */ extern FILE *PDS_file; /* Pointer to PDS file */ extern FILE *table_file; /* Pointer to user translation table */ extern FILE *PDSDD; /* Pointer to PDS Data Dictionary file */ extern FILE *index_file; /* Pointer to PDSDD index file */ extern FILE *trans_out; /* output file for translation table */ extern FILE *log_file; /* output file for unmatched FITS keywords */ /****************************************************************************** * Function: parse_arguments * Abstract: parses command line arguments supplied by the user. * Input * argc: number of arguments * argv: array of input parameters. * Outputs * PDS_filename: Holds name of input PDS file from command line. * table_filename: Holds name of User Translation Table file from command * line. * FITS_filename: Holds name of FITS output file from command line. * dd_path: Path to PDS Data Dictionary. * std_path: Path to Standard Translation Table. * Return * OK on success, error code otherwise. *******************************************************************************/ int parse_arguments(int argc,char *argv[],char *PDS_filename, char *table_filename,char *FITS_filename, char *reserved_filename,char **dd_path,char **std_path) { int i; /* general index */ int len; /* string length */ int FITS_found = FALSE; /* TRUE when FITS file name parameter found */ int table_found = FALSE; /* TRUE when translation table name found */ int PDS_found = FALSE; /* TRUE when PDS file name found */ if ((argc >= 2) && (strcmp(argv[1],"-h") == 0)) return SWITCH_DESC; if (argc < 4) return ARG_ERROR; /* LOOP command line arguments */ for (i = 1; i < argc; i++) { /* look for switch parameter */ /* is switch valid ? */ if ((argv[i][0] == '-') && (argv[i][1] != 'p') && (argv[i][1] != 't')) return SWITCH_ERROR_1; if (strcmp(argv[i],"-p")==0){ if (argv[i+1] == NULL) return SWITCH_ERROR_2; else { len = strlen(argv[i+1]); if ((*dd_path = (char *)malloc(len+1)) == NULL) return MALLOC_ERROR; strcpy(*dd_path,argv[i+1]); i++; } } else if (strcmp(argv[i],"-t")==0){ if (argv[i+1] == NULL) return SWITCH_ERROR_2; else { len = strlen(argv[i+1]); if ((*std_path = (char *)malloc(len+1)) == NULL) return MALLOC_ERROR; strcpy(*std_path,argv[i+1]); i++; } } else if (strcmp(argv[i],"-r")==0){ if (argv[i+1] == NULL) return SWITCH_ERROR_2; else { len = strlen(argv[i+1]); strcpy(reserved_filename,argv[i+1]); i++; } } else /* look for required command line parameters */ if (PDS_found == FALSE){ strcpy(PDS_filename,argv[i]); PDS_found = TRUE; } else if (table_found == FALSE){ strcpy(table_filename,argv[i]); table_found = TRUE; } else if (FITS_found == FALSE){ strcpy(FITS_filename,argv[i]); FITS_found = TRUE; } } /* if required parameter is missing, then return error */ if ((FITS_found == FALSE)||(table_found == FALSE)||(PDS_found == FALSE)) return ARG_ERROR_2; return OK; } /* end parse_arguments */ /***************************************************************************** * Function: close_files * Abstract: Closes all opened files. *****************************************************************************/ void close_files(void) { fclose( FITS_file ); fclose( table_file); fclose( PDS_file ); fclose( PDSDD ); fclose( index_file); fclose( trans_out); fclose( log_file ); } /* end close_files */ /************************************************************************** * Function: skip_blanks * Abstract: skips past blank lines and comments. * If EndOfFile is encountered, return 0. * Input * file: pointer to PDS file. * Output * line: buffer to hold line. * Return * 1 on success, 0 on failure. ***************************************************************************/ int skip_blanks(FILE *file, char *line) { int len; if (!fgets(line,101,file)) return 0; eat_white(line); if ((line[0] == '/') && (line[1] == '*')){ len = strlen(line); while ((line[len-2] != '*') && (line[len-1] != '/')){ if (!fgets(line,101,file)) return 0; len = strlen(line); } if (!fgets(line,101,file)) return 0; } while((strcmp(line,"\n") == 0) || (strlen(line) == 0)) if (!fgets(line,101,file)) return 0; return 1; } /* end skip_lines */ /************************************************************************** * Function: split_pds_line * Abstract: splits input string into two strings seperated by '='. * Description: Used by read_pds to split a PDS line into a keyword * and a value string. * Inputs * line: Character string holds 80 character string. * Output * key: Character string holds PDS keyword. * value: Character string holds PDS value string. * Return * OK on success ***************************************************************************/ int split_pds_line(char *line, char *key, char *value) { static char local[100]; /* buffer to hold PDS string */ char *key_str; char *value_str; /* pointer to PDS value string */ /* copy line to temp string */ strcpy(local,line); /* get PDS keyword */ key_str = strtok(local,"="); strcpy(key,eat_white(key_str)); /* get value string */ if ((value_str = strtok(NULL,"=")) == NULL) return OK; strcpy(value,eat_white(value_str)); return OK; } /* end split_fits_line */ /********************************************************************** *Function: eat_white *Abstract: deletes leading and trailing blanks from char string **********************************************************************/ char *eat_white(char *string) { int len1,len2,cnt = 0,j; /* get string length */ len1 = strlen(string); /* while first char is blank, shift string to left */ while (isspace(string[0])){ for (j = 0; j < len1; j++) /* shift to left */ string[j] = string[j+1]; } /* get new length */ len2 = strlen(string); cnt = len2 - 1; while (isspace(string[cnt])) cnt--; /* append end_of_string */ string[cnt+1] = '\0'; return string; } /* end eat_white */ /****************************************************************************** * Function: print_header * Abstract: prints header for log file. * Input * name: character string name of error log file. ******************************************************************************/ void print_header(char *name) { fprintf(log_file,"##################################################"); fprintf(log_file,"##############################\n"); fprintf(log_file,"# %s\n#\n",name); fprintf(log_file,"# This log file contains all system messages"); fprintf(log_file,", including warning and error\n# messages. "); fprintf(log_file,"It also contains PDS keywords for which no"); fprintf(log_file," corresponding FITS \n# keyword was "); fprintf(log_file,"found in either the standard or user defined"); fprintf(log_file," translation files.\n"); fprintf(log_file,"###################################################"); fprintf(log_file,"#############################\n"); } /* end print_header */ /****************************************************************************** * Function: print_error * Abstract: prints error messages * Input * status: integer error flag *******************************************************************************/ void print_error(int status) { if (status == MALLOC_ERROR){ printf("\nERROR: Unable to allocate memory for data structure.\n"); fprintf(log_file,"\nERROR: Unable to allocate memory"); fprintf(log_file," for data structure.\n"); fprintf(log_file,"Program will terminate\n"); } else if (status == ERROR){ printf("\nCRITICAL ERROR DETECTED; program will now terminate\n"); fprintf(log_file, "\nCRITICAL ERROR DETECTED; program will now terminate\n"); } else if (status == ARG_ERROR) { printf("usage:\n"); printf("p2f [-h] [-p ] [-t ] "); printf("\n [-r ]\n "); printf(" \n"); } else if (status == ARG_ERROR_2){ printf("\nMISSING COMMAND LINE ARGUMENT:\n"); printf("usage:\n"); printf("p2f [-h] [-p ] [-t ] "); printf("\n [-r ]\n "); printf(" \n"); } else if (status == SWITCH_ERROR_1){ printf("\nInvalid switch in comand line.\n"); printf("usage:\n"); printf("p2f [-h] [-p ] [-t ] "); printf("\n [-r ]\n "); printf(" \n"); } else if (status == SWITCH_ERROR_2){ printf("\nMissing command line argument after switch.\n"); printf("usage:\n"); printf("p2f [-h] [-p ] [-t ] "); printf("\n [-r ]\n "); printf(" \n"); } else if (status == FORMAT_ERROR) printf("ERROR: FORMAT ERROR: see log file.\n"); else if (status == DATE_ERROR) printf("ERROR: DATE ERROR: see log file.\n"); else if (status == EOF_ERROR){ printf("ERROR: unexpected end of file encountered\n"); fprintf(log_file,"ERROR: unexpected end of file encountered\n"); } else if (status == STD_ERROR){ printf("ERROR: Unable to open Standard Translation Table file.\n"); printf(" Incorrect path or PDS form\n"); } else if (status == FITS_ERROR){ printf( "ERROR: Can't open FITS file!\n" ); } else if (status == TBL_ERROR){ printf( "ERROR: Can't open PDS to FITS Translation file!\n" ); } else if (status == PDS_ERROR){ printf( "ERROR: Can't open PDS label file!\n" ); } else if (status == PDSDD_ERROR){ printf("ERROR: Can't open PDS Data Dictionary file!\n"); } else if (status == INDEX_ERROR){ printf("ERROR: Can't open PDS Data Dictionary index file!\n"); } else if (status == LOG_ERROR){ printf("ERROR: Can't open log file!\n"); } else if (status == RES_ERROR){ printf("ERROR: Can't open Reserved FITS Keyword file!\n"); } else if (status == FITS_LEN_ERROR) { printf("ERROR: bogus FITS keyword found in User Tranlation Table!\n"); printf(" See the log file for details\n"); } else if (status == SWITCH_DESC){ printf("usage:\n"); printf("p2f [-h] [-p ] [-t ] "); printf("\n [-r ]\n "); printf(" \n"); printf("\nexplanation of switches:\n"); printf("\t-h\tprints this message.\n"); printf("\t-p\t is the path to the PDS Data Dictionary.\n"); printf("\t\tIf it is not supplied the PDSDD is assumed to be in the "); printf("\n\t\tdirectory specified by defaults.h.\n"); printf("\t-t\t is the path to the Standard "); printf("\n\t\tTranslation tables. If it is not supplied the"); printf(" Standard \n\t\tTranslation table is assume to be in "); printf("the directory specified\n\t\tby defaults.h.\n"); printf("\t-r\t "); printf("\n\t\tIf it is not supplied the default file name is"); printf(" RES_KEYS.LST.\n"); printf("The switches and optional arguments can appear in any order"); printf(" but, the required arguments must appear in the order shown.\n"); } } /* end print_error */ /****************************************************************************** * Function: make_path * Abstract: builds path to PDS data dictionary and index files. * Input: * path: char string path to dictionary or index. * file: char string name of dictionary or index file. * Output * result: path and file concatenated. ******************************************************************************/ int make_path(char *path, char *file,char *result) { int path_len; /* string length */ path_len = strlen(path); strcpy(result,path); if (result[path_len-1] != '/') strcat(result,"/"); strcat(result,file); return OK; } /* end make_path */ /***************************************************************************** * Function: Nto1 * Abstract: returns 1 if translation string is N to 1 relation * Input * Pstr: holds PDS string from translation table tuple. * Fstr: holds FITS string from translation table tuple. * Return * OK on success ******************************************************************************/ int Nto1(char *Pstr,char *Fstr) { int len; /* string length */ int i; /* index */ int Pflag = 0,Fflag = 0; /* PDS and FITS flags */ /* if Fstr is literal or comment, then abort */ if ((Fstr[0] == '\"')||(Fstr[0] == '#')) return 0; /* get length of PDS string */ len = strlen(Pstr); /* look for '*' in string */ for (i = 0; i < len; i++) if (Pstr[i] == '*') Pflag = 1; /* get length of FITS string */ len = strlen(Fstr); /* look for '*' in string */ for (i = 0; i < len; i++) if (Fstr[i] == '*') Fflag = 1; if (Pflag && !Fflag) return 1; else return 0; }/* end Nto1 */ /***************************************************************************** * Function: one_to_N * Abstract: returns 1 if translation string is 1-to-N relation * Input * Pstr: holds PDS string from translation table tuple. * Fstr: holds FITS string from translation table tuple. * Return * OK on success ******************************************************************************/ int one_to_N(char *Pstr,char *Fstr) { int len; /* string length */ int i; /* index */ int Pflag = 0,Fflag = 0; /* PDS and FITS flags */ /* if Fstr is literal or comment, then abort */ if ((Fstr[0] == '\"')||(Fstr[0] == '#')) return 0; /* get length of PDS string */ len = strlen(Pstr); /* look for '*' in string */ for (i = 0; i < len; i++) if (Pstr[i] == '*') Pflag = 1; /* get length of FITS string */ len = strlen(Fstr); /* look for '*' in string */ for (i = 0; i < len; i++) if (Fstr[i] == '*') Fflag = 1; if (!Pflag && Fflag) return 1; else return 0; }/* end one_to_N */ /***************************************************************************** * Function: NtoN * Abstract: returns 1 if translation string is N to N relation. * Input * Pstr: holds PDS string from translation table tuple. * Fstr: holds FITS string from translation table tuple. * Return * OK on success ******************************************************************************/ int NtoN(char *Pstr,char *Fstr) { int len; /* string length */ int i; /* index */ int Pflag = 0,Fflag = 0; /* PDS and FITS flags */ /* if Fstr is literal or comment, then abort */ if ((Fstr[0] == '\"')||(Fstr[0] == '#')) return 0; /* get length of PDS string */ len = strlen(Pstr); /* look for '*' in PDS string */ for (i = 0; i < len; i++) if (Pstr[i] == '*') Pflag = 1; /* get length of FITS string */ len = strlen(Fstr); /* look for '*' in FITS string */ for (i = 0; i < len; i++) if (Fstr[i] == '*') Fflag = 1; /* if both strings contain * then return TRUE */ if (Pflag && Fflag) return 1; /* else return FALSE */ else return 0; }/* end NtoN */ /********************************************************************** *Function: sub_strcpy *Description: copies source substring, * src[start] .. src[dest_len + start -1], * to dest string. Appends NULL to dest[dest_len]. * dest string must be allocated. * returns 1 for success, -1 for fail. **********************************************************************/ int sub_strcpy(char *dest, char *src, int start,int dest_len) { int i,src_len,max; /* determine max length to aviod reading past end of src string */ src_len = strlen(src); if (src_len < start + dest_len) max = src_len - start; else max = dest_len; /* copy src substring to dest string*/ for (i=0; i < max ;i++) dest[i] = src[i+start]; /* append end of string to dest */ dest[i] = '\0'; return 1; } /********************************************************************** *Function: cpy_to_substr *Description: copies src to substring (dest[start] .. dest[max-1]). * returns 1 for success, -1 for fail. **********************************************************************/ int cpy_to_substr(char *dest, char *src, int start,int max) { int i; /* first check to see if src is long enough */ if (strlen(src) < (max)) return -1; /* copy src substring to dest string*/ for (i = 0; i < max; i++) dest[i+start] = src[i]; return 1; } /* end cpy_to_substr */ /**************************************************************************** * Function: strip_quotes * Abstract: remove surrounding quotes from string. ****************************************************************************/ int strip_quotes(char *str) { int len; len = strlen(str); if ((str[0] == '\"') && (str[len-1] == '\"')) { str[0] = ' '; str[len-1] = ' '; eat_white(str); } return OK; } /* end strip_quotes */ /************************************************************************** * Function: search_PDSDD * Abstract: find_keyword performs binary search of the file pointed to * by *PDSDD, comparing each keyword with target keyword. If * found it copies the corresponding record into the record * buffer and returns the byte offset. If the keyword is not * found it returns -1. * Inputs: * target: search keyword character string. * char *record; buffer to hold target record * Return: line number of target record if it is found, * else returns -1 for error. **************************************************************************/ long search_PDSDD(char *keyword) { long offset; /* offset into PDSDD */ long found; /* offset into index */ char record[100]; /* record from index */ /* search index for keyword, get associated record */ found = search_index(keyword,record); /* if keyword is found, then find it in PDSDD */ if (found != -1L) { /* read in the offset i.e. third column in index file */ strtok(record," "); strtok(NULL," "); offset = atol(strtok(NULL," ")); /* now move cursor to that offset */ fseek(PDSDD,offset,0); } /* if keyword not found then return -1 */ else offset = -1L; return offset; } /* end search_PDSDD */ /************************************************************************** * Function: search_index * Abstract: find_keyword performs binary search of the file pointed to * by *infile, comparing each keyword with target keyword. If * found it copies the corresponding record into the record * buffer. * Input: * target: search keyword character string. * record: buffer to hold target record * Return: * line number of target record if it found, else returns -1 for error. **************************************************************************/ long search_index(char *target,char *record) { /* variable declarations */ long flen = 0L; /* file size */ long start = 0L; /* first record in index */ long low,mid,high; /* used for binary search */ long bytes; /* offset of search record */ long line_num; /* line number */ char keyword[35]; /* PDS keyword string */ int found = FALSE; /* TRUE when found */ int cmp; /* result of string compare */ /* first read past header */ fgets(record,100,index_file); sscanf(record,"%s",keyword); while (strcmp(keyword,"END")){ fgets(record,100,index_file); sscanf(record,"%s",keyword); } start = ftell(index_file); /* start marks first record */ flen = fsize(index_file); /* find file size */ low = start; /* low and high used for binary search */ high = flen; /* perform binary search */ while ( (low <= high) && (found == FALSE)) { fseek(index_file,low,0);/* set file cursor to low */ mid = (floor((high - low)/160))*80; /* mid marks first byte of record midway between low and high */ fseek(index_file,mid,1); /* set cursor to mid */ fgets(record,100,index_file); /* read that record into buffer */ sscanf(record,"%s",keyword); /* get keyword from record */ cmp = strcmp(target,keyword);/* compare that keyword against target */ if (cmp > 0) /* target is lexically greater */ low = low + mid + 80L; /* so update low to mid */ else if (cmp < 0) /* target is lexically smaller */ high = low + mid -1L; /* so update high to mid */ else { found = TRUE; /* target is found! (much rejoiceing) */ bytes = ftell(index_file); /* bytes marks first byte of record */ } } line_num = bytes/80L; /* calculate line number */ rewind(index_file); /* rewind cursor */ if (found == TRUE) return line_num; /* if found return line number */ else return -1L; /* else return -1 */ } /***************************************************************************** * Function: get_PDS_type * Abstract: gets the required PDS keywords and objects from the PDSDD * Inputs * required_key: array of required PDS keyword name character strings. * required obj: array of required PDS object name character strings. * Returns * OK on success *****************************************************************************/ int get_PDS_type(char *type) { char record[100]; /* PDSDD record buffer */ char string[35]; /* string buffer */ char *ptr; int done = FALSE; fgets(record,100,PDSDD); sscanf(record,"%s",string); while ((strcmp(string,"END_OBJECT") != 0)&& (done == FALSE)) { fgets(record,100,PDSDD); sscanf(record,"%s",string); if (strcmp(string,"GENERAL_DATA_TYPE") == 0){ ptr = strtok(record,"="); ptr = strtok(NULL,"="); strcpy(type,eat_white(ptr)); done = TRUE; } } return 1; }/* end get_required */ /*************************************************************************** * Function: fsize * Abstract: used to find size of file in bytes * Input: FILE *file; pointer to file opened by fopen * Output: returns size of file in bytes ***************************************************************************/ long fsize(FILE *file) { long saved_fpos; /* saved file position */ long file_size; /* file size */ if (file == NULL) { /* error */ return -1L; } saved_fpos = ftell(file); /* save current position of file cursor */ if (fseek(file, 0L, 2) == -1) /* move cursor to end of file */ return -1L; /* -1 indicates error */ file_size = ftell(file); /* get current position of cursor */ /* this is size of file */ fseek(file, saved_fpos, 0); /* rewind cursor */ return file_size; /* return file size */ } /* end fsize */ /********************************************************************** *Function: p2f_date *Abstract: convets PDS DATE to FITS DATE format. * Input * date: holds PDS date string * Output * pds_date: holds FITS date string. * Return * OK on success **********************************************************************/ int p2f_date(char *date,char *fits_date) { char *str; /* pointer to token */ char temp[26]; /* holds date string */ int YY, MM, DD, len; /* year, month, day string */ strcpy(temp,date); if ((temp[0] == '\"') || (temp[0] == '\'')){ len = strlen(temp); temp[0] = ' '; temp[len-1] = ' '; eat_white(temp); } /* check if already in correct format */ if ((temp[2] == '/') && (temp[5] == '/')){ strcpy(fits_date,date); return OK; } /* Convert FITS date into three integers */ str = strtok(temp, "-"); YY = atoi( str ); YY -= 1900; if (YY > 99) return DATE_ERROR; str = strtok( NULL, "-"); MM = atoi( str ); if ((MM != 99)&&(MM > 12)) return DATE_ERROR; str = strtok( NULL, "-"); DD = atoi( str ); if ((DD != 99) && (DD > 31)) return DATE_ERROR; /* Build up DateString */ sprintf( fits_date, "\'%02d/%02d/%02d\'", DD, MM, YY); return OK; } /* end p2f_date */ /********************************************************************** *Function: p2f_time *Abstract: convets PDS TIME to FITS fraction of day format. * Input * date: holds PDS time string * Output * pds_date: holds FITS time string. * Return * OK on success **********************************************************************/ int p2f_time(char *pds_time,char *fits_time) { int len; float hh; float mm; float ss; float day_frac; len = strlen(pds_time); if (pds_time[len-1] == 'Z') pds_time[len-1] = '\0'; hh = atof(strtok(pds_time,":")); mm = atof(strtok(NULL,":")); ss = atof(strtok(NULL,":")); day_frac = (hh*3600.0 + mm*60.0 + ss)/86400.0; sprintf(fits_time,"%f",day_frac); return OK; } /* end p2f_time */ /********************************************************************** *Function: check_length *Abstract: convets PDS TIME to FITS TIME format. * Input * date: holds PDS time string * Output * pds_date: holds FITS time string. * Return * OK on success **********************************************************************/ int check_length(char *FITS_string) { char local[20]; char key[20]; char *ptr1; char *ptr2; strcpy(local,FITS_string); ptr1 = strtok(local,"."); ptr2 = strtok(NULL,"."); if (ptr2 == NULL) strcpy(key,ptr1); else strcpy(key,ptr2); if (strlen(key) > 8) return FALSE; return TRUE; } /* end check_length */