/************************************************************************** * File: pds.c * Programmers: Anne Raugh * Dorian Winterfeld * Institution: PDS/Small Bodies Node * University of Maryland * Date: Feb. 13, 1995 * Abstract: Function implementations for PDS utilities. * Description: This file contains functions for reading in the PDS * label and building the FITS header object. ***************************************************************************/ #include #include #include #include #include "pds.h" #include "fits_obj.h" #include "pds_tbl.h" #include "pdserror.h" #include "pds_util.h" #include "linklist.h" /* global variables */ extern FILE *PDS_file; extern FILE *log_file; /************************************************************************** * Function: read_PDS_file * Abstract: Routine to step through the PDS label records and assign the * appropriate value strings the the FITS structure elements. * * Description: As each line is read, it is first broken into PDS keyword string * and value string. The PDS object type is prepended onto the keyword, * except for the implicit FILE object. A search is made of the translation * table to match this name exactly. A warning is issued if the keyword is * not matched; otherwise the value string is then assigned * to all appropriate FITS elements. Certain values are stored for * calculated FITS fields such as NAXIS. * Input * main_object: pointer to FITS object. * * Return * 1 on success, 0 on failure. ***************************************************************************/ int read_PDS_file(FITS_object *main_object,table *ttable,table *ltable) { char line[100]; /* holds a line from a PDS label */ char test_buf[100]; /* used for testing */ char object_path[100]; /* PDS object path */ char type[20]; /* keyword data type */ char key[100]; /* PDS keyword */ char key_str[200]; /* full keyword string; includes path */ char value[10000]; /* PDS value string */ int first = TRUE; /* first object encountered */ int len; int status = OK; int i; table_element *entry; list_type *object_list; /*keeps track of PDS objects */ object_list = list_create(); object_path[0] = '\0'; skip_blanks(PDS_file,line); status = split_pds_line(line,key,value); /* loop thru PDS file */ while (strcmp(key,"END")) { /* look for OBJECT and build object path */ if (strcmp(key,"OBJECT") == 0 ) { if (first == TRUE){ strcpy(object_path,value); strcat(object_path,"."); first = FALSE; } else { strcat(object_path,value); strcat(object_path,"."); } insert(object_list,value); } else /* look for END_OBJECT and pop object path */ if (strcmp(key,"END_OBJECT") == 0){ i = strlen(object_path) - 2; while ((object_path[i] != '.') && (i > 0)) i--; object_path[i] = '\0'; if (i > 0) strcat(object_path,"."); } else /* look for NOTE or DESCRIPTION */ if ((strcmp(key,"NOTE") == 0) || (strcmp(key,"DESCRIPTION") == 0)) { if (strcmp(value,"\"") == 0){ fgets(line,100,PDS_file); strcpy(test_buf,line); eat_white(test_buf); len = strlen(test_buf); strcpy(value,line); strcat(value,"\n"); } else { strcpy(test_buf,line); eat_white(test_buf); len = strlen(test_buf); strcat(value,"\n"); } while (test_buf[len-1] != '\"'){ fgets(line,101,PDS_file); strcpy(test_buf,line); eat_white(test_buf); len = strlen(test_buf); strcat(value,line); strcat(value,"\n"); } } /* build key string */ if (object_path[0] == '\0') strcpy(key_str,key); else { strcpy(key_str,object_path); strcat(key_str,key); } /* search translation table for key string */ entry = find_pds_keyword(ttable,key_str,NULL); /* if key found then set value else add to log file */ if (entry == NULL) fprintf(log_file,"%s\n",key_str); else { if (!strcmp(entry->FITS_type,"NULL")){ search_PDSDD(key); get_PDS_type(type); } else strcpy(type,entry->FITS_type); set_value(value,type,entry,object_list,main_object); } /* fetch next line */ skip_blanks(PDS_file,line); status = split_pds_line(line,key,value); if (status <= ERROR) return status; } /* end while loop */ /* add literal table values */ add_lit_table(main_object,ltable); /* now add calculated fields for specific object type */ post_process(main_object,ttable); return status; } /* end read_PDS */ /************************************************************************** * Function: find_pds_keyword * Abstract: Routine to search the internal translation table for a given * PDS keyord. * Description: This routine attempts to find a matching translation table entry * for the given key. * The table is assumed to be sorted in alphabetic order. First attempt is * to match exactly. Failing that the search is repeated with "[*]" after * every object in the pds key string. If the no match is found then * return NULL * Input * ttable pointer to translation table * key PDS keyword string * start_here pointer to start element in table * Return * table_element pointer to table element ***************************************************************************/ table_element *find_pds_keyword(table *ttable,char *key, table_element *start_here) { table_element *entry; char object_str2[100]; char modified_key[100]; int len; int dots[10]; int i; int dot_cnt = 0; /* Exact match search: */ if (start_here == NULL) entry = ttable->elements; else entry = start_here; while (entry != NULL) { if (strcmp(entry->PDS_string,key) == 0) return entry; else entry = entry->next; } /* If you made it this far, no success. Try again with wildcard "*" */ /* parse PDS string into individual objects and store in linllist*/ len = strlen(key); for (i=0; ielements; else entry = start_here; while (entry != NULL) { if (strcmp(entry->PDS_string,modified_key) == 0) return entry; else entry = entry->next; } } /* Still no success: */ return NULL; } /* end find_pds_keyword */ /************************************************************************** * Function: set_value * Abstract: Routine to assign the value string to the appropriate FITS keyword. * Objects and keywords are created on the fly as they are needed. * Description: * Input * Return ***************************************************************************/ int set_value(char *value, char *type,table_element *entry, list_type *object_list, FITS_object *main_object) { int N = 1; char N_string[4]; int i; int len; int object_cnt; char obj_cnt_str[5]; char value_copy[100]; char PDS_copy[100]; char *element; char *object1; char *object2; char *object; char modified_string[100]; int found = FALSE; FITS_keyword *FITSkey; list_type *element_list; list_node *node; /* Determine if this is a 1->* relation */ if (one_to_N(entry->PDS_string,entry->FITS_string)) { element_list = list_create(); strcpy(value_copy,value); eat_white(value_copy); if (value_copy[0] == '{'){ len = strlen(value_copy); value_copy[0] = ' '; value_copy[len-1] = ' '; eat_white(value_copy); } element = strtok(value_copy,","); while (element != NULL) { insert(element_list,element); element = strtok(NULL,","); } node = element_list->head; while (node != NULL) { strcpy(modified_string,entry->FITS_string); len = strlen(modified_string); modified_string[len-1] = '\0'; sprintf(N_string,"%d",N); strcat(modified_string,N_string); FITSkey = find_FITS_keyword(modified_string,main_object); len = strlen(node->data); FITSkey->value = (char *)malloc(len + 1); if (FITSkey->value == NULL) return MALLOC_ERROR; strcpy(FITSkey->value,node->data); strcpy(FITSkey->type,type); N++; node = node->next; } } else /* Determine if this is a *->* relation */ if (NtoN(entry->PDS_string,entry->FITS_string)) { /* first find PDS object containing "[*]" from PDS key string*/ strcpy(PDS_copy,entry->PDS_string); object1 = strtok(PDS_copy,"."); while (found == FALSE) { object2 = object1; len = strlen(object1); for (i=0;iFITS_string); strtok(modified_string,"*"); strcat(modified_string,obj_cnt_str); FITSkey = find_FITS_keyword(modified_string,main_object); len = strlen(value); FITSkey->value = (char *)malloc(len + 1); if (FITSkey->value == NULL) return MALLOC_ERROR; strcpy(FITSkey->value,value); strcpy(FITSkey->type,type); } else { /* must be a 1->1 relation */ FITSkey = find_FITS_keyword(entry->FITS_string, main_object); len = strlen(value); FITSkey->value = (char *)malloc(len + 1); if (FITSkey->value == NULL) return MALLOC_ERROR; strncpy(FITSkey->value,value,len+1); strcpy(FITSkey->type,type); } return OK; } /* end set_value */ /************************************************************************** * Function: find_FITS_keyword * Abstract: Workhorse routine to locate a specific keyword and extension, * if one exists. * Description: * Input * Return ***************************************************************************/ FITS_keyword *find_FITS_keyword(char *key, FITS_object *object) { char *ext_ptr; char *key_ptr; FITS_keyword *keyword_ptr; FITS_object *extension_ptr; char key_copy[100]; /* SPLIT key into extension and keyword */ strcpy(key_copy,key); ext_ptr = strtok(key_copy,"."); key_ptr = strtok(NULL,"."); if (key_ptr == NULL) keyword_ptr = find_keyword_in_object(key,object); else { extension_ptr = find_extension_in_object(ext_ptr,object); keyword_ptr = find_keyword_in_object(key_ptr,extension_ptr); } return keyword_ptr; } /* end find_FITS_keyword */ /************************************************************************** * Function: find_extension_in_object * Abstract: Routine to find a given extension object given the main header * object. If it is not found, it is created. * Description: * Input * Return ***************************************************************************/ FITS_object *find_extension_in_object(char *extension,FITS_object *object) { FITS_object *ext_obj; ext_obj = object->next; while (ext_obj != NULL) { if (strcmp(ext_obj->name,extension) == 0) return ext_obj; ext_obj = ext_obj->next; } /* Not found. Create it: */ ext_obj = create_FITS_object(extension, object); return ext_obj; } /* end find_extension_in_object */ /************************************************************************** * Function: find_keyword_in_object * Abstract: Routine to find a given keyword in the given object. If the * keyword is not found, it is created. * Description: * Input * Return ***************************************************************************/ FITS_keyword *find_keyword_in_object(char *keyword,FITS_object *object) { FITS_keyword *key; key = object->keyword_list; while (key != NULL) { if (strcmp(key->name,keyword) == 0) return key; key = key->next; } /* Not found. Create it: */ key = create_FITS_keyword(keyword, object); return key; } /* end find_keyword_in_object */ /**************************************************************************** * Function: how_many_objects * Abstract: counts number of ****************************************************************************/ int how_many_objects(list_type *object_list,char *object) { list_node *node_ptr; int object_cnt = 0; node_ptr = object_list->head; while (node_ptr != NULL) { if (strcmp(node_ptr->data,object) == 0) object_cnt++; node_ptr = node_ptr->next; } return object_cnt; } /* end how_many_objects */ /***************************************************************************** * Function: add_lit_table * Abstract: add the keywords from the literal table to the FITS objects. * Input * ltable: literal table pointer. * main_object: pointer to main FITS object. *****************************************************************************/ int add_lit_table(FITS_object *main_object,table *ltable) { table_element *entry; /* pointer to table element object */ char *value; /* value string */ FITS_keyword *FITSkey; /* pointer to FITS keyword */ int len; /* start at beginning of literal table */ entry = ltable->elements; while (entry != NULL){ /* get the PDS value string */ value = entry->PDS_string; /* remove the quotes */ strip_quotes(value); /* set the value field of the corresponding FITS object */ FITSkey = find_FITS_keyword(entry->FITS_string, main_object); len = strlen(value); FITSkey->value = (char *)malloc(len + 1); if (FITSkey->value == NULL) return MALLOC_ERROR; strcpy(FITSkey->value,value); strcpy(FITSkey->type,"LIT_STR"); entry = entry->next; } return OK; } /* end add_lit_table */ /***************************************************************************** * Function: post_process * Abstract: * Input * *****************************************************************************/ int post_process(FITS_object *main, table *ttable) { if (!strcmp(ttable->PDS_form,"BINARY_TABLE")) process_binary_table(main); else if (!strcmp(ttable->PDS_form,"ASCII_TABLE")) process_ascii_table(main); return OK; } /* end post_process */ /***************************************************************************** * Function: process_binary_table * Abstract: calculate TFORMn value for each column * Input * *****************************************************************************/ int process_binary_table(FITS_object *main) { FITS_object *sub_obj; /* PDS object pointer */ FITS_keyword *key_ptr; /* PDS keyword object pointer */ char dtype[20]; char bytes[20]; char tform[20]; char dtype_val[20]; char data_type[3]; char index[4]; char tform_val[5]; char items[6]; char ibytes[3]; int tfields; int byte_cnt = 0; /* bytes in data type */ int bytes_val = 0; /* value of dummy key BYTES */ int items_val = 0; /* value of dummy key ITEMS */ int ibytes_val = 0; int i; /* goto first suboject list */ sub_obj = main->next; /* Find Column object list */ while (strcmp(sub_obj->name,"BINTABLE") != 0){ sub_obj = sub_obj->next; } /* search for TFIELDS keyword */ key_ptr = find_FITS_keyword("TFIELDS",sub_obj); tfields = atoi(key_ptr->value); for (i=1; i <= tfields; i++) { /* search for DTYPE keyword (it's a dummy) */ sprintf(index,"%d",i); strcpy(dtype,"DTYPE"); strcat(dtype,index); key_ptr = find_FITS_keyword(dtype,sub_obj); strcpy(dtype_val,key_ptr->value); strip_quotes(dtype_val); /* search for BYTES keyword (it's a dummy, too) */ strcpy(bytes,"BYTES"); strcat(bytes,index); key_ptr = find_FITS_keyword(bytes,sub_obj); bytes_val = atoi(key_ptr->value); /* search for ITEMS keyword (it's a dummy, too) */ strcpy(items,"ITEMS"); strcat(items,index); key_ptr = find_FITS_keyword(items,sub_obj); if (key_ptr->value) { items_val = atoi(key_ptr->value); /* search for IBYTES keyword (it's a dummy, too) */ strcpy(ibytes,"IBYTES"); strcat(ibytes,index); key_ptr = find_FITS_keyword(ibytes,sub_obj); if (key_ptr->value) ibytes_val = atoi(key_ptr->value); } /* calculate TFORMn (it's required) */ if (!strcmp(dtype_val,"LOGICAL")){ strcpy(data_type,"L"); byte_cnt = 1; } else if (!strcmp(dtype_val,"MSB_BIT_STRING") || !strcmp(dtype_val,"BIT")){ strcpy(data_type,"X"); byte_cnt = 1; } else if (!strcmp(dtype_val,"CHARACTER")){ strcpy(data_type,"A"); byte_cnt = 1; } else if (!strcmp(dtype_val,"BYTE")){ strcpy(data_type,"B"); byte_cnt = 1; } else if (!strcmp(dtype_val,"MSB_INTEGER")|| !strcmp(dtype_val,"INTEGER")){ if (items_val == 0) byte_cnt = bytes_val; else byte_cnt = ibytes_val; if (byte_cnt == 1) strcpy(data_type,"B"); else if (byte_cnt == 2) strcpy(data_type,"I"); else if (byte_cnt == 4) strcpy(data_type,"J"); } else if (!strcmp(dtype_val,"FLOAT") || !strcmp(dtype_val,"IEEE_REAL")){ if (items_val == 0) byte_cnt = bytes_val; else byte_cnt = ibytes_val; if (byte_cnt == 4) strcpy(data_type,"E"); else if (byte_cnt == 8) strcpy(data_type,"D"); } else if (!strcmp(dtype_val,"COMPLEX") || !strcmp(dtype_val,"IEEE_COMPLEX")){ strcpy(data_type,"C"); byte_cnt = 8; } sprintf(tform_val,"%d",bytes_val/byte_cnt); strcat(tform_val,data_type); /* create TFORM keyword */ strcpy(tform,"TFORM"); strcat(tform,index); key_ptr = find_FITS_keyword(tform,sub_obj); if ((key_ptr->value = (char *)malloc(6)) == NULL) return MALLOC_ERROR; strcpy(key_ptr->value,tform_val); strcpy(key_ptr->type,"CHARACTER"); } return OK; } /* end process_binary_table */ /***************************************************************************** * Function: process_ascii_table * Abstract: calculate TFORMn value for each column * Input * *****************************************************************************/ int process_ascii_table(FITS_object *main) { FITS_object *sub_obj; /* PDS object pointer */ FITS_keyword *key_ptr; /* PDS keyword object pointer */ char dtype[20]; char bytes[20]; char tform[20]; char dtype_val[20]; char data_type[3]; char index[4]; char tform_val[5]; char items[6]; char ibytes[3]; char tform_num[10]; int tfields; int byte_cnt = 0; /* bytes in data type */ int bytes_val = 0; /* value of dummy key BYTES */ int items_val = 0; /* value of dummy key ITEMS */ int ibytes_val = 0; int i; /* goto first suboject list */ sub_obj = main->next; /* Find Column object list */ while (strcmp(sub_obj->name,"TABLE") != 0){ sub_obj = sub_obj->next; } /* search for TFIELDS keyword */ key_ptr = find_FITS_keyword("TFIELDS",sub_obj); tfields = atoi(key_ptr->value); for (i=1; i <= tfields; i++) { /* search for DTYPE keyword (it's a dummy) */ sprintf(index,"%d",i); strcpy(dtype,"DTYPE"); strcat(dtype,index); key_ptr = find_FITS_keyword(dtype,sub_obj); strcpy(dtype_val,key_ptr->value); strip_quotes(dtype_val); /* search for BYTES keyword (it's a dummy, too) */ strcpy(bytes,"BYTES"); strcat(bytes,index); key_ptr = find_FITS_keyword(bytes,sub_obj); bytes_val = atoi(key_ptr->value); /* search for ITEMS keyword (it's a dummy, too) */ strcpy(items,"ITEMS"); strcat(items,index); key_ptr = find_FITS_keyword(items,sub_obj); if (key_ptr->value) { items_val = atoi(key_ptr->value); /* search for IBYTES keyword (it's a dummy, too) */ strcpy(ibytes,"IBYTES"); strcat(ibytes,index); key_ptr = find_FITS_keyword(ibytes,sub_obj); if (key_ptr->value) ibytes_val = atoi(key_ptr->value); } /* calculate TFORMn (it's required) */ if (!strcmp(dtype_val,"CHARACTER") || !strcmp(dtype_val,"BYTE")){ strcpy(data_type,"A"); byte_cnt = 1; } else if (!strcmp(dtype_val,"ASCII_INTEGER")|| !strcmp(dtype_val,"INTEGER")){ if (items_val == 0) byte_cnt = bytes_val; else byte_cnt = ibytes_val; strcpy(data_type,"I"); } else if (!strcmp(dtype_val,"FLOAT") || !strcmp(dtype_val,"ASCII_REAL")){ if (items_val == 0) byte_cnt = bytes_val; else byte_cnt = ibytes_val; if (byte_cnt == 4) strcpy(data_type,"E"); else if (byte_cnt == 8) strcpy(data_type,"D"); } strcpy(tform_val,data_type); sprintf(tform_num,"%d",bytes_val/byte_cnt); strcat(tform_val,tform_num); /* create TFORM keyword */ strcpy(tform,"TFORM"); strcat(tform,index); key_ptr = find_FITS_keyword(tform,sub_obj); if ((key_ptr->value = (char *)malloc(6)) == NULL) return MALLOC_ERROR; strcpy(key_ptr->value,tform_val); strcpy(key_ptr->type,"CHARACTER"); } return OK; } /* end process_ascii_table */