/*========================================================================*/ /* */ /* PDS Label Library Lite */ /* (lablib3) */ /* */ /* Version: */ /* */ /* 1.0Beta Mar 31, 1994 */ /* 1.0 Jan 23, 1995 */ /* 1.1 Feb 23, 1995 */ /* 1.2 Jun 06, 1995 Preliminary */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* 01-09-95 jsh - Changed OBJECT to OBJDESC */ /* 01-09-95 jsh - Corrected strcmp and strncmp == NULL */ /* 02-16-95 jsh - Applied LASP changes (from OA dvlp - s. monk) */ /* - Function Prototypes */ /* - Filename Units */ /* - Filename for SUN/Unix */ /* - TB_MAX_BUFFER */ /* - Several 0 -> NULL in function calls */ /* 02-20-95 jsh - Added OdlPrintLine (reduced # fprintf) */ /* 06-06-95 jsh/gmw - Allow SFDU without "= SFDU" */ /* 06-06-95 jsh/gmw - Stop gap for "/*" in text strings */ /* 06-12-02 saa - Make OdlGetFileSpec return "fspec" when */ /* "orig_fspec" does not contain any "/" (instead */ /* of "orig_fspec" which it currently returns) */ /* 03-06-03 saa - OdlValidElement overwrote out of bounds memory */ /* when a value with inline units was specified */ /* with no spaces inbetween, such as: */ /* INSTRUMENT_FOV = 20 */ /* */ /*========================================================================*/ #include "header.h" #include "io_lablib3.h" #ifdef _WINDOWS #include "system.h" #else #include #endif long odl_message_count = {0}; short odl_suppress_messages = {TRUE}; char * find_file(char *fname); /*========================================================================*/ /* */ /* Label Parse routines */ /* */ /*========================================================================*/ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlParseLabelFile */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine causes a file containing a PDS label to be parsed */ /* and its "^" keywords expanded. It returns a pointer to the */ /* root of the OBJECT tree data structure. */ /* */ /* The "filespec" parameter is the full path and name of the */ /* label file to be parsed. */ /* */ /* The "message_fname" parameter is the name of the file where */ /* parser error messages will be written. If the file exists, */ /* the messages are appended, otherwise a new file is created. */ /* A NULL value passed in causes messages to be sent to stdout. */ /* */ /* The "suppress_messages" parameter is a flag that tells the code */ /* whether or not to print parser error messages. A value of TRUE */ /* (1) tells the code to supress all messages. If this parameter */ /* is 1, it doesn't matter what you specified with the */ /* "message_fname". Nothing will be written to that file. If a */ /* zero (0) is passed in, then messages will be written to the */ /* file you specified with the "message_fname" parameter. */ /* */ /* The expand parameter is a flag that controls whether or not */ /* ^STRUCTURE and ^CATALOG keywords are expanded. To expand one */ /* of these keywords means to take the file name it points to, */ /* parse its contents, and insert the results into the tree right */ /* where the keyword is sitting. In other words, these keywords */ /* function just like include files in "C". These are the values */ /* that can be passed in: */ /* */ /* ODL_EXPAND_STRUCTURE - expand ^STRUCTURE keywords only */ /* ODL_EXPAND_CATALOG - expand ^CATALOG keywords only */ /* ODL_EXPAND_STRUCTURE | ODL_EXPAND_CATALOG - expand */ /* both keywords (the "|" character is the logical */ /* "or" of both values). */ /* */ /*----------------------------------------------------------------------*/ /* */ /* WARNING: The value returned by this routine points to memory */ /* allocated by this routine (sometimes quite a bit of */ /* memory!). Be sure to deallocate it using the */ /* OdlFreeTree routine. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlParseLabelFile (filespec, message_fname, expand, suppress_messages) char *filespec; char *message_fname; MASK expand; unsigned short suppress_messages; #else OBJDESC *OdlParseLabelFile (char *filespec, char *message_fname, MASK expand, unsigned short suppress_messages) #endif { OBJDESC *root = {NULL}; odl_suppress_messages = suppress_messages; root = (OBJDESC *) OdlParseFile(filespec,NULL,message_fname,NULL,suppress_messages,1,1,0); root = (OBJDESC *) OdlExpandLabelFile(root, filespec, message_fname, expand, suppress_messages); return(root); } /* End: "OdlParseLabelFile" */ OBJDESC *OdlParseLabelFptr (fp, message_fname, expand, suppress_messages) FILE *fp; char *message_fname; MASK expand; unsigned short suppress_messages; { OBJDESC *root = {NULL}; odl_suppress_messages = suppress_messages; root = (OBJDESC *) OdlParseFile(0,fp,message_fname,NULL,suppress_messages,1,1,0); root = (OBJDESC *) OdlExpandLabelFile(root, NULL, message_fname, expand, suppress_messages); return(root); } /* End: "OdlParseLabelFptr" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlParseLabelString */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine causes a character string containing an ODL */ /* statement to be parsed and its "^" keywords expanded. It */ /* returns a pointer to the root of the OBJECT tree data structure.*/ /* */ /* WARNING: The value returned by this routine points to memory */ /* allocated by this routine. Be sure to deallocate it */ /* using the OdlFreeTree routine. */ /* */ /* WARNING: This routine will try to create a temporary file in */ /* the following locations, depending on the system: */ /* */ /* UNIX: ~/.tmp */ /* VMS: sys$login:.tmp */ /* MSDOS: C:\.tmp */ /* All others: .tmp */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlParseLabelString (odl_string, message_fname, expand, suppress_messages) char *odl_string; char *message_fname; MASK expand; unsigned short suppress_messages; #else OBJDESC *OdlParseLabelString (char *odl_string, char *message_fname, MASK expand, unsigned short suppress_messages) #endif { OBJDESC *root = {NULL}; FILE *tmp_fptr = {NULL}; char *tmp_fname = {NULL}; odl_suppress_messages = suppress_messages; tmp_fname = (char *) OdlTempFname(); if (tmp_fname == NULL) OdlPrintMessage(message_fname,NULL,0,"Unable to create a temporary file"); if ((tmp_fptr = (FILE *) fopen(tmp_fname, "w")) != NULL) { fprintf(tmp_fptr, "%s", odl_string); fclose(tmp_fptr); root = (OBJDESC *) OdlParseLabelFile(tmp_fname, message_fname, expand, suppress_messages); #ifdef VMS AppendString(tmp_fname, ";*") #endif remove(tmp_fname); } LemmeGo(tmp_fname) return(root); } /* End: "OdlParseLabelString" */ /*========================================================================*/ /* */ /* Label Expand routines */ /* */ /*========================================================================*/ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlExpandLabelFile */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine locates "^STRUCTURE" and "^CATALOG" keywords and */ /* expands them. To "expand" means to extract the file name */ /* pointed to by the keyword, parse its contents, and insert the */ /* resulting tree into the label right where the keyword is */ /* sitting. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlExpandLabelFile (object, orig_fspec, message_fname, expand, suppress_messages) OBJDESC *object; char *orig_fspec, *message_fname; MASK expand; unsigned short suppress_messages; #else OBJDESC *OdlExpandLabelFile (OBJDESC *object, char *orig_fspec, char *message_fname, MASK expand, unsigned short suppress_messages) #endif { KEYWORD *kwd = {NULL}; KEYWORD *new_kwd = {NULL}; KEYWORD *save_kwd = {NULL}; OBJDESC *temp_root = {NULL}; OBJDESC *new_obj = {NULL}; OBJDESC *save_obj = {NULL}; FILE *l_ptr = {NULL}; unsigned long start_loc = {1}; unsigned short loc_type = {ODL_RECORD_LOCATION}; unsigned short done = {FALSE}; char *fspec = {NULL}; char *fname = {NULL}; char *keyword_name = {NULL}; char error_message[5*(TB_MAXLINE + TB_MAXPATH + TB_MAXFNAME)]; odl_suppress_messages = suppress_messages; /* Let's expand all ^STRUCTURE keywords, shall we? */ if ((expand&ODL_EXPAND_STRUCTURE) == ODL_EXPAND_STRUCTURE) { expand -= ODL_EXPAND_STRUCTURE; CopyString(keyword_name, "^*STRUCTURE") } else /* On second thought, let's expand all ^CATALOG keywords */ if ((expand&ODL_EXPAND_CATALOG) == ODL_EXPAND_CATALOG) { expand -= ODL_EXPAND_CATALOG; CopyString(keyword_name, "^*CATALOG") } else /* Hmmm. I guess we have nothing left to expand. */ { expand = ODL_NOEXPAND; done = TRUE; } /* Keep expanding until we can expand no more forever */ while (! done) { /* Find the expand keyword wherever it my be hiding */ kwd = (KEYWORD *) OdlFindKwd(object, keyword_name, NULL, 1, ODL_RECURSIVE_DOWN); /* We're done if there aren't any more keywords to expand */ if (kwd == NULL) done = TRUE; else { /* Get the file name, minus quotes and blanks, sans path */ fname = (char *) OdlGetFileName(kwd, &start_loc, &loc_type); /* We're in trouble if we've encountered this file before */ if (ExpandIsRecursive(kwd, fname)) { sprintf(error_message, "Recursive %s statement found in file: %s", keyword_name, fname); OdlPrintMessage(message_fname,NULL,kwd->line_number,error_message); } else { /* Figure out exactly where the file is located */ fspec = (char *) OdlGetFileSpec(fname, orig_fspec); /* We're in trouble if we can't find the file */ if (fspec == NULL) { sprintf(error_message, "Unable to locate %s file: %s", keyword_name, fname); OdlPrintMessage(message_fname,NULL,kwd->line_number,error_message); } else { l_ptr = (FILE *) OdlLocateStart(fspec, start_loc, loc_type); /* Parse the file */ temp_root = (OBJDESC *) OdlParseFile(fspec,l_ptr, message_fname,NULL,suppress_messages,1,1,1); /* Was there anything in the file to parse? */ if (temp_root != NULL) { /* Append any keywords */ for (new_kwd=temp_root->first_keyword; new_kwd != NULL; new_kwd = save_kwd) { save_kwd = new_kwd->right_sibling; OdlPasteKwd((KEYWORD *) OdlCutKwd(new_kwd), kwd->parent); } /* Append any sub-objects */ for (new_obj=temp_root->first_child; new_obj != NULL; new_obj = save_obj) { save_obj = new_obj->right_sibling; OdlPasteObjDesc((OBJDESC *) OdlCutObjDesc(new_obj), kwd->parent); } /* Deallocate the temporary root */ temp_root->first_keyword = NULL; temp_root->first_child = NULL; temp_root = (OBJDESC *) OdlFreeTree(temp_root); } /* End: "if (temp_root != NULL) ..." */ /* Free the file spec storage */ LemmeGo(fspec) CloseMe(l_ptr) } /* End: "if (fspec == NULL) ... else ..." */ } /* End: "if (ExpandIsRecursive( ... else ..." */ OdlFreeKwd((KEYWORD *)OdlCutKwd(kwd)); /* Free the file name storage */ LemmeGo(fname) } /* End: "if (kwd == NULL) ... else ..." */ } /* End: "while (! done) ..." */ /* Free the keyword name storage */ LemmeGo(keyword_name) /* Check and see if there are any other keywords to expand */ if (expand != ODL_NOEXPAND) { object = (OBJDESC *) OdlExpandLabelFile(object, orig_fspec, message_fname, expand, suppress_messages); } /* Return the root of the expanded tree */ return(object); } /* End: "OdlExpandLabelFile" */ /*******************/ /* Local Routine */ /*******************/ #ifdef _NO_PROTO static unsigned short ExpandIsRecursive (keyword, exp_fname) KEYWORD *keyword; char *exp_fname; #else static unsigned short ExpandIsRecursive (KEYWORD *keyword, char *exp_fname) #endif { OBJDESC *obj = {NULL}; char *temp_fname = {NULL}; unsigned short found = {FALSE}; if ((keyword != NULL) && (exp_fname != NULL)) { #if (defined( VAX) || defined( ALPHA_VMS)) UpperCase(exp_fname) #endif CopyString(temp_fname, keyword->file_name) #if (defined( VAX) || defined( ALPHA_VMS)) UpperCase(temp_fname) #endif found = (strcmp(temp_fname, exp_fname) == 0); LemmeGo(temp_fname) for (obj=keyword->parent; ((! found) && (obj != NULL)); obj=obj->parent) { CopyString(temp_fname, obj->file_name) #if (defined( VAX) || defined( ALPHA_VMS)) UpperCase(temp_fname) #endif found = (strcmp(temp_fname, exp_fname) == 0); LemmeGo(temp_fname) } } return(found); } /* End: "ExpandIsRecursive" */ /*========================================================================*/ /* */ /* Object description routines */ /* */ /*========================================================================*/ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlFindObjDesc */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine locates an object within a parsed label by its */ /* class name (like TABLE), by its position (look for the seventh */ /* table object in the label), by a particular keyword present */ /* in the object (like NAME), or by a particular value that a */ /* particular keyword has (like START_BYTE = 76). */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlFindObjDesc(start_object, object_class, keyword_name, keyword_value, object_position, search_scope) OBJDESC *start_object; char *object_class; char *keyword_name; char *keyword_value; unsigned long object_position; unsigned short search_scope; #else OBJDESC *OdlFindObjDesc( OBJDESC *start_object, char *object_class, char *keyword_name, char *keyword_value, unsigned long object_position, unsigned short search_scope) #endif { OBJDESC *found_object = {NULL}; OBJDESC *obj = {NULL}; KEYWORD *kwd = {NULL}; unsigned short found = {FALSE}; unsigned short scope = search_scope; unsigned long current_position = {0}; for (obj=start_object; ((obj != NULL) && (! found)); obj = (OBJDESC *) OdlNextObjDesc(obj, start_object->level, &scope)) { if (object_class == NULL) found = TRUE; else found = OdlWildCardCompare(object_class, obj->class); if ((found) && (keyword_name != NULL)) { kwd = (KEYWORD *) OdlFindKwd(obj, keyword_name, NULL, 1, ODL_THIS_OBJECT); found = (kwd != NULL); } if ((found) && (keyword_value != NULL)) found = OdlWildCardCompare(keyword_value, (char *) OdlGetKwdValue(kwd)); if ((found) && (object_position > 0)) found = ((++current_position) == object_position); if (found) found_object = obj; } /* End: "for (obj=start_object; ..." */ return(found_object); } /* End: "OdlFindObjDesc" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlNextObjDesc */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine locates the next object in the tree based on the */ /* search_scope passed in. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlNextObjDesc (object, root_level, search_scope) OBJDESC *object; unsigned long root_level; unsigned short *search_scope; #else OBJDESC *OdlNextObjDesc (OBJDESC *object, unsigned long root_level, unsigned short *search_scope) #endif { OBJDESC *next_object = {NULL}; if (object != NULL) { switch (*search_scope) { /* look only in the current object */ case ODL_THIS_OBJECT : next_object = NULL; break; /* look at the current object's first child now, and its */ /* child's right siblings in subsequent searches */ case ODL_CHILDREN_ONLY : next_object = object->first_child; *search_scope = ODL_SIBLINGS_ONLY; break; /* look at the current object's right sibling */ case ODL_SIBLINGS_ONLY : next_object = object->right_sibling; break; /* treat the current object as the root of a sub-tree */ case ODL_RECURSIVE_DOWN : next_object = (OBJDESC *) OdlTraverseTree(object, root_level); break; /* search children, then siblings, then move up to parent */ /* keep going until the end of the label is reached */ default : next_object = (OBJDESC *) OdlTraverseTree(object, (unsigned long) 0); break; } /* End: "switch (*search_scope) ..." */ } /* End: "if (object != NULL) ..." */ return(next_object); } /* End: "OdlNextObjDesc" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlCutObjDesc */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine cuts an ODL object structure out of an ODL tree */ /* and returns a pointer to it. All references to it in the tree */ /* are removed, and all references to the original tree within the */ /* object are removed. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlCutObjDesc (object) OBJDESC *object; #else OBJDESC *OdlCutObjDesc (OBJDESC *object) #endif { if (object != NULL) { if (object->right_sibling == NULL) object->parent->last_child = object->left_sibling; else object->right_sibling->left_sibling = object->left_sibling; if (object->left_sibling == NULL) object->parent->first_child = object->right_sibling; else object->left_sibling->right_sibling = object->right_sibling; object->parent = NULL; object->left_sibling = NULL; object->right_sibling = NULL; } /* End: "if (object != NULL) ..." */ return(object); } /* End routine: "OdlCutObjDesc" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlPasteObjDesc */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine adds an object to a tree as the last child of the */ /* parent_object. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlPasteObjDesc (new_object, parent_object) OBJDESC *new_object; OBJDESC *parent_object; #else OBJDESC *OdlPasteObjDesc (OBJDESC *new_object, OBJDESC *parent_object) #endif { if ((new_object != NULL) && (parent_object != NULL)) { new_object->left_sibling = parent_object->last_child; new_object->right_sibling = NULL; new_object->parent = parent_object; if (parent_object->first_child == NULL) parent_object->first_child = new_object; if (parent_object->last_child != NULL) parent_object->last_child->right_sibling = new_object; parent_object->last_child = new_object; OdlAdjustObjDescLevel(new_object); } /* End: "if ((new_object != NULL) && ..." */ return(new_object); } /* End routine: "OdlPasteObjDesc" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlPasteObjDescBefore */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine adds an object to a tree as the left sibling of */ /* the old_object. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlPasteObjDescBefore (new_object, old_object) OBJDESC *new_object; OBJDESC *old_object; #else OBJDESC *OdlPasteObjDescBefore (OBJDESC *new_object, OBJDESC *old_object) #endif { if ((new_object != NULL) && (old_object != NULL)) { new_object->left_sibling = old_object->left_sibling; new_object->right_sibling = old_object; new_object->parent = old_object->parent; if (old_object->left_sibling == NULL) old_object->parent->first_child = new_object; else old_object->left_sibling->right_sibling = new_object; old_object->left_sibling = new_object; OdlAdjustObjDescLevel(new_object); } /* End: "if ((new_object != NULL) && ..." */ return(new_object); } /* End routine: "OdlPasteObjDescBefore" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlPasteObjDescAfter */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine adds an object to a tree as the right sibling of */ /* the old_object. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlPasteObjDescAfter (new_object, old_object) OBJDESC *new_object; OBJDESC *old_object; #else OBJDESC *OdlPasteObjDescAfter (OBJDESC *new_object, OBJDESC *old_object) #endif { if ((new_object != NULL) && (old_object != NULL)) { new_object->right_sibling = old_object->right_sibling; new_object->left_sibling = old_object; new_object->parent = old_object->parent; if (old_object->right_sibling == NULL) old_object->parent->last_child = new_object; else old_object->right_sibling->left_sibling = new_object; old_object->right_sibling = new_object; OdlAdjustObjDescLevel(new_object); } /* End: "if ((new_object != NULL) && ..." */ return(new_object); } /* End routine: "OdlPasteObjDescAfter" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlCopyObjDesc */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine makes a copy of an object and returns a pointer */ /* to the copy. All fields are duplicated except for references */ /* to the original tree, which are removed. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlCopyObjDesc (object) OBJDESC *object; #else OBJDESC *OdlCopyObjDesc (OBJDESC *object) #endif { OBJDESC *new_object = {NULL}; if (object != NULL) { new_object = OdlNewObjDesc(object->class, object->pre_comment, object->line_comment, object->post_comment, object->end_comment, object->file_name, object->is_a_group, object->line_number); } return(new_object); } /* End routine: "OdlCopyObjDesc" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlNewObjDesc */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine creates a new object structure and initializes */ /* its fields with the values passed in. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlNewObjDesc (object_class, pre_comment, line_comment, post_comment, end_comment, file_name, is_a_group, line_number) char *object_class; char *pre_comment; char *line_comment; char *post_comment; char *end_comment; char *file_name; short is_a_group; long line_number; #else OBJDESC *OdlNewObjDesc (char *object_class, char *pre_comment, char *line_comment, char *post_comment, char *end_comment, char *file_name, short is_a_group, long line_number) #endif { OBJDESC *new_object = {NULL}; if ((new_object = (OBJDESC *)malloc(sizeof(OBJDESC))) == NULL) SayGoodbye() else { CopyString(new_object->class, object_class) CopyString(new_object->pre_comment, pre_comment) CopyString(new_object->line_comment, line_comment) CopyString(new_object->post_comment, post_comment) CopyString(new_object->end_comment, end_comment) CopyString(new_object->file_name, file_name) new_object->is_a_group = is_a_group; new_object->child_count = 0; new_object->line_number = line_number; new_object->level = 0; new_object->parent = NULL; new_object->left_sibling = NULL; new_object->right_sibling = NULL; new_object->first_child = NULL; new_object->last_child = NULL; new_object->first_keyword = NULL; new_object->last_keyword = NULL; new_object->appl1 = NULL; new_object->appl2 = NULL; } /* End: "if ((new_object = ... else ..." */ return(new_object); } /* End routine: "OdlNewObjDesc" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetLabelVersion */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns a pointer to a character string containing */ /* the ODL version of the label. It looks for this information in */ /* the ODL_VERSION_NUMBER keyword. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO THE ACTUAL VALUE OF THE */ /* ODL_VERSION_NUMBER KEYWORD AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO char *OdlGetLabelVersion (object) OBJDESC *object; #else char *OdlGetLabelVersion (OBJDESC *object) #endif { KEYWORD *kwd = {NULL}; char *version = {NULL}; if (object != NULL) { kwd = (KEYWORD *) OdlFindKwd(object, "PDS_VERSION_ID", NULL, 1, ODL_THIS_OBJECT); if (kwd == NULL) { kwd = (KEYWORD *) OdlFindKwd(object, "ODL_VERSION_NUMBER", NULL, 1, ODL_THIS_OBJECT); } if (kwd != NULL) version = (char *) OdlGetKwdValue(kwd); } return(version); } /* End: "OdlGetLabelVersion" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetObjDescClassName */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns the class name of an object. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO THE ACTUAL INFORMATION STORED */ /* IN THE ODL OBJECT STRUCTURE AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO char *OdlGetObjDescClassName (object) OBJDESC *object; #else char *OdlGetObjDescClassName (OBJDESC *object) #endif { char *class_name = {NULL}; if (object != NULL) class_name = object->class; return(class_name); } /* End: "OdlGetObjDescClassName" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetObjDescChildCount */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns a count of the immediate children of an */ /* object. It does not count children of children, etc. */ /* */ /************************************************************************/ #ifdef _NO_PROTO int OdlGetObjDescChildCount (object) OBJDESC *object; #else int OdlGetObjDescChildCount (OBJDESC *object) #endif { OBJDESC *obj = {NULL}; int child_count = {0}; if (object != NULL) { for (obj=object->first_child; obj != NULL; obj=obj->right_sibling) ++child_count; } return(child_count); } /* End: "OdlGetObjDescChildCount" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetObjDescLevel */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns the nesting level of an object. The ROOT */ /* object in a tree is always defined to be level 0. */ /* */ /************************************************************************/ #ifdef _NO_PROTO int OdlGetObjDescLevel (object) OBJDESC *object; #else int OdlGetObjDescLevel (OBJDESC *object) #endif { OBJDESC *obj = {NULL}; int level = {0}; if (object != NULL) { for (obj=object->parent; obj != NULL; obj=obj->parent) ++level; } return(level); } /* End: "OdlGetObjDescLevel" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlAdjustObjDescLevel */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine changes the nesting level of an object and all of */ /* its subobjects so they fit in with their place in the overall */ /* ODL tree. This is particularly useful when objects are cut */ /* from one tree and pasted into another tree, perhaps higher or */ /* lower in the nesting hierarchy then they were in the original */ /* tree. */ /* */ /************************************************************************/ #ifdef _NO_PROTO void OdlAdjustObjDescLevel (object) OBJDESC *object; #else void OdlAdjustObjDescLevel (OBJDESC *object) #endif { OBJDESC *obj = {NULL}; unsigned short scope = {ODL_RECURSIVE_DOWN}; for (obj=object; obj != NULL; obj = (OBJDESC *) OdlNextObjDesc(obj, object->level, &scope)) { obj->level = (obj->parent == NULL) ? 0 : (1 + obj->parent->level); } return; } /* End routine: "OdlAdjustObjDescLevel" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetObjDescParent */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns a pointer to an object's parent. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO AN EXISTING ODL OBJECT AND */ /* AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlGetObjDescParent (object) OBJDESC *object; #else OBJDESC *OdlGetObjDescParent (OBJDESC *object) #endif { OBJDESC *parent = {NULL}; if (object != NULL) parent = object->parent; return(parent); } /* End: "OdlGetObjDescParent" */ /*========================================================================*/ /* */ /* Keyword routines */ /* */ /*========================================================================*/ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlFindKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine locates the keyword in a label that satisfies the */ /* requirements passed in: The object where the search is to */ /* begin, the name of the keyword, a particular value that the */ /* keyword must have, which version of the keyword we want (if */ /* there are duplicates), and the search scope we want to use to */ /* limit the objects searched. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlFindKwd (start_object, keyword_name, keyword_value, keyword_position, search_scope) OBJDESC *start_object; char *keyword_name; char *keyword_value; unsigned long keyword_position; unsigned short search_scope; #else KEYWORD *OdlFindKwd (OBJDESC *start_object, char *keyword_name, char *keyword_value, unsigned long keyword_position, unsigned short search_scope) #endif { OBJDESC *obj = {NULL}; KEYWORD *kwd = {NULL}; KEYWORD *found_kwd = {NULL}; unsigned short found = {FALSE}; unsigned short scope = search_scope; unsigned long current_position = {0}; for (obj=start_object; ((obj != NULL) && (! found)); obj = (OBJDESC *) OdlNextObjDesc(obj, start_object->level, &scope)) { for (kwd=obj->first_keyword; ((kwd != NULL) && (! found)); kwd=kwd->right_sibling) { if (keyword_name == NULL) found = TRUE; else found = OdlWildCardCompare(keyword_name, kwd->name); if ((found) && (keyword_value != NULL)) found = OdlWildCardCompare(keyword_value, (char *) OdlGetKwdValue(kwd)); if ((found) && (keyword_position > 0)) found = ((++current_position) == keyword_position); if (found) found_kwd = kwd; } /* End: "for (kwd=obj-> ..." */ } /* End: "for (obj=start_object; ..." */ return(found_kwd); } /* End: "OdlFindKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlNextKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine locates the keyword in a label that satisfies the */ /* requirements passed in: The object where the search is to */ /* begin, the name of the keyword, a particular value that the */ /* keyword must have, which version of the keyword we want (if */ /* there are duplicates), and the search scope we want to use to */ /* limit the objects searched. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlNextKwd (start_keyword, keyword_name, keyword_value, keyword_position, search_scope) KEYWORD *start_keyword; char *keyword_name; char *keyword_value; unsigned long keyword_position; unsigned short search_scope; #else KEYWORD *OdlNextKwd (KEYWORD *start_keyword, char *keyword_name, char *keyword_value, unsigned long keyword_position, unsigned short search_scope) #endif { OBJDESC *start_object = {NULL}; OBJDESC *obj = {NULL}; KEYWORD *kwd = {NULL}; KEYWORD *found_kwd = {NULL}; unsigned short found = {FALSE}; unsigned short scope = search_scope; unsigned long current_position = {0}; if (start_keyword != NULL) { start_object = start_keyword->parent; obj = start_object; kwd = start_keyword; do { for ( ; ((kwd != NULL) && (! found)); kwd=kwd->right_sibling) { if (keyword_name == NULL) found = TRUE; else found = OdlWildCardCompare(keyword_name, kwd->name); if ((found) && (keyword_value != NULL)) found = OdlWildCardCompare(keyword_value, (char *) OdlGetKwdValue(kwd)); if ((found) && (keyword_position > 0)) found = ((++current_position) == keyword_position); if (found) found_kwd = kwd; } /* End: "for (kwd=start_keyword; ..." */ if (! found) { obj = (OBJDESC *) OdlNextObjDesc(obj, start_object->level, &scope); kwd = (KEYWORD *) OdlGetFirstKwd(obj); } } while ((obj != NULL) && (! found)); } /* End: "if (start_keyword != NULL) ..." */ return(found_kwd); } /* End: "OdlNextKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlCutKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine removes a keyword from an object and returns a */ /* pointer to it. All references to the object within the keyword */ /* are removed, and all references to the keyword within the */ /* object are removed. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO AN EXISTING KEYWORD STRUCTURE */ /* AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlCutKwd (keyword) KEYWORD *keyword; #else KEYWORD *OdlCutKwd (KEYWORD *keyword) #endif { if (keyword != NULL) { if (keyword->left_sibling != NULL) keyword->left_sibling->right_sibling = keyword->right_sibling; if (keyword->right_sibling != NULL) keyword->right_sibling->left_sibling = keyword->left_sibling; if (keyword->parent->first_keyword == keyword) keyword->parent->first_keyword = keyword->right_sibling; if (keyword->parent->last_keyword == keyword) keyword->parent->last_keyword = keyword->left_sibling; keyword->parent = NULL; keyword->left_sibling = NULL; keyword->right_sibling = NULL; } /* End: "if ((keyword != NULL) && ..." */ return(keyword); } /* End routine: "OdlCutKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlPasteKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine adds a keyword to the end of an object's keyword */ /* list. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlPasteKwd (keyword, object) KEYWORD *keyword; OBJDESC *object; #else KEYWORD *OdlPasteKwd (KEYWORD *keyword, OBJDESC *object) #endif { if ((keyword != NULL) && (object != NULL)) { keyword->parent = object; keyword->left_sibling = object->last_keyword; keyword->right_sibling = NULL; if (object->first_keyword == NULL) object->first_keyword = keyword; if (object->last_keyword != NULL) object->last_keyword->right_sibling = keyword; object->last_keyword = keyword; } /* End: "if ((keyword != NULL) && ..." */ return(keyword); } /* End routine: "OdlPasteKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlPasteKwdBefore */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine adds a keyword to an object as the left sibling of */ /* the old_keyword. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlPasteKwdBefore (new_keyword, old_keyword) KEYWORD *new_keyword; KEYWORD *old_keyword; #else KEYWORD *OdlPasteKwdBefore (KEYWORD *new_keyword, KEYWORD *old_keyword) #endif { if ((new_keyword != NULL) && (old_keyword != NULL)) { new_keyword->parent = old_keyword->parent; new_keyword->left_sibling = old_keyword->left_sibling; new_keyword->right_sibling = old_keyword; if (old_keyword->left_sibling == NULL) old_keyword->parent->first_keyword = new_keyword; else old_keyword->left_sibling->right_sibling = new_keyword; old_keyword->left_sibling = new_keyword; } /* End: "if ((new_keyword != NULL) && ..." */ return(new_keyword); } /* End routine: "OdlPasteKwdBefore" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlPasteKwdAfter */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine adds a keyword to an object as the right sibling */ /* of the old_keyword. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlPasteKwdAfter (new_keyword, old_keyword) KEYWORD *new_keyword; KEYWORD *old_keyword; #else KEYWORD *OdlPasteKwdAfter (KEYWORD *new_keyword, KEYWORD *old_keyword) #endif { if ((new_keyword != NULL) && (old_keyword != NULL)) { new_keyword->parent = old_keyword->parent; new_keyword->right_sibling = old_keyword->right_sibling; new_keyword->left_sibling = old_keyword; if (old_keyword->right_sibling == NULL) old_keyword->parent->last_keyword = new_keyword; else old_keyword->right_sibling->left_sibling = new_keyword; old_keyword->right_sibling = new_keyword; } /* End: "if ((new_keyword != NULL) && ..." */ return(new_keyword); } /* End routine: "OdlPasteKwdAfter" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlCopyKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine makes a copy of a keyword and returns a pointer to */ /* it. All of the keyword's fields are duplicated except for */ /* references to the parent object, which are removed. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlCopyKwd (keyword) KEYWORD *keyword; #else KEYWORD *OdlCopyKwd (KEYWORD *keyword) #endif { KEYWORD *new_keyword = {NULL}; if (keyword != NULL) { new_keyword = OdlNewKwd(keyword->name, keyword->value, keyword->pre_comment, keyword->line_comment, keyword->file_name, keyword->line_number); } return(new_keyword); } /* End routine: "OdlCopyKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlNewKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine creates a new keyword structure, initializes */ /* its fields with the values passed in, and returns a pointer */ /* to it. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlNewKwd (keyword_name, value_text, pre_comment, line_comment, file_name, line_number) char *keyword_name; char *value_text; char *pre_comment; char *line_comment; char *file_name; long line_number; #else KEYWORD *OdlNewKwd (char *keyword_name, char *value_text, char *pre_comment, char *line_comment, char *file_name, long line_number) #endif { KEYWORD *new_keyword = {NULL}; if ((new_keyword = (KEYWORD *)malloc(sizeof(KEYWORD))) == NULL) SayGoodbye() else { CopyString(new_keyword->name, keyword_name) CopyString(new_keyword->pre_comment, pre_comment) CopyString(new_keyword->line_comment, line_comment) CopyString(new_keyword->file_name, file_name) CopyString(new_keyword->value, value_text) new_keyword->is_a_pointer = (keyword_name == NULL) ? FALSE : (*keyword_name == '^'); if (value_text == NULL) { new_keyword->size = 0; new_keyword->is_a_list = FALSE; } else { new_keyword->size = strlen(new_keyword->value); new_keyword->is_a_list = ((*value_text == '{') || (*value_text == '(')); } new_keyword->line_number = line_number; new_keyword->parent = NULL; new_keyword->left_sibling = NULL; new_keyword->right_sibling = NULL; new_keyword->appl1 = NULL; new_keyword->appl2 = NULL; } /* End: "if ((new_keyword = ... else ..." */ return(new_keyword); } /* End routine: "OdlNewKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetFirstKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns a pointer to the first keyword data */ /* structure in an object definition structure. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO THE ACTUAL INFORMATION STORED */ /* IN THE OBJECT DATA STRUCTURE AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlGetFirstKwd (object) OBJDESC *object; #else KEYWORD *OdlGetFirstKwd (OBJDESC *object) #endif { KEYWORD *kwd = {NULL}; if (object != NULL) kwd = object->first_keyword; return(kwd); } /* End: "OdlGetFirstKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetNextKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns a pointer to the next keyword data */ /* structure in an object definition's list of keyword structures. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO THE ACTUAL INFORMATION STORED */ /* IN THE OBJECT DATA STRUCTURE AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlGetNextKwd (keyword) KEYWORD *keyword; #else KEYWORD *OdlGetNextKwd (KEYWORD *keyword) #endif { KEYWORD *kwd = {NULL}; if (keyword != NULL) kwd = keyword->right_sibling; return(kwd); } /* End: "OdlGetNextKwd" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetKwdValue */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns a pointer to a keyword's value. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO THE ACTUAL INFORMATION STORED */ /* IN THE KEYWORD DATA STRUCTURE AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO char *OdlGetKwdValue (keyword) KEYWORD *keyword; #else char *OdlGetKwdValue (KEYWORD *keyword) #endif { char *value = {NULL}; if (keyword != NULL) value = keyword->value; return(value); } /* End: "OdlGetKwdValue" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetAllKwdValues */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine extracts each individual value from a set or */ /* sequence of values of a keyword, stores these values in a */ /* linked list, and returns a pointer to this list. */ /* */ /* For example, if a keyword has this combination of sets and */ /* sequences as its value: */ /* */ /* {red, (green, blue), {17, (("book.lbl", 345), orange)}} */ /* */ /* Then the TB_STRING_LIST returned would contain: */ /* */ /* red */ /* green */ /* blue */ /* 17 */ /* "book.lbl" */ /* 345 */ /* orange */ /* */ /* WARNING: The string list must be freed using the */ /* RemoveStringList macro (look in toolbox.h). */ /* */ /************************************************************************/ #ifdef _NO_PROTO TB_STRING_LIST *OdlGetAllKwdValues (keyword) KEYWORD *keyword; #else TB_STRING_LIST *OdlGetAllKwdValues(KEYWORD *keyword) #endif { TB_STRING_LIST *value_list = {NULL}; char *val_start = {NULL}; char *val_stop = {NULL}; char save_ch; if (keyword != NULL) { if (keyword->value != NULL) { for (val_start=(char *)OdlValueStart(keyword->value); *val_start != '\0'; val_start=(char *)OdlValueStart(val_stop+1)) { val_stop = (char *) OdlValueEnd(val_start); save_ch = *(val_stop + 1); *(val_stop + 1) = '\0'; AddStringToList(val_start, value_list) *(val_stop + 1) = save_ch; } } /* End: "if (keyword->value != NULL) ..." */ } /* End: "if (keyword != NULL) ..." */ return(value_list); } /* End: "OdlGetAllKwdValues" */ #ifdef _NO_PROTO int OdlGetAllKwdValuesArray (keyword, array) KEYWORD *keyword; char ***array; #else int OdlGetAllKwdValuesArray (KEYWORD *keyword, char ***array) #endif { TB_STRING_LIST *value_list = {NULL}; char *val_start = {NULL}; char *val_stop = {NULL}; char save_ch; *array = NULL; if (keyword != NULL) { if (keyword->value != NULL) { for (val_start=(char *)OdlValueStart(keyword->value); *val_start != '\0'; val_start=(char *)OdlValueStart(val_stop+1)) { val_stop = (char *) OdlValueEnd(val_start); save_ch = *(val_stop + 1); *(val_stop + 1) = '\0'; AddStringToList(val_start, value_list) *(val_stop + 1) = save_ch; } } /* End: "if (keyword->value != NULL) ..." */ } /* End: "if (keyword != NULL) ..." */ if (value_list) { return(ListToArray(value_list, array)); } else { return(0); } } /* End: "OdlGetAllKwdValues" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetKwdValueType */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine determines the data type of a keyword's value and */ /* returns a data type symbolic id. Possible symbolic ids are: */ /* */ /* ODL_UNKNOWN (can't tell what the heck it is) */ /* ODL_INTEGER (handles optional leading plus or minus) */ /* ODL_REAL (handles optional leading plus or minus, */ /* scientific notation, and real exponents) */ /* ODL_SYMBOL (unqouted or single quoted string of */ /* characters) */ /* ODL_TEXT (double quoted string of characters) */ /* ODL_DATE (yyyy-mm-dd or yyyy-ddd) */ /* ODL_DATE_TIME (yyyy-mm-ddThh:mm:ss.h) */ /* ODL_SEQUENCE (starts with a paren character "(") */ /* ODL_SET (starts with a brace character "{") */ /* */ /************************************************************************/ #ifdef _NO_PROTO unsigned short OdlGetKwdValueType (keyword) KEYWORD *keyword; #else unsigned short OdlGetKwdValueType (KEYWORD *keyword) #endif { unsigned short type = {ODL_UNKNOWN}; if (keyword != NULL) type = (unsigned short) OdlDataType(keyword->value); return(type); } /* End: "OdlGetKwdValueType" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetKwdUnit */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine locates the units part of a keyword's value, */ /* extracts it, stores it in a new character string, and returns */ /* a pointer to this new character string. */ /* */ /* WARNING: This routine allocates memory for the return value */ /* that must be freed. */ /* */ /************************************************************************/ #ifdef _NO_PROTO char *OdlGetKwdUnit (keyword) KEYWORD *keyword; #else char *OdlGetKwdUnit (KEYWORD *keyword) #endif { char *c = {NULL}; char *unit = {NULL}; /* If we were given a keyword to use */ if (keyword != NULL) { /* Attempt to locate the units string */ c = (char *) strchr(keyword->value, '<'); if (c != NULL) { /* We found it! Now copy it and make it upper case */ CopyString(unit, c) UpperCase(unit) /* Close off the units string */ c = (char *) strchr(unit, '>'); if (c != NULL) *(c + 1) = '\0'; } } /* End: "if (keyword != NULL) ..." */ return(unit); } /* End: "OdlGetKwdUnit" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetKwdName */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns the name of a keyword. */ /* */ /* WARNING: NO MEMORY IS ALLOCATED BY THIS ROUTINE. THE RETURN */ /* VALUE IS A POINTER TO THE ACTUAL INFORMATION STORED */ /* IN THE KEYWORD DATA STRUCTURE AND MUST NOT BE FREED. */ /* */ /************************************************************************/ #ifdef _NO_PROTO char *OdlGetKwdName (keyword) KEYWORD *keyword; #else char *OdlGetKwdName (KEYWORD *keyword) #endif { char *name = {NULL}; if (keyword != NULL) name = keyword->name; return(name); } /* End: "OdlGetKwdName" */ /*========================================================================*/ /* */ /* Memory deallocation routines */ /* */ /*========================================================================*/ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlFreeTree */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine frees all memory used by an ODL tree. The return */ /* value is always NULL. */ /* */ /************************************************************************/ #ifdef _NO_PROTO OBJDESC *OdlFreeTree (object) OBJDESC *object; #else OBJDESC *OdlFreeTree (OBJDESC *object) #endif { if (object != NULL) { OdlFreeTree(object->first_child); OdlFreeTree(object->right_sibling); OdlFreeAllKwds(object); LemmeGo(object->class) LemmeGo(object->pre_comment) LemmeGo(object->line_comment) LemmeGo(object->post_comment) LemmeGo(object->end_comment) LemmeGo(object->file_name) LemmeGo(object) } return(object); } /* End: "OdlFreeTree" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlFreeAllKwds */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine frees all memory used by an object's keywords. */ /* When it's finished, all references to keywords are gone from */ /* the object. The return value is always NULL. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlFreeAllKwds (object) OBJDESC *object; #else KEYWORD *OdlFreeAllKwds (OBJDESC *object) #endif { KEYWORD *kwd = {NULL}; if (object != NULL) { for (kwd=object->first_keyword; kwd != NULL; kwd=(KEYWORD *) OdlFreeKwd(kwd)) ; object->first_keyword = NULL; object->last_keyword = NULL; } return(kwd); } /* End: "OdlFreeAllKwds" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlFreeKwd */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine frees the memory used by a keyword. The return */ /* value is always a pointer to the right sibling of the keyword. */ /* */ /************************************************************************/ #ifdef _NO_PROTO KEYWORD *OdlFreeKwd (keyword) KEYWORD *keyword; #else KEYWORD *OdlFreeKwd (KEYWORD *keyword) #endif { KEYWORD *next_kwd = {NULL}; if (keyword != NULL) { next_kwd = keyword->right_sibling; LemmeGo(keyword->name) LemmeGo(keyword->file_name) LemmeGo(keyword->value) LemmeGo(keyword->pre_comment) LemmeGo(keyword->line_comment) LemmeGo(keyword) } return(next_kwd); } /* End: "OdlFreeKwd" */ /*========================================================================*/ /* */ /* File and File Name routines */ /* */ /*========================================================================*/ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlOpenMessageFile */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine returns a pointer to an opened file based on */ /* what is passed in. If message_fptr is not NULL, the we assume */ /* that the file is already open and return message_fptr. If */ /* message_fname is NULL, or we can't open message_fname, then */ /* we return stdout. If message_fname can be opened, then we */ /* return a pointer to the newly opened file. */ /* */ /************************************************************************/ #ifdef _NO_PROTO FILE *OdlOpenMessageFile (message_fname, message_fptr) char *message_fname; FILE *message_fptr; #else FILE *OdlOpenMessageFile (char *message_fname, FILE *message_fptr) #endif { FILE *fptr = {stdout}; char *c = message_fname; if (message_fptr != NULL) fptr = message_fptr; else if (message_fname != NULL && ! odl_suppress_messages) { if ((fptr = (FILE *) fopen(message_fname, "a")) == NULL) { fptr = stdout; OdlPrintMessage(NULL, NULL, 0, "Unable to open the output file. Messages will be written to the terminal"); } } return(fptr); } /* End routine: "OdlOpenMessageFile" */ /************************************************************************/ /* */ /* Component: */ /* */ /* OdlGetFileName */ /* */ /* Author: */ /* */ /* David P. Bernath (Jet Propulsion Laboratory) */ /* */ /* Version: */ /* */ /* 1.0 March 31, 1994 */ /* */ /* Change History: */ /* */ /* 03-31-94 Original code */ /* */ /*----------------------------------------------------------------------*/ /* */ /* Description: */ /* */ /* This routine extracts the file name from a "^" keyword, */ /* allocates storage for it, and returns a pointer to this new */ /* character string. It also returns information about where */ /* the data actually begins in the file. */ /* */ /* For example, lets say we're looking at a label in a file */ /* called test.lbl, and we want to get the file name assocated */ /* the FNAME keyword. Here are the possible values this keyword */ /* might have, and what information would be returned for each */ /* possibility: */ /* */ /* ^FNAME = 17 */ /* */ /* file name : test.lbl (attached) */ /* *start_location : 17 */ /* *start_location type : ODL_RECORD_LOCATION */ /* */ /* ^FNAME = 29 */ /* */ /* file name : test.lbl (attached) */ /* *start_location : 29 */ /* *start_location type : ODL_RECORD_LOCATION */ /* */ /* ^FNAME = 197 */ /* */ /* file name : test.lbl (attached) */ /* *start_location : 197 */ /* *start_location type : ODL_RECORD_LOCATION */ /* */ /* ^FNAME = 346 */ /* */ /* file name : test.lbl (attached) */ /* *start_location : 346 */ /* *start_location type : ODL_BYTE_LOCATION */ /* */ /* ^FNAME = 2189 */ /* */ /* file name : test.lbl (detached) */ /* *start_location : 2189 */ /* *start_location type : ODL_BYTE_LOCATION */ /* */ /* ^FNAME = "file_name.dat" */ /* */ /* file name : file_name.dat (detached) */ /* *start_location : 1 */ /* *start_location type : ODL_RECORD_LOCATION */ /* */ /* ^FNAME = ("file_name.dat", 17) */ /* */ /* file name : file_name.dat (detached) */ /* *start_location : 17 */ /* *start_location type : ODL_RECORD_LOCATION */ /* */ /* ^FNAME = ("file_name.dat", 29 ) */ /* */ /* file name : file_name.dat (detached) */ /* *start_location : 29 */ /* *start_location type : ODL_RECORD_LOCATION */ /* */ /* ^FNAME = ("file_name.dat", 197 ) */ /* */ /* file name : file_name.dat (detached) */ /* *start_location : 197 */ /* *start_location type : ODL_RECORD_LOCATION */ /* */ /* ^FNAME = ("file_name.dat", 346 ) */ /* */ /* file name : file_name.dat (detached) */ /* *start_location : 346 */ /* *start_location type : ODL_BYTE_LOCATION */ /* */ /* ^FNAME = ("file_name.dat", 2189 ) */ /* */ /* file name : file_name.dat (detached) */ /* *start_location : 2189 */ /* *start_location type : ODL_BYTE_LOCATION */ /* */ /************************************************************************/ #ifdef _NO_PROTO char *OdlGetFileName (keyword, start_location, start_location_type) KEYWORD *keyword; unsigned long *start_location; unsigned short *start_location_type; #else char *OdlGetFileName (KEYWORD *keyword, unsigned long *start_location, unsigned short *start_location_type) #endif { char *fname = {NULL}; char *text = {NULL}; char *unit = {NULL}; char *first_word = {NULL}; char *second_word = {NULL}; if (keyword != NULL) { /* Make a copy of the keyword's value */ CopySt