;;--------------------------------------------------------------------------- ;; Name: VERIFY_LABEL ;; ;; Purpose: To verify the contents of a PDS label. ;; ;; Calling Sequence: ;; verify_label, label ;; ;; Input: ;; label - a string array containing contents of a PDS label. ;; ;; Output: ;; This routine croaks if there is an error in the label. ;; ;; Optional inputs: none ;; ;; External routines: Pdspar, Get_index, Verify_image, Verify_table, ;; Verify_qube, Verify_arrcol, Clean, Remove, Pointpds ;; ;; Modification history: ;; Written by Puneet Khetarpal, 30 June 2005 ;; ;;--------------------------------------------------------------------------- ;-- level 2 ----------------------------------------------------------------- ; precondition: there is no end object value present for current ; element in label, and objarray value has the value needed to be placed ; in end_object keyword ; postcondition: the value is inserted function add_end_object, element, name ; error check on_error, 1 ; remove all padding chars from element element = remove(element, string([10B, 13B])) ; remove lf and cr chars element = strtrim(element) ; remove trailing blanks from the string ; add name to element object after '=' sign element += ' = ' + name + string([13B, 10B]) return, element end ;-- level 1 ----------------------------------------------------------------- ; precondition: none ; postcondition: checks for number of elements >= 2 and for comments. Note, ; label is passed by reference. pro check_comments, label ; error checking on_error, 1 ; check for number of elements of label if (n_elements(label) lt 2) then begin message, "Error: PDS label must have two or more elements" endif ; go through the label and extract the comments where they exist comm_check = stregex(label, '/\*') ; check which elements have comm comm_pos = where(comm_check ne -1, comm_cnt) ; extract index for comments ; if comments are found in label if (comm_cnt gt 0) then begin for i = 0, comm_cnt - 1 do begin ; go through the records that have elem = label[comm_pos[i]] ; store line length = comm_check[comm_pos[i]] - 1 ; store length to be saved label[comm_pos[i]] = strmid(elem, 0, length) ; extract string label[comm_pos[i]] += string([13B, 10B]) ; add lf cr chars endfor endif end ; precondition: the input is first two elements of label array ; postcondition: the label is checked for sfdu label and pds_version_id ; keywords. pro check_sfdu_pds, record1, record2 ; error checking on_error, 1 ; return to main level of program ; first check for pds version id keyword in first two records if (~ stregex(record1, 'SFDU', /boolean)) && $ (~ stregex(record1, 'PDS_VERSION_ID += +PDS3', /boolean)) && $ (~ stregex(record2, 'PDS_VERSION_ID += +PDS3', /boolean)) && $ (~ stregex(record1, 'XV_COMPATIBILITY', /boolean)) then begin message, "Error: No PDS_VERSION_ID keyword found in label." endif end ; precondition: the input is the last element of label array ; postcondition: the label is checked for the end statement pro check_end, record ; error checking on_error, 1 ; return to main level of program ;; check for end statement if (~ stregex(record, '^END *', /boolean)) then begin message, "Error: No END statement found as last record for label." endif end ;; precondition: label has been tested for pds_version_id and end keyword ;; postcondition: each keyword in the label is searched for '=' and a ;; value after it. pro check_keys_values, label ; local variable cr = string(13b) lf = string(10b) ; error checking on_error, 1 ; return to main level of program ;; go through each record in label and search for '=' for i = 0, n_elements(label) - 1 do begin if (stregex(label[i], ' = ', /boolean)) && $ ~(stregex(label[i], '= +[^ ' + cr + lf +']+', /boolean)) then begin message, "Error: No value for keyword found " + label[i] endif endfor end ; precondition: label has been tested for pds_version_id and end ; keyword ; postcondition: the label is now tested for the file characteristics ; data elements keywords pro check_file_chars_elements, label ; error checking on_error, 1 ; return to main level of program ; check for the record type rec_type = pdspar(label, 'record_type', COUNT=rtcnt) ; extract from lbl rec_type = remove(rec_type, '"') if (rtcnt eq 0) then begin ; if none found, then issue error message, "Error: no RECORD_TYPE keyword found in label" endif else if (rtcnt gt 1) then begin ; if more than one, then error message, "Error: multiple RECORD_TYPE keywords found; " + $ clean(string(rtcnt), /space) ; if doesn't match fixed_length, stream, variable_length, or undefined ; then issue error endif else if ((clean(rec_type, /space) ne "FIXED_LENGTH") && $ (clean(rec_type, /space) ne "STREAM") && $ (clean(rec_type, /space) ne "VARIABLE_LENGTH") && $ (clean(rec_type, /space) ne "UNDEFINED")) then begin message, "Error: invalid value for RECORD_TYPE found; " + rec_type endif ; check for record bytes if rec type fixed or variable length if (rec_type ne "UNDEFINED" && rec_type ne "STREAM") then begin rec_bytes = pdspar(label, 'record_bytes', COUNT=rbcnt) ; extract if (rbcnt eq 0) then begin ; if none found, then issue error message, "Error: no RECORD_BYTES keyword found in label" endif else if (rbcnt gt 1) then begin ; if more than one, then error message, "Error: multiple RECORD_BYTES keywords found; " + $ clean(string(rbcnt), /space) endif else if (fix(rec_bytes[0]) lt 0) then begin ; if < 0, then err message, "Error: RECORD_BYTES value must be >= 0; " + rec_bytes[0] endif endif end ; precondition: label has been tested for file characteristic elements ; postcondition: the file pointer keywords are tested and checked for ; validity. Also, determines whether corresponding OBJECT keyword ; exists in label. pro check_label_pointers, label, filename ; error checking on_error, 1 ;; first extract all names data object pointers keywords point_check = stregex(label, '\^([0-9a-z_A-Z]+)') ; get locations of ^ char point_pos = where(point_check ne -1, pointcnt) ; find matches if (pointcnt eq 0) then begin ; if no matches then message, "Error: No pointer keywords found in label" ; issue error endif ; extract names from label locations names = stregex(label[point_pos], '\^([0-9a-zA-Z_]+)', /subexpr, /extract) objnames = names[1,*] ; store in array ; remove all non-object or non-structure pointer names expr = '(CATALOG$)|(PROJECTION$)|(TEXT$)|(DESC$)|(DESCRIPTION$)' pos = where(stregex(objnames, expr, /boolean) eq 0, matches) if (matches eq 0) then begin message, "Error: No viable pointer keywords found in label" ; issue err endif objnames = objnames[pos] ; store object/structure pointer names ; check fo objects corresponding to each pointer object objects = pdspar(label, 'OBJECT', COUNT=objcnt) ; check for object objects = strtrim(objects) if (objcnt eq 0) then begin message, "Error: No object keywords found in label" ; issue error endif ; process pointer values for errors using pointpds for i = 0, n_elements(objnames) - 1 do begin pointer = pointpds(label, filename, objnames[i]) ; check for pointer ; check for correspsonding OBJECT keyword in label check = stregex(objects, '^'+objnames[i]+' *$', /boolean) poscheck = where(check eq 1, checkcnt) ; determine where matched if (checkcnt eq 0) then begin ; if not matched then issue error message, "Error: No OBJECT corresponding to ^" + objnames[i] + $ " pointer found in label" endif endfor end ; precondition: there exist object keywords in the label, and comments ; have been eliminated from the label. ; postcondition: the object and end-object keywords are matched for ; consistency pro check_end_object, label ; error checking on_error, 1 ; extract all object keywords values and indices obj_names = pdspar(label, 'object', COUNT=obj_count, INDEX=obj_index) obj_names = strtrim(obj_names, 2) objarray = strarr(obj_count) ;; extract all end object keywords values and indices eobj_names = pdspar(label, 'end_object', COUNT=eobj_count,INDEX=eobj_index) eobj_names = strtrim(eobj_names, 2) ; process the entire label count = 0 ; counter for the object array contents for i = 0, n_elements(label) - 1 do begin ; loop through elements pos = where(obj_index eq i, matchcnt) ; match cur index in obj index if (matchcnt gt 0) then begin ; if matched, then add to objarray[count] = obj_names[pos] ; objarray stack count++ ; increment counter endif ;; test for end object keyword in label test = stregex(label[i], 'END_OBJECT', /boolean) if (test && (count gt 0)) then begin ; if found and count > 0 if (eobj_count gt 0) then begin ; if end object keyword value found ;; match current index in end object values indices pos = where(eobj_index eq i, matchcnt) ;; if matched and last element in objarray != end ;; object value at matched position, then issue error if ((matchcnt gt 0) && (objarray[count-1] ne $ eobj_names[pos])) then begin message, "Error: OBJECT and END_OBJECT keyword " + $ "mismatch - "+ objarray[count-1] + " " + eobj_names[pos] endif else if (matchcnt eq 0) then begin ;; add end object val label[i] = add_end_object(label[i], objarray[count-1]) endif endif else begin ;; add end object value to current element label[i] = add_end_object(label[i], objarray[count-1]) endelse count-- ;; if everything goes well, then decrement count endif else if (test && (count le 0)) then begin ; if count <= 0, err message, "Error: unmatched END_OBJECT keyword found in label" endif endfor ; if count != 0 that means there is still an unmatched OBJECT keyword if (count ne 0) then begin ; issue error message, "Error: inconsistent pair of OBJECT-END_OBJECT keywords" + $ "found" endif end ; precondition: there exist PDS objects in label ; postcondition: each object is verified according to the PDS standards. pro check_objects, label ; error check on_error, 1 ; first check for image objects test = verify_image(label) test = verify_table(label) test = verify_qube(label) test = verify_arrcol(label) ; check for bit element, bit column and container objects objects = pdspar(label, 'OBJECT') objects = strtrim(objects) pos = where(stregex(objects, '(BIT_ELEMENT)|(BIT_COLUMN)|(CONTAINER)', $ /boolean) eq 1, matches) if (matches gt 0) then begin message, "Die Fetcher!: BIT_COLUMN, BIT_ELEMENT or CONTAINER object" +$ " found. Currently not supported by PDSREAD." endif end ;-- level 0 ----------------------------------------------------------------- ; precondition: label is a string array containing the contents of the label ; for the data product; and filename is the name of the label file ; postcondition: the contents of the label array are verified for viability. ; an stderror is returned if there is something wrong, and a ; boolean to show whether verified or not. function verify_label, lbl, filename ; error checking on_error, 1 ; return to main level of program ; save lbl array label = lbl ; check label for its elements and comments check_comments, label ; check whether label has pds_version_id keywords check_sfdu_pds, label[0], label[1] ;; check whether the last record has end statement check_end, label[n_elements(label)-1] ;; check whether all keywords have values with '=' signs check_keys_values, label ;; check for file characteristics keywords for label check_file_chars_elements, label ;; check for object pointers check_label_pointers, label, filename ;; check for end_object consistency check_end_object, label ;; check for image objects check_objects, label return, 1 end