/************************************************************************** * File: pds_tbl.c * Programmer: Dorian winterfeld * Anne Raugh * Institution: PDS/Small Bodies Node * University of Maryland * Date: March 15, 1995 * Last revision: * Abstract: All functions relating to the translation table. * Description: These functions are used to build up an "internal" * table by combining the User Translation table and the * Standard Translation table indicated by the first line * of the User table. **************************************************************************/ #include #include #include #include "pds_tbl.h" #include "pds_util.h" #include "pdserror.h" #include "linklist.h" #include "defaults.h" extern FILE *table_file; extern FILE *log_file; /************************************************************************** * Function: init_table * Abstract: initialize the table by setting element to NULL. * Inputs * tbl_ptr: pointer to table to be initialized. * Returns * pointer to table input table. ***************************************************************************/ table *init_table(table *tbl_ptr) { if((tbl_ptr = (table *)malloc(sizeof(table))) == NULL) return NULL; tbl_ptr->elements = NULL; return tbl_ptr; } /* end init_table */ /************************************************************************** *Function: read_table *Description: Routine to read in the user defined translation file and * combine it with the predefined translation table. * Returns 1 for success and 0 otherwise. *Inputs * ltable: pointer to translation table of literal values. * ttable: pointer to translation table of keywords. *Outputs * ptr_array: Array of character strings used in SERIES_IMAGES to store array * of image names. * std_path: char string which holds path to the Standard Tranlation Table *Returns * 1 for success; error code for failure. ***************************************************************************/ int read_table(table *ltable, table *ttable, char *std_path, list_type *reserved_list) { char line_buffer[100]; /* table line buffer */ int add = 0; /* flag indicates if tuple is addition */ int status = OK; /* error flag */ /* first check user table for reserved keywords */ check_table(table_file,reserved_list); /* reset cursor to begining of file */ fseek(table_file,0,0); /* skip over comments and blank lines */ if(skip_lines(table_file,line_buffer) <= 0) return ERROR; /* First non-comment line of file defines the type of FITS and PDS files descibed in the translation file. These are stored in the ttable */ status = split_line(line_buffer, ttable->PDS_form, ttable->FITS_form, NULL, &add); /* Also store file types in the literal table */ status = split_line(line_buffer, ltable->PDS_form,ltable->FITS_form, NULL,&add); /* Now load tables with predefined table */ status = setup_predefined(ltable,ttable,std_path); if (status < 1) return status; /* Now load literal and translation tables with user supplied file */ status = load_table(table_file,ltable,ttable); return status; } /* end read_table */ /************************************************************************** * Function:check_table * Abstract: * Inputs * Output * Return ***************************************************************************/ void check_table(FILE *tbl,list_type *reserved_list) { char Fstr[20]; char Fkey[9]; char *key_ptr; char Pstr[50]; char line[100]; char Ftype[20]; int add; list_node *node_ptr; while (skip_lines(tbl,line)) { /* split into PDS and FITS keywords */ split_line(line,Pstr,Fstr,Ftype,&add); key_ptr = strtok(Fstr,"."); key_ptr = strtok(NULL,"."); if (key_ptr != NULL) strcpy(Fkey,key_ptr); else strcpy(Fkey,Fstr); node_ptr = reserved_list->head; while (node_ptr != NULL){ if (strcmp(node_ptr->data,Fkey) == 0) fprintf(log_file,"WARNING: FITS keyword %s is a reserved keyword\n", Fstr); node_ptr = node_ptr->next; } } } /* end check_table */ /************************************************************************** * Function: skip_lines * Abstract: skips past comments,begining with '#' ,or blank lines. * if EndOfFile is encountered, return NULL. * Inputs * fptr: pointer to translation table. * Output * line: Character string which holds 80 char record from table. * Return * 1 for success; error code for failure. ***************************************************************************/ int skip_lines(FILE *fptr, char *line) { if (!fgets(line,100,fptr)) return 0; while((line[0] == '#')||(line[0] == ' ')||(strlen(line) == 1)) if (!fgets(line,100,fptr)) return 0; return 1; } /* end skip_lines */ /************************************************************************** * Function: split_line * Abstract: splits input string into two strings. * Description: Splits line into two strings using "=" as a delimeter. The * PDS string, the left string, is checked is checked for "+", * indictaeing an addition to previous definitions, and * or a literal prefix and/or suffix. The FITS string is checked * for an explicit datatype. * Inputs * line: Character string; holds record from translation table. * Outputs * Pstring: Character string; holds PDS keyword string * Fstring: Character string; holds FITS keyword string * pre_string: Character string; holds literal prefix to FITS keyword * post_string: Character string; holds literal suffix to FITS keyword * pre: pointer to interger flag; TRUE if prefix string exists. * post: pointer to interger flag; TRUE if suffix string exists. * add: pointer to interger flag; TRUE if tuple is addition to previous * definition. * Returns * TRUE for success; otherwise, error code. ***************************************************************************/ int split_line(char *line, char *Pstring, char *Fstring, char *Ftype, int *add) { static char local[100]; /* table line buffer */ char *Pstr,*Fstr; /* PDS and FITS substring pointers */ char *ptr; int Plen; /* length of strings*/ int status = OK; /* error status */ strcpy(local,line); /* split line into PDS and FITS substrings strings and get thier lengths */ Pstr = strtok(local,"="); Fstr = strtok(NULL,"="); Plen = strlen(Pstr); /* check to see if PDS keyword is an addition to previous definition */ if (Pstr[Plen-1] == '+') { *add = 1; Pstr[Plen-1] = ' '; } else *add = 0; /* copy PDS string */ strcpy(Pstring,Pstr); eat_white(Pstring); /* remove comments from FITS string */ strtok(Fstr,"#"); /* look for explicit FITS datatype */ ptr = strtok(Fstr,"("); ptr = strtok(NULL,"("); if (ptr){ strcpy(Ftype,ptr); strtok(Ftype,")"); } else if (Ftype) strcpy(Ftype,"NULL"); /* copy FITS string */ strcpy(Fstring,Fstr); eat_white(Fstring); /* error check */ if (!strlen(Pstring) || !strlen(Fstring)) status = SYNTAX_WARNING; return status; } /* end split_line */ /************************************************************************** * Function: setup_predefined * Abstract: add predefined translation table to program translation table. * Inputs * ltable: pointer to literal table. * ttable: pointer to translation table. * path: Char string; path to Standard Translation table. ***************************************************************************/ int setup_predefined(table *ltable,table *ttable,char *path) { char buffer[100]; /* table line buffer */ FILE *std_file; /* pointer to Standard translation table */ int status = OK; if (path == NULL) make_path(STD_PATH,ttable->PDS_form,buffer); else make_path(path,ttable->PDS_form,buffer); strcat(buffer,".std"); if ((std_file = fopen(buffer,"r")) == NULL) return STD_ERROR; status = load_table(std_file,ltable,ttable); return status; } /* setup_predefined */ /************************************************************************** * Function: load_table * Abstract: reads through user supplied translation table and adds all * translation PDS/FITS pairs to program translation table. * Inputs * tbl: Pointer to translation table file. * ltable: pointer to literal table. * ttable: pointer to translation table. * Return * OK for success, error code otherwise. **************************************************************************/ int load_table(FILE *tbl,table *ltable, table *ttable) { char line[100]; /* table line buffer */ table_element *element; /* pointer to table element object */ int add = 0;/* add: condition flag for translation tuple */ /* 0 for replacement, 1 for addition */ while (skip_lines(tbl,line)) { /* make new element */ element = (table_element *)malloc(sizeof(table_element)); /* split into PDS and FITS keywords */ split_line(line,element->PDS_string,element->FITS_string, element->FITS_type,&add); /* if FITS string is literal, skip it */ if (element->FITS_string[0] != '\"'){ /* if FITS keyword has more than eight char then WARNING */ if (!check_length(element->FITS_string)){ fprintf(log_file,"WARNING: FITS keyword %s in Translation Table ", element->FITS_string); fprintf(log_file,"is too long!\n"); } /* if PDS string is literal, then add to literal table */ if (literal_value(element->PDS_string)) link_elements(ltable,element,add); else /* add to main translation table */ link_elements(ttable,element,add); } } return 1; } /* end load_table */ /************************************************************************** * Function: link_elments * Abstract: Routine to link the new element into the table. Elements are * sorted alphabetically (i.e. by ASCII code). * Inputs * tbl_ptr: pointer to table. * newone: pointer to new table element. * add: Integer flag; if add is false, then supercede previous definitions. * Return * 1 for success, error code otherwise. **************************************************************************/ int link_elements(table *tbl_ptr,table_element *newone, int add) { table_element *next_one; /* pointer to next table element object */ table_element *last_one; /* pointer to last table element object */ table_element *curr_one; /* pointer to current table element object */ /* check for bogus parameters */ if (!tbl_ptr || !newone) return 0; /* if add is false, then search and delete duplicate nodes */ if ((add == 0) && (tbl_ptr->elements != NULL)){ /* first node is special case */ while (strcmp(newone->PDS_string,tbl_ptr->elements->PDS_string) == 0){ curr_one = tbl_ptr->elements; tbl_ptr->elements = tbl_ptr->elements->next; free(curr_one); } /* check the middle nodes */ last_one = tbl_ptr->elements; curr_one = last_one->next; if (curr_one != NULL) next_one = curr_one->next; while (curr_one != NULL) { if(strcmp(newone->PDS_string,curr_one->PDS_string) == 0){ last_one->next = next_one; free(curr_one); curr_one = last_one; } last_one = curr_one; curr_one = last_one->next; if (curr_one != NULL) next_one = curr_one->next; } }; /* First check for first element */ if (tbl_ptr->elements == NULL){ tbl_ptr->elements = newone; newone->next = NULL; return 1; } /* Find insertion point (beginning of list is special case )*/ if(strcmp(newone->FITS_string,tbl_ptr->elements->FITS_string) <= 0){ newone->next = tbl_ptr->elements; tbl_ptr->elements = newone; return 1; } last_one = tbl_ptr->elements; next_one = last_one->next; while (next_one) { if(strcmp(newone->FITS_string,next_one->FITS_string) <= 0){ newone->next = next_one; last_one->next = newone; return 1; } last_one = next_one; next_one = last_one->next; } /* if you got here newone gets added to end of list */ last_one->next = newone; newone->next = NULL; return 1; } /* end link_element */ /***************************************************************************** * Function: literal_string * Abstract: returns 1 of string is a literal (in matching quotes), else 0. * Inputs * string: char string to be tested. * Returns * TRUE if "string" is in quotes, FALSE otherwise. ****************************************************************************/ int literal_value(char *string) { int len; /* string length */ /* get length of string */ len = strlen(string); /* if first and last character are quotes then return 1 */ if ((string[0] == '\"') && (string[len-1] == '\"')) return 1; /* not a literal, return 0 */ return 0; } /* end literal_string */ /***************************************************************************** * Function: print_table * Abstract: writes table to screen in PDS = FITS format * Inputs * out_file: pointer to output file. * tbl: pointer to translation table. ****************************************************************************/ void print_table(FILE *out_file,table *tbl) { table_element *element; /* pointer to table element object */ fprintf(out_file,"%-30s = %-30s\n\n",tbl->PDS_form,tbl->FITS_form); element = tbl->elements; while (element != NULL){ fprintf(out_file,"%-30s = %-30s\n",element->PDS_string, element->FITS_string); element = element->next; } } /* print_table */