/*----------------------------------------------------------------------*\
 | Check syntax of metadata entries.  The only things in this module	|
 | that are public are check_syntax and summarize_errors.  Everything	|
 | else is static.														|
 |																		|
 | Errors are noted when an element is									|
 |	1. unrecognized														|
 |	2. in the wrong place												|
 |	3. repeated too many times											|
 |	4. required but missing												|
 |	5. value is empty but shouldn't be									|
 |	6. improper value													|
 |																		|
 | These are described above in rough order of decreasing severity. 	|
 |																		|
 | Peter N. Schweitzer (U.S. Geological Survey, Reston, VA 20192)		|
\*----------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "keyword.h"
#include "item.h"
#include "local.h"
#include "stricmp.h"
extern double strtod (const char *s, char **t);
extern int check_text_values;
extern char *profile_name;
static int bio_profile = -1;
static int  sh_profile = -1;
static int  rs_profile = -1;
extern FILE *out;
struct error_t {
	int unrecognized;
	int misplaced;
	int too_many;
	int missing;
	int empty;
	int bad_value;
	};
static struct error_t errors = {0,0,0,0,0,0};
/*----------------------------------------------------------------------*\
 | Functions that detect common errors and print appropriate messages.	|
\*----------------------------------------------------------------------*/
static int allow (struct item *p, ...) {
	int err = 0;
	struct item *q;
	va_list ap;
	enum fgdc_keyword key;
	if (!p->child) err = 0;
	for (q=p->child; q; q=q->next)
		if (q->key != Wblank) {
			va_start (ap,p);
			while ((key = va_arg (ap,enum fgdc_keyword)) != Wnull)
				if (q->key == key) break;
			va_end (ap);
			if (is_extension (q->key))
				if (parent_child (p->key,q->key)) break;
				else {
					errors.misplaced++;
					err++;
					}
			if (key == Wnull) {
				if (q->key == Wunknown) {
					fprintf (out,"Error (line %d): no element recognized in \"%s\"; text is not permitted in %s\n",
						q->line_number,q->d,text_of(p->key));
					errors.unrecognized++;
					}
				else {
					/*--------------------------------------------------*\
					 | With the proliferation of extensions, we might	|
					 | assume that people know what they're doing when	|
					 | they put extensions willy-nilly in the metadata.	|
					 | So generate an error message only if this is a	|
					 | standard element in the wrong place, not if it's	|
					 | an extension or profile element.					|
					 | For an extension out of place, just generate a	|
					 | warning, not an error message.					|
					\*--------------------------------------------------*/
					if (is_standard (q->key)) {
						fprintf (out,"Error (line %d): %s is not permitted in %s\n",
							q->line_number,text_of(q->key),text_of(p->key));
						errors.misplaced++;
						}
					else {
						fprintf (out,"Warning (line %d): %s is not expected in %s\n",
							q->line_number,text_of(q->key),text_of(p->key));
						}
					}
				err++;
				}
			}
	return (err);
	}
static int require (struct item *p, ...) {
	int err = 0;
	struct item *q;
	va_list ap;
	enum fgdc_keyword key;
	if (!p->child) err = 1;
	va_start (ap,p);
	while ((key = va_arg (ap,enum fgdc_keyword)) != Wnull) {
		for (q=p->child; q; q=q->next) if (q->key == key) break;
		if (q == NULL) {
			fprintf (out,"Error (line %d): %s is required in %s\n",
				p->line_number,text_of(key),text_of(p->key));
			errors.missing++;
			err++;
			}
		}
	va_end (ap);
	return (err);
	}
static int count (struct item *p, enum fgdc_keyword key) {
	int n = 0;
	struct item *q;
	for (q=p->child; q; q=q->next) if (q->key == key) n++;
	return (n);
	}
static int limit (struct item *p, int m, ...) {
	int err = 0;
	int n = 0;
	struct item *q;
	va_list ap;
	enum fgdc_keyword key;
	if (!p->child) err = 0;
	va_start (ap,m);
	while ((key = va_arg (ap,enum fgdc_keyword)) != Wnull) {
		n = 0;
		for (q=p->child; q; q=q->next)
			if (q->key == key) {
				n++;
				if (n > m) {
					fprintf (out,"Error (line %d): too many %s found in %s\n",
						q->line_number,text_of(q->key),text_of(p->key));
					errors.too_many++;
					err++;
					}
				}
		}
	return (err);
	}
static int allow_one_of (struct item *p, ...) {
	int n = 0;
	int err = 0;
	struct item *q;
	va_list ap;
	enum fgdc_keyword key;
	if (!p->child) err = 0;
	for (q=p->child; q; q=q->next) {
		va_start (ap,p);
		while ((key = va_arg (ap,enum fgdc_keyword)) != Wnull)
			if (q->key == key) n++;
		va_end (ap);
		}
	if (n > 1) {
		va_start (ap,p);
		key = va_arg (ap,enum fgdc_keyword);
		fprintf (out,"Error (line %d): %s permits only one of %s ",
			p->line_number,text_of(p->key),text_of(key));
		while ((key = va_arg (ap,enum fgdc_keyword)) != Wnull)
			fprintf (out,"or %s ",text_of(key));
		fprintf (out,"\n");
		va_end (ap);
		errors.too_many++;
		err = 1;
		}
	return (err);
	}
static int require_one_of (struct item *p, ...) {
	int n = 0;
	int err = 0;
	struct item *q;
	va_list ap;
	enum fgdc_keyword key;
	if (!p->child) err = 1;
	for (q=p->child; q; q=q->next) {
		va_start (ap,p);
		while ((key = va_arg (ap,enum fgdc_keyword)) != Wnull)
			if (q->key == key) n++;
		va_end (ap);
		}
	if (n < 1) {
		va_start (ap,p);
		key = va_arg (ap,enum fgdc_keyword);
		fprintf (out,"Error (line %d): %s requires one of %s ",
			p->line_number,text_of(p->key),text_of(key));
		while ((key = va_arg (ap,enum fgdc_keyword)) != Wnull)
			fprintf (out,"or %s ",text_of(key));
		fprintf (out,"\n");
		va_end (ap);
		errors.missing++;
		err = 1;
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Metadata =
 |		Identification_Information +
 |		0{Data_Quality_Information}1 +
 |		0{Spatial_Data_Organization_Information}1 +
 |		0{Spatial_Reference_Information}1 +
 |		0{Entity_and_Attribute_Information}1 +
 |		0{Distribution_Information}n +
 |		Metadata_Reference_Information +
 |		0{Platform_and_Mission_Information}1 +	// Remote-sensing profile
 |		0{Instrument_Information}n				// Remote-sensing profile
\*----------------------------------------------------------------------*/
static int check_Metadata (struct item *p) {
	int err = 0;
	if (rs_profile)
		err += allow (p,
			WIdentification_Information,
			WData_Quality_Information,
			WSpatial_Data_Organization_Information,
			WSpatial_Reference_Information,
			WEntity_and_Attribute_Information,
			WDistribution_Information,
			WMetadata_Reference_Information,
			WPlatform_and_Mission_Information,
			WInstrument_Information,
			Wnull);
	else
		err += allow (p,
			WIdentification_Information,
			WData_Quality_Information,
			WSpatial_Data_Organization_Information,
			WSpatial_Reference_Information,
			WEntity_and_Attribute_Information,
			WDistribution_Information,
			WMetadata_Reference_Information,
			Wnull);
	err += require (p,
		WIdentification_Information,
		WMetadata_Reference_Information,
		Wnull);
	err += limit (p,1,
		WIdentification_Information,
		WData_Quality_Information,
		WSpatial_Data_Organization_Information,
		WSpatial_Reference_Information,
		WEntity_and_Attribute_Information,
		WMetadata_Reference_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Identification_Information =
 |		Dataset_Identifier +							// Remote-sensing
 |		Citation +
 |		Description +
 |		Time_Period_of_Content +
 |		Status +
 |		Spatial_Domain +								// in BDP, is mandatory if applicable
 |		0{Processing_Level}n +							// Remote-sensing
 |		Keywords +
 |		0{Taxonomy}1 +									// Biological data profile
 |		0{Platform_and_Instrument_Identification}n +	// Remote-sensing
 |		[Band_Identification |							// Remote-sensing
 |		Thematic_Layer_Identification] +				// Remote-sensing
 |		Access_Constraints +
 |		Use_Constraints +
 |		(Point_of_Contact) +
 |		(1{Browse_Graphic}n) +
 |		(Data_Set_Credit) +
 |		(Security_Information) +
 |		(Native_Data_Set_Environment) +
 |		(1{Cross_Reference}n) +
 |		0{Aggregation_Information}n						// Remote-sensing
 |		0{Analytical_Tool}1								// Biological data profile
\*----------------------------------------------------------------------*/
static int check_Identification_Information (struct item *p) {
	int err = 0;
	if (bio_profile) {
		err += allow (p,
			WCitation,
			WDescription,
			WTime_Period_of_Content,
			WStatus,
			WSpatial_Domain,
			WKeywords,
			WTaxonomy,
			WAccess_Constraints,
			WUse_Constraints,
			WPoint_of_Contact,
			WBrowse_Graphic,
			WData_Set_Credit,
			WSecurity_Information,
			WNative_Data_Set_Environment,
			WCross_Reference,
			WAnalytical_Tool,
			Wnull);
		err += require (p,
			WCitation,
			WDescription,
			WTime_Period_of_Content,
			WStatus,
			WKeywords,
			WAccess_Constraints,
			WUse_Constraints,
			Wnull);
		err += limit (p,1,
			WCitation,
			WDescription,
			WTime_Period_of_Content,
			WStatus,
			WSpatial_Domain,
			WKeywords,
			WTaxonomy,
			WAccess_Constraints,
			WUse_Constraints,
			WPoint_of_Contact,
			WData_Set_Credit,
			WSecurity_Information,
			WNative_Data_Set_Environment,
			Wnull);
		}
	else
		if (rs_profile) {
			err += allow (p,
				WDataset_Identifier,
				WCitation,
				WDescription,
				WTime_Period_of_Content,
				WStatus,
				WSpatial_Domain,
				WProcessing_Level,
				WKeywords,
				WPlatform_and_Instrument_Identification,
				WBand_Identification,
				WThematic_Layer_Identification,
				WAccess_Constraints,
				WUse_Constraints,
				WPoint_of_Contact,
				WBrowse_Graphic,
				WData_Set_Credit,
				WSecurity_Information,
				WNative_Data_Set_Environment,
				WCross_Reference,
				WAggregation_Information,
				Wnull);
			err += require (p,
				WDataset_Identifier,
				WCitation,
				WDescription,
				WTime_Period_of_Content,
				WStatus,
				WSpatial_Domain,
				WKeywords,
				WAccess_Constraints,
				WUse_Constraints,
				Wnull);
			err += require_one_of (p,
				WBand_Identification,
				WThematic_Layer_Identification,
				Wnull);
			err += limit (p,1,
				WDataset_Identifier,
				WCitation,
				WDescription,
				WTime_Period_of_Content,
				WStatus,
				WSpatial_Domain,
				WKeywords,
				WBand_Identification,
				WThematic_Layer_Identification,
				WAccess_Constraints,
				WUse_Constraints,
				WPoint_of_Contact,
				WData_Set_Credit,
				WSecurity_Information,
				WNative_Data_Set_Environment,
				Wnull);
			}
		else {	/* Standard */
			err += allow (p,
				WCitation,
				WDescription,
				WTime_Period_of_Content,
				WStatus,
				WSpatial_Domain,
				WKeywords,
				WAccess_Constraints,
				WUse_Constraints,
				WPoint_of_Contact,
				WBrowse_Graphic,
				WData_Set_Credit,
				WSecurity_Information,
				WNative_Data_Set_Environment,
				WCross_Reference,
				Wnull);
			err += require (p,
				WCitation,
				WDescription,
				WTime_Period_of_Content,
				WStatus,
				WSpatial_Domain,
				WKeywords,
				WAccess_Constraints,
				WUse_Constraints,
				Wnull);
			err += limit (p,1,
				WCitation,
				WDescription,
				WTime_Period_of_Content,
				WStatus,
				WSpatial_Domain,
				WKeywords,
				WAccess_Constraints,
				WUse_Constraints,
				WPoint_of_Contact,
				WData_Set_Credit,
				WSecurity_Information,
				WNative_Data_Set_Environment,
				Wnull);
			}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Citation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Citation (struct item *p) {
	int err = 0;
	err += allow (p,WCitation_Information,Wnull);
	err += require (p,WCitation_Information,Wnull);
	err += limit (p,1,WCitation_Information,Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Description =
 |		Abstract +
 |		Purpose +
 |		Documentation +		// Remote-sensing profile
 |		(Supplemental_Information)
\*----------------------------------------------------------------------*/
static int check_Description (struct item *p) {
	int err = 0;
	if (rs_profile)
		err += allow (p,
			WAbstract,
			WPurpose,
			WDocumentation,
			WSupplemental_Information,
			Wnull);
	else
		err += allow (p,
			WAbstract,
			WPurpose,
			WSupplemental_Information,
			Wnull);
	err += require (p,
		WAbstract,
		WPurpose,
		Wnull);
	err += limit (p,1,
		WAbstract,
		WPurpose,
		WSupplemental_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Time_Period_of_Content =
 |		Time_Period_Information +
 |		Currentness_Reference
\*----------------------------------------------------------------------*/
static int check_Time_Period_of_Content (struct item *p) {
	int err = 0;
	err += allow (p,
		WTime_Period_Information,
		WCurrentness_Reference,
		Wnull);
	err += require (p,
		WTime_Period_Information,
		WCurrentness_Reference,
		Wnull);
	err += limit (p,1,
		WTime_Period_Information,
		WCurrentness_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Status =
 |		Progress +
 |		Maintenance_and_Update_Frequency
\*----------------------------------------------------------------------*/
static int check_Status (struct item *p) {
	int err = 0;
	err += allow (p,
		WProgress,
		WMaintenance_and_Update_Frequency,
		Wnull);
	err += require (p,
		WProgress,
		WMaintenance_and_Update_Frequency,
		Wnull);
	err += limit (p,1,
		WProgress,
		WMaintenance_and_Update_Frequency,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Spatial_Domain =
 |		Description_of_Geographic_Extent +		// Biological data profile
 |												// and Shoreline
 |		Bounding_Coordinates +
 |		(1{Data_Set_G-Polygon}n)
 |		(1{Frame_Area}n) +						// Remote-sensing
 |		(1{Multiple_Image_Alignment}n) +		// Remote-sensing
 |		(Worldwide_Reference_System)			// Remote-sensing
\*----------------------------------------------------------------------*/
static int check_Spatial_Domain (struct item *p) {
	int err = 0;
	if (bio_profile || sh_profile) {
		err += allow (p,
			WDescription_of_Geographic_Extent,
			WBounding_Coordinates,
			WData_Set_G_Polygon,
			Wnull);
		/*--------------------------------------------------------------*\
		 | In bio, Description_of_Geographic_Extent is mandatory; in	|
		 | shoreline, it's mandatory if applicable (puzzled look).		|
		\*--------------------------------------------------------------*/
		if (bio_profile)
			err += require (p,
				WDescription_of_Geographic_Extent,
				WBounding_Coordinates,
				Wnull);
		else
			err += require (p,
				WBounding_Coordinates,
				Wnull);
		err += limit (p,1,
			WDescription_of_Geographic_Extent,
			WBounding_Coordinates,
			Wnull);
		}
	else
		if (rs_profile) {
			err += allow (p,
				WBounding_Coordinates,
				WData_Set_G_Polygon,
				WFrame_Area,
				WMultiple_Image_Alignment,
				WWorldwide_Reference_System,
				Wnull);
			err += require (p,
				WBounding_Coordinates,
				Wnull);
			err += limit (p,1,
				WBounding_Coordinates,
				WWorldwide_Reference_System,
				Wnull);
			}
		else {	/* Standard */
			err += allow (p,
				WBounding_Coordinates,
				WData_Set_G_Polygon,
				Wnull);
			err += require (p,
				WBounding_Coordinates,
				Wnull);
			err += limit (p,1,
				WBounding_Coordinates,
				Wnull);
			}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Bounding_Coordinates =
 |		West_Bounding_Coordinate +
 |		East_Bounding_Coordinate +
 |		North_Bounding_Coordinate +
 |		South_Bounding_Coordinate +
 |		Bounding_Altitudes			// Biological data profile
\*----------------------------------------------------------------------*/
static int check_Bounding_Coordinates (struct item *p) {
	int err = 0;
	if (bio_profile) {
		err += allow (p,
			WWest_Bounding_Coordinate,
			WEast_Bounding_Coordinate,
			WNorth_Bounding_Coordinate,
			WSouth_Bounding_Coordinate,
			WBounding_Altitudes,
			Wnull);
		err += limit (p,1,
			WWest_Bounding_Coordinate,
			WEast_Bounding_Coordinate,
			WNorth_Bounding_Coordinate,
			WSouth_Bounding_Coordinate,
			WBounding_Altitudes,
			Wnull);
		}
	else {
		err += allow (p,
			WWest_Bounding_Coordinate,
			WEast_Bounding_Coordinate,
			WNorth_Bounding_Coordinate,
			WSouth_Bounding_Coordinate,
			Wnull);
		err += limit (p,1,
			WWest_Bounding_Coordinate,
			WEast_Bounding_Coordinate,
			WNorth_Bounding_Coordinate,
			WSouth_Bounding_Coordinate,
			Wnull);
		}
	err += require (p,
		WWest_Bounding_Coordinate,
		WEast_Bounding_Coordinate,
		WNorth_Bounding_Coordinate,
		WSouth_Bounding_Coordinate,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Bounding_Altitudes =		// Biological data profile
 |		Altitude_Minimum +
 |		Altitude_Maximum +
 |		Altitude_Distance_Units
\*----------------------------------------------------------------------*/
static int check_Bounding_Altitudes (struct item *p) {
	int err = 0;
	err += allow (p,
		WAltitude_Minimum,
		WAltitude_Maximum,
		WAltitude_Distance_Units,
		Wnull);
	err += require (p,
		WAltitude_Minimum,
		WAltitude_Maximum,
		WAltitude_Distance_Units,
		Wnull);
	err += limit (p,1,
		WAltitude_Minimum,
		WAltitude_Maximum,
		WAltitude_Distance_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Data_Set_G-Polygon =
 |		Data_Set_G-Polygon_Outer_G-Ring +
 |		0{Data_Set_G-Polygon_Exclusion_G-Ring}n
\*----------------------------------------------------------------------*/
static int check_Data_Set_G_Polygon (struct item *p) {
	int err = 0;
	err += allow (p,
		WData_Set_G_Polygon_Outer_G_Ring,
		WData_Set_G_Polygon_Exclusion_G_Ring,
		Wnull);
	err += require (p,
		WData_Set_G_Polygon_Outer_G_Ring,
		Wnull);
	err += limit (p,1,
		WData_Set_G_Polygon_Outer_G_Ring,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Data_Set_G-Polygon_Outer_G-Ring =
 |		4{G-Ring_Point}n |
 |		G-Ring
\*----------------------------------------------------------------------*/
static int check_Data_Set_G_Polygon_Outer_G_Ring (struct item *p) {
	int err = 0;
	int ip,ir;
	err += allow (p,
		WG_Ring_Point,
		WG_Ring,
		Wnull);
	ip = count (p,WG_Ring_Point);
	ir = count (p,WG_Ring);
	if (ir == 0 && ip < 4) {
		fprintf (out,"Error (line %d): no fewer than 4 %s are required in %s\n",
			p->line_number,text_of(WG_Ring_Point),text_of(p->key));
		errors.missing++;
		err++;
		}
	if (ir > 0 && ip > 0) {
		fprintf (out,"Error (line %d): %s permits %s or %s but not both\n",
			p->line_number,
			text_of(p->key),
			text_of(WG_Ring_Point),
			text_of(WG_Ring)
			);
		errors.too_many++;
		err++;
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Data_Set_G-Polygon_Exclusion_G-Ring =
 |		4{G-Ring_Point}n
 |		| G-Ring
\*----------------------------------------------------------------------*/
static int check_Data_Set_G_Polygon_Exclusion_G_Ring (struct item *p) {
	return (check_Data_Set_G_Polygon_Outer_G_Ring(p));
	}
/*----------------------------------------------------------------------*\
 |	G-Ring_Point =
 |		G-Ring_Latitude +
 |		G-Ring_Longitude +
\*----------------------------------------------------------------------*/
static int check_G_Ring_Point (struct item *p) {
	int err = 0;
	err += allow (p,
		WG_Ring_Latitude,
		WG_Ring_Longitude,
		Wnull);
	err += require (p,
		WG_Ring_Latitude,
		WG_Ring_Longitude,
		Wnull);
	err += limit (p,1,
		WG_Ring_Latitude,
		WG_Ring_Longitude,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Keywords =
 |		1{Theme}n +
 |		0{Place}n +
 |		0{Stratum}n +
 |		0{Temporal}n
\*----------------------------------------------------------------------*/
static int check_Keywords (struct item *p) {
	int err = 0;
	err += allow (p,
		WTheme,
		WPlace,
		WStratum,
		WTemporal,
		Wnull);
	err += require (p,
		WTheme,
		Wnull);
	err += limit (p,1,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Theme =
 |		Theme_Keyword_Thesaurus +
 |		1{Theme_Keyword}n
\*----------------------------------------------------------------------*/
static int check_Theme (struct item *p) {
	int err = 0;
	err += allow (p,
		WTheme_Keyword_Thesaurus,
		WTheme_Keyword,
		Wnull);
	err += require (p,
		WTheme_Keyword_Thesaurus,
		WTheme_Keyword,
		Wnull);
	err += limit (p,1,
		WTheme_Keyword_Thesaurus,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Place =
 |		Place_Keyword_Thesaurus +
 |		1{Place_Keyword}n
\*----------------------------------------------------------------------*/
static int check_Place (struct item *p) {
	int err = 0;
	err += allow (p,
		WPlace_Keyword_Thesaurus,
		WPlace_Keyword,
		Wnull);
	err += require (p,
		WPlace_Keyword_Thesaurus,
		WPlace_Keyword,
		Wnull);
	err += limit (p,1,
		WPlace_Keyword_Thesaurus,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Stratum =
 |		Stratum_Keyword_Thesaurus +
 |		1{Stratum_Keyword}n
\*----------------------------------------------------------------------*/
static int check_Stratum (struct item *p) {
	int err = 0;
	err += allow (p,
		WStratum_Keyword_Thesaurus,
		WStratum_Keyword,
		Wnull);
	err += require (p,
		WStratum_Keyword_Thesaurus,
		WStratum_Keyword,
		Wnull);
	err += limit (p,1,
		WStratum_Keyword_Thesaurus,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Temporal =
 |		Temporal_Keyword_Thesaurus +
 |		1{Temporal_Keyword}n
\*----------------------------------------------------------------------*/
static int check_Temporal (struct item *p) {
	int err = 0;
	err += allow (p,
		WTemporal_Keyword_Thesaurus,
		WTemporal_Keyword,
		Wnull);
	err += require (p,
		WTemporal_Keyword_Thesaurus,
		WTemporal_Keyword,
		Wnull);
	err += limit (p,1,
		WTemporal_Keyword_Thesaurus,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Taxonomy =
 |		1{Keywords_Taxon}n +
 |		0{Taxonomic_System}1 +
 |		(General_Taxonomic_Coverage) +
 |		1{Taxonomic_Classification}n	Changed 2001-02-27 at the request
 |										of Susan Stitt to reflect the
 |										intention of the BDP authors
\*----------------------------------------------------------------------*/
static int check_Taxonomy (struct item *p) {
	int err = 0;
	err += allow (p,
		WKeywords_Taxon,
		WTaxonomic_System,
		WGeneral_Taxonomic_Coverage,
		WTaxonomic_Classification,
		Wnull);
	err += require (p,
		WKeywords_Taxon,
		WTaxonomic_Classification,
		Wnull);
	err += limit (p,1,
		WTaxonomic_System,
		WGeneral_Taxonomic_Coverage,
		/* WTaxonomic_Classification, */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Keywords/Taxon =
 |		Taxonomic_Keyword_Thesaurus +
 |		1{Taxonomic_Keywords}n
\*----------------------------------------------------------------------*/
static int check_Keywords_Taxon (struct item *p) {
	int err = 0;
	err += allow (p,
		WTaxonomic_Keyword_Thesaurus,
		WTaxonomic_Keywords,
		Wnull);
	err += require (p,
		WTaxonomic_Keyword_Thesaurus,
		WTaxonomic_Keywords,
		Wnull);
	err += limit (p,1,
		WTaxonomic_Keyword_Thesaurus,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Taxonomic_System =
 |		1{Classification_System_Authority}n +
 |		0{Identification_Reference}n +
 |		(1{Identifier}n) +
 |		Taxonomic_Procedures +
 |		0{Taxonomic_Completeness}1 +
 |		0{Vouchers}n
\*----------------------------------------------------------------------*/
static int check_Taxonomic_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WClassification_System_Authority,
		WIdentification_Reference,
		WIdentifier,
		WTaxonomic_Procedures,
		WTaxonomic_Completeness,
		WVouchers,
		Wnull);
	err += require (p,
		WClassification_System_Authority,
		WTaxonomic_Procedures,
		Wnull);
	err += limit (p,1,
		WTaxonomic_Procedures,
		WTaxonomic_Completeness,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Classification_System_Authority =
 |		Classification_System_Citation +
 |		0{Classification_System_Modifications}1
\*----------------------------------------------------------------------*/
static int check_Classification_System_Authority (struct item *p) {
	int err = 0;
	err += allow (p,
		WClassification_System_Citation,
		WClassification_System_Modifications,
		Wnull);
	err += require (p,
		WClassification_System_Citation,
		Wnull);
	err += limit (p,1,
		WClassification_System_Citation,
		WClassification_System_Modifications,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Classification_System_Citation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Classification_System_Citation (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,
		Wnull);
	err += limit (p,1,
		WCitation_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Identification_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Identification_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,
		Wnull);
	err += limit (p,1,
		WCitation_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Identifier =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Identifier (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Information,
		Wnull);
	err += require (p,
		WContact_Information,
		Wnull);
	err += limit (p,1,
		WContact_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Vouchers =
 |		Specimen +
 |		Repository
\*----------------------------------------------------------------------*/
static int check_Vouchers (struct item *p) {
	int err = 0;
	err += allow (p,
		WSpecimen,
		WRepository,
		Wnull);
	err += require (p,
		WSpecimen,
		WRepository,
		Wnull);
	err += limit (p,1,
		WSpecimen,
		WRepository,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Repository =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Repository (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Information,
		Wnull);
	err += require (p,
		WContact_Information,
		Wnull);
	err += limit (p,1,
		WContact_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Taxonomic_Classification =
 |		Taxon_Rank_Name +
 |		Taxon_Rank_Value +
 |		(1{Applicable_Common_Name}n) +
 |		0{Taxonomic_Classification}n
\*----------------------------------------------------------------------*/
static int check_Taxonomic_Classification (struct item *p) {
	int err = 0;
	err += allow (p,
		WTaxon_Rank_Name,
		WTaxon_Rank_Value,
		WApplicable_Common_Name,
		WTaxonomic_Classification,
		Wnull);
	err += require (p,
		WTaxon_Rank_Name,
		WTaxon_Rank_Value,
		Wnull);
	err += limit (p,1,
		WTaxon_Rank_Name,
		WTaxon_Rank_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Point_of_Contact =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Point_of_Contact (struct item *p) {
	int err = 0;
	err += allow (p,WContact_Information,Wnull);
	err += require (p,WContact_Information,Wnull);
	err += limit (p,1,WContact_Information,Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Browse_Graphic =
 |		Browse_Graphic_File_Name +
 |		Browse_Graphic_File_Description +
 |		Browse_Graphic_File_Type
\*----------------------------------------------------------------------*/
static int check_Browse_Graphic (struct item *p) {
	int err = 0;
	err += allow (p,
		WBrowse_Graphic_File_Name,
		WBrowse_Graphic_File_Description,
		WBrowse_Graphic_File_Type,
		Wnull);
	err += require (p,
		WBrowse_Graphic_File_Name,
		WBrowse_Graphic_File_Description,
		WBrowse_Graphic_File_Type,
		Wnull);
	err += limit (p,1,
		WBrowse_Graphic_File_Name,
		WBrowse_Graphic_File_Description,
		WBrowse_Graphic_File_Type,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Security_Information =
 |		Security_Classification_System +
 |		Security_Classification +
 |		Security_Handling_Description
\*----------------------------------------------------------------------*/
static int check_Security_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WSecurity_Classification_System,
		WSecurity_Classification,
		WSecurity_Handling_Description,
		Wnull);
	err += require (p,
		WSecurity_Classification_System,
		WSecurity_Classification,
		WSecurity_Handling_Description,
		Wnull);
	err += limit (p,1,
		WSecurity_Classification_System,
		WSecurity_Classification,
		WSecurity_Handling_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Cross_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Cross_Reference (struct item *p) {
	return (check_Citation(p));
	}
/*----------------------------------------------------------------------*\
 |	Analytical_Tool =
 |		Analytical_Tool_Description +
 |		Tool_Access_Information +
 |		(Tool_Contact) +
 |		(Tool_Citation)
\*----------------------------------------------------------------------*/
static int check_Analytical_Tool (struct item *p) {
	int err = 0;
	err += allow (p,
		WAnalytical_Tool_Description,
		WTool_Access_Information,
		WTool_Contact,
		WTool_Citation,
		Wnull);
	err += require (p,
		WAnalytical_Tool_Description,
		WTool_Access_Information,
		Wnull);
	err += limit (p,1,
		WAnalytical_Tool_Description,
		WTool_Access_Information,
		WTool_Contact,
		WTool_Citation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Tool_Access_Information =
 |		0{Online_Linkage}n +
 |		Tool_Access_Instructions +
 |		(Tool_Computer_and_Operating_System)
\*----------------------------------------------------------------------*/
static int check_Tool_Access_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WOnline_Linkage,
		WTool_Access_Instructions,
		WTool_Computer_and_Operating_System,
		Wnull);
	err += require (p,
		WTool_Access_Instructions,
		Wnull);
	err += limit (p,1,
		WTool_Access_Instructions,
		WTool_Computer_and_Operating_System,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Tool_Contact =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Tool_Contact (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Information,
		Wnull);
	err += require (p,
		WContact_Information,
		Wnull);
	err += limit (p,1,
		WContact_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Tool_Citation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Tool_Citation (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,
		Wnull);
	err += limit (p,1,
		WCitation_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Data_Quality_Information =
 |		0{Attribute_Accuracy}1 +
 |		Logical_Consistency_Report +
 |		Completeness_Report +
 |		0{Positional_Accuracy}1 +
 |		Lineage +
 |		(Image_Quality) +				// Remote-sensing
 |		(Acquisition_Information) +		// Remote-sensing
 |		(Cloud_Cover) +
 |		0{Tidal_Information}1 +			// Shoreline profile
 |		0{Marine_Weather_Condition}1 +	// Shoreline profile
 |		0{Environmental_Event}1			// Shoreline profile
\*----------------------------------------------------------------------*/
static int check_Data_Quality_Information (struct item *p) {
	int err = 0;
	if (sh_profile)
		err += allow (p,
			WAttribute_Accuracy,
			WLogical_Consistency_Report,
			WCompleteness_Report,
			WPositional_Accuracy,
			WLineage,
			WCloud_Cover,
			WTidal_Information,
			WMarine_Weather_Condition,
			WEnvironmental_Event,
			Wnull);
	else
		if (rs_profile)
			err += allow (p,
				WAttribute_Accuracy,
				WLogical_Consistency_Report,
				WCompleteness_Report,
				WPositional_Accuracy,
				WLineage,
				WImage_Quality,
				WAcquisition_Information,
				WCloud_Cover,
				Wnull);
		else	/* Standard */
			err += allow (p,
				WAttribute_Accuracy,
				WLogical_Consistency_Report,
				WCompleteness_Report,
				WPositional_Accuracy,
				WLineage,
				WCloud_Cover,
				Wnull);
	err += require (p,
		WLogical_Consistency_Report,
		WCompleteness_Report,
		WLineage,
		Wnull);
	err += limit (p,1,
		WAttribute_Accuracy,
		WLogical_Consistency_Report,
		WCompleteness_Report,
		WPositional_Accuracy,
		WLineage,
		WCloud_Cover,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Attribute_Accuracy =
 |		Attribute_Accuracy_Report +
 |		(1{Quantitative_Attribute_Accuracy_Assessment}n)
\*----------------------------------------------------------------------*/
static int check_Attribute_Accuracy (struct item *p) {
	int err = 0;
	err += allow (p,
		WAttribute_Accuracy_Report,
		WQuantitative_Attribute_Accuracy_Assessment,
		Wnull);
	err += require (p,
		WAttribute_Accuracy_Report,
		Wnull);
	err += limit (p,1,
		WAttribute_Accuracy_Report,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Quantitative_Attribute_Accuracy_Assessment =
 |		Attribute_Accuracy_Value +
 |		Attribute_Accuracy_Explanation
\*----------------------------------------------------------------------*/
static int check_Quantitative_Attribute_Accuracy_Assessment (struct item *p) {
	int err = 0;
	err += allow (p,
		WAttribute_Accuracy_Value,
		WAttribute_Accuracy_Explanation,
		Wnull);
	err += require (p,
		WAttribute_Accuracy_Value,
		WAttribute_Accuracy_Explanation,
		Wnull);
	err += limit (p,1,
		WAttribute_Accuracy_Value,
		WAttribute_Accuracy_Explanation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Positional_Accuracy =
 |		0{Horizontal_Positional_Accuracy}1 +
 |		0{Vertical_Positional_Accuracy}1
\*----------------------------------------------------------------------*/
static int check_Positional_Accuracy (struct item *p) {
	int err = 0;
	err += allow (p,
		WHorizontal_Positional_Accuracy,
		WVertical_Positional_Accuracy,
		Wnull);
	err += limit (p,1,
		WHorizontal_Positional_Accuracy,
		WVertical_Positional_Accuracy,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Horizontal_Positional_Accuracy =
 |		Horizontal_Positional_Accuracy_Report +
 |		(1{Quantitative_Horizontal_Positional_Accuracy_Assessment}n)
\*----------------------------------------------------------------------*/
static int check_Horizontal_Positional_Accuracy (struct item *p) {
	int err = 0;
	err += allow (p,
		WHorizontal_Positional_Accuracy_Report,
		WQuantitative_Horizontal_Positional_Accuracy_Assessment,
		Wnull);
	err += require (p,
		WHorizontal_Positional_Accuracy_Report,
		Wnull);
	err += limit (p,1,
		WHorizontal_Positional_Accuracy_Report,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Quantitative_Horizontal_Positional_Accuracy_Assessment =
 |		Horizontal_Positional_Accuracy_Value +
 |		Horizontal_Positional_Accuracy_Explanation
\*----------------------------------------------------------------------*/
static int check_Quantitative_Horizontal_Positional_Accuracy_Assessment (struct item *p) {
	int err = 0;
	err += allow (p,
		WHorizontal_Positional_Accuracy_Value,
		WHorizontal_Positional_Accuracy_Explanation,
		Wnull);
	err += require (p,
		WHorizontal_Positional_Accuracy_Value,
		WHorizontal_Positional_Accuracy_Explanation,
		Wnull);
	err += limit (p,1,
		WHorizontal_Positional_Accuracy_Value,
		WHorizontal_Positional_Accuracy_Explanation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Vertical_Positional_Accuracy =
 |		Vertical_Positional_Accuracy_Report +
 |		(1{Quantitative_Vertical_Positional_Accuracy_Assessment}n)
\*----------------------------------------------------------------------*/
static int check_Vertical_Positional_Accuracy (struct item *p) {
	int err = 0;
	err += allow (p,
		WVertical_Positional_Accuracy_Report,
		WQuantitative_Vertical_Positional_Accuracy_Assessment,
		Wnull);
	err += require (p,
		WVertical_Positional_Accuracy_Report,
		Wnull);
	err += limit (p,1,
		WVertical_Positional_Accuracy_Report,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Quantitative_Vertical_Positional_Accuracy_Assessment =
 |		Vertical_Positional_Accuracy_Value +
 |		Vertical_Positional_Accuracy_Explanation
\*----------------------------------------------------------------------*/
static int check_Quantitative_Vertical_Positional_Accuracy_Assessment (struct item *p) {
	int err = 0;
	err += allow (p,
		WVertical_Positional_Accuracy_Value,
		WVertical_Positional_Accuracy_Explanation,
		Wnull);
	err += require (p,
		WVertical_Positional_Accuracy_Value,
		WVertical_Positional_Accuracy_Explanation,
		Wnull);
	err += limit (p,1,
		WVertical_Positional_Accuracy_Value,
		WVertical_Positional_Accuracy_Explanation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Lineage =
 |		0{Methodology}n +			// Biological data profile
 |		0{Source_Information}n +
 |		1{Process_Step}n +
 |		0{Process_Step_Citation}1	// Shoreline profile
\*----------------------------------------------------------------------*/
static int check_Lineage (struct item *p) {
	int err = 0;
	if (bio_profile)
		err += allow (p,
			WMethodology,
			WSource_Information,
			WProcess_Step,
			Wnull);
	else
		if (sh_profile)
			err += allow (p,
				WSource_Information,
				WProcess_Step,
				WProcess_Step_Citation,
				Wnull);
		else
			err += allow (p,
				WSource_Information,
				WProcess_Step,
				Wnull);
	err += require (p,
		WProcess_Step,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Methodology =
 |		Methodology_Type +
 |		(1{Methodology_Identifier}n) +
 |		Methodology_Description +
 |		0{Methodology_Citation}n
\*----------------------------------------------------------------------*/
static int check_Methodology (struct item *p) {
	int err = 0;
	err += allow (p,
		WMethodology_Type,
		WMethodology_Identifier,
		WMethodology_Description,
		WMethodology_Citation,
		Wnull);
	err += require (p,
		WMethodology_Type,
		WMethodology_Description,
		Wnull);
	err += limit (p,1,
		WMethodology_Type,
		WMethodology_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Methodology_Identifier =
 |		Methodology_Keyword_Thesaurus +
 |		1{Methodology_Keyword}n
\*----------------------------------------------------------------------*/
static int check_Methodology_Identifier (struct item *p) {
	int err = 0;
	err += allow (p,
		WMethodology_Keyword_Thesaurus,
		WMethodology_Keyword,
		Wnull);
	err += require (p,
		WMethodology_Keyword_Thesaurus,
		WMethodology_Keyword,
		Wnull);
	err += limit (p,1,
		WMethodology_Keyword_Thesaurus,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Methodology_Citation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Methodology_Citation (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,
		Wnull);
	err += limit (p,1,
		WCitation_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Source_Information =
 |		Source_Citation +
 |		0{Source_Scale_Denominator}1 +
 |		Type_of_Source_Media +
 |		Source_Time_Period_of_Content +
 |		Source_Citation_Abbreviation +
 |		Source_Contribution
\*----------------------------------------------------------------------*/
static int check_Source_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WSource_Citation,
		WSource_Scale_Denominator,
		WType_of_Source_Media,
		WSource_Time_Period_of_Content,
		WSource_Citation_Abbreviation,
		WSource_Contribution,
		Wnull);
	err += require (p,
		WSource_Citation,
		WType_of_Source_Media,
		WSource_Time_Period_of_Content,
		WSource_Citation_Abbreviation,
		WSource_Contribution,
		Wnull);
	err += limit (p,1,
		WSource_Citation,
		WSource_Scale_Denominator,
		WType_of_Source_Media,
		WSource_Time_Period_of_Content,
		WSource_Citation_Abbreviation,
		WSource_Contribution,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Source_Citation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Source_Citation (struct item *p) {
	return (check_Citation(p));
	}
/*----------------------------------------------------------------------*\
 |	Source_Time_Period_of_Content =
 |		Time_Period_Information +
 |		Source_Currentness_Reference
\*----------------------------------------------------------------------*/
static int check_Source_Time_Period_of_Content (struct item *p) {
	int err = 0;
	err += allow (p,
		WTime_Period_Information,
		WSource_Currentness_Reference,
		Wnull);
	err += require (p,
		WTime_Period_Information,
		WSource_Currentness_Reference,
		Wnull);
	err += limit (p,1,
		WTime_Period_Information,
		WSource_Currentness_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Process_Step =
 |		Process_Description +
 |		0{Source_Used_Citation_Abbreviation}n +
 |		Process_Date +
 |		(Process_Time) +
 |		0{Source_Produced_Citation_Abbreviation}n +
 |		(Process_Contact) +
 |		(Algorithm_Information) +		// Remote-sensing
 |		(Processing_Information)		// Remote-sensing
\*----------------------------------------------------------------------*/
static int check_Process_Step (struct item *p) {
	int err = 0;
	if (rs_profile)
		err += allow (p,
			WProcess_Description,
			WSource_Used_Citation_Abbreviation,
			WProcess_Date,
			WProcess_Time,
			WSource_Produced_Citation_Abbreviation,
			WProcess_Contact,
			WAlgorithm_Information,
			WProcessing_Information,
			Wnull);
	else	/* Standard */
		err += allow (p,
			WProcess_Description,
			WSource_Used_Citation_Abbreviation,
			WProcess_Date,
			WProcess_Time,
			WSource_Produced_Citation_Abbreviation,
			WProcess_Contact,
			Wnull);
	err += require (p,
		WProcess_Description,
		WProcess_Date,
		Wnull);
	if (rs_profile)
		err += limit (p,1,
			WProcess_Description,
			WProcess_Date,
			WProcess_Time,
			WProcess_Contact,
			WAlgorithm_Information,
			WProcessing_Information,
			Wnull);
	else	/* Standard */
		err += limit (p,1,
			WProcess_Description,
			WProcess_Date,
			WProcess_Time,
			WProcess_Contact,
			Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Process_Contact =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Process_Contact (struct item *p) {
	return (check_Point_of_Contact(p));
	}
/*----------------------------------------------------------------------*\
 |	Spatial_Data_Organization_Information =
 |		0{Indirect_Spatial_Reference}1 +
 |		0{
 |		Direct_Spatial_Reference_Method +
 |		([Point_and_Vector_Object_Information |
 |		Raster_Object_Information])
 |		}1
\*----------------------------------------------------------------------*/
static int check_Spatial_Data_Organization_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WIndirect_Spatial_Reference,
		WDirect_Spatial_Reference_Method,
		WPoint_and_Vector_Object_Information,
		WRaster_Object_Information,
		Wnull);
	err += allow_one_of (p,
		WPoint_and_Vector_Object_Information,
		WRaster_Object_Information,
		Wnull);
	if (count (p,WPoint_and_Vector_Object_Information) > 0 ||
		count (p,WRaster_Object_Information) > 0)
		err += require (p,
			WDirect_Spatial_Reference_Method,
			Wnull);
	err += limit (p,1,
		WIndirect_Spatial_Reference,
		WDirect_Spatial_Reference_Method,
		WPoint_and_Vector_Object_Information,
		WRaster_Object_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Point_and_Vector_Object_Information =
 |		[1{SDTS_Terms_Description}n |
 |		VPF_Terms_Description]
\*----------------------------------------------------------------------*/
static int check_Point_and_Vector_Object_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WSDTS_Terms_Description,
		WVPF_Terms_Description,
		Wnull);
	err += require_one_of (p,
		WSDTS_Terms_Description,
		WVPF_Terms_Description,
		Wnull);
	err += limit (p,1,
		WVPF_Terms_Description,
		Wnull);
	if ((count (p,WSDTS_Terms_Description) > 0) &&
		(count (p,WVPF_Terms_Description)  > 0)) {
		fprintf (out,"Error (line %d): %s permits %s or %s but not both\n",
			p->line_number,
			text_of(p->key),
			text_of(WSDTS_Terms_Description),
			text_of(WVPF_Terms_Description)
			);
		errors.too_many++;
		err++;
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	SDTS_Terms_Description =
 |		SDTS_Point_and_Vector_Object_Type +
 |		(Point_and_Vector_Object_Count)
\*----------------------------------------------------------------------*/
static int check_SDTS_Terms_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WSDTS_Point_and_Vector_Object_Type,
		WPoint_and_Vector_Object_Count,
		Wnull);
	err += require (p,
		WSDTS_Point_and_Vector_Object_Type,
		Wnull);
	err += limit (p,1,
		WSDTS_Point_and_Vector_Object_Type,
		WPoint_and_Vector_Object_Count,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	VPF_Terms_Description =
 |		VPF_Topology_Level +
 |		1{VPF_Point_and_Vector_Object_Information}n
\*----------------------------------------------------------------------*/
static int check_VPF_Terms_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WVPF_Topology_Level,
		WVPF_Point_and_Vector_Object_Information,
		Wnull);
	err += require (p,
		WVPF_Topology_Level,
		WVPF_Point_and_Vector_Object_Information,
		Wnull);
	err += limit (p,1,
		WVPF_Topology_Level,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	VPF_Point_and_Vector_Object_Information =
 |		VPF_Point_and_Vector_Object_Type +
 |		(Point_and_Vector_Object_Count)
\*----------------------------------------------------------------------*/
static int check_VPF_Point_and_Vector_Object_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WVPF_Point_and_Vector_Object_Type,
		WPoint_and_Vector_Object_Count,
		Wnull);
	err += require (p,
		WVPF_Point_and_Vector_Object_Type,
		Wnull);
	err += limit (p,1,
		WVPF_Point_and_Vector_Object_Type,
		WPoint_and_Vector_Object_Count,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Raster_Object_Information =
 |		Cell_Value_Type +			// Remote-sensing
 |		[							// Remote-sensing
 |		Raster_Object_Type +
 |		(Row_Count +
 |		Column_Count +
 |		0{Vertical_Count}1)
 |		|							// Remote-sensing
 |		Dimension_Description]		// Remote-sensing
\*----------------------------------------------------------------------*/
static int check_Raster_Object_Information (struct item *p) {
	int err = 0;
	int nRow_Count,nColumn_Count,nVertical_Count;
	if (rs_profile)
		err += allow (p,
			WCell_Value_Type,
			WRaster_Object_Type,
			WRow_Count,
			WColumn_Count,
			WVertical_Count,
			WDimension_Description,
			Wnull);
	else	/* Standard */
		err += allow (p,
			WRaster_Object_Type,
			WRow_Count,
			WColumn_Count,
			WVertical_Count,
			Wnull);
	err += require (p,
		WRaster_Object_Type,
		Wnull);
	if (rs_profile)
		err += require_one_of (p,
			WRaster_Object_Type,
			WDimension_Description,
			Wnull);
	nRow_Count = count (p,WRow_Count);
	nColumn_Count = count (p,WColumn_Count);
	nVertical_Count = count (p,WVertical_Count);
	if (nVertical_Count > 0 && (nRow_Count == 0 || nColumn_Count == 0)) {
		fprintf (out,"Error (line %d): %s requires both %s and %s if %s is given\n",
			p->line_number,text_of(p->key),
			text_of(WRow_Count),
			text_of(WColumn_Count),
			text_of(WVertical_Count)
			);
		errors.missing++;
		err++;
		}
	if ((nRow_Count == 0 && nColumn_Count != 0) ||
		(nRow_Count != 0 && nColumn_Count == 0)) {
		fprintf (out,"Error (line %d): %s requires %s if %s is given, and vice versa\n",
			p->line_number,text_of(p->key),
			text_of(WRow_Count),
			text_of(WColumn_Count)
			);
		errors.missing++;
		err++;
		}
	err += limit (p,1,
		WRaster_Object_Type,
		WRow_Count,
		WColumn_Count,
		WVertical_Count,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Spatial_Reference_Information =
 |		0{Horizontal_Coordinate_System_Definition}1 +
 |		0{Vertical_Coordinate_System_Definition}1 +
 |		0{Georeferencing_Information}1			// Remote-sensing
\*----------------------------------------------------------------------*/
static int check_Spatial_Reference_Information (struct item *p) {
	int err = 0;
	if (rs_profile)
		err += allow (p,
			WHorizontal_Coordinate_System_Definition,
			WVertical_Coordinate_System_Definition,
			WGeoreferencing_Information,
			Wnull);
	else	/* Standard */
		err += allow (p,
			WHorizontal_Coordinate_System_Definition,
			WVertical_Coordinate_System_Definition,
			Wnull);
	err += limit (p,1,
		WHorizontal_Coordinate_System_Definition,
		WVertical_Coordinate_System_Definition,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Horizontal_Coordinate_System_Definition =
 |		[Geographic |
 |		1{Planar}n |
 |		Local] +
 |		0{Geodetic_Model}1
\*----------------------------------------------------------------------*/
static int check_Horizontal_Coordinate_System_Definition (struct item *p) {
	int err = 0;
	int nGeographic = 0;
	int nPlanar = 0;
	int nLocal = 0;
	err += allow (p,
		WGeographic,
		WPlanar,
		WLocal,
		WGeodetic_Model,
		Wnull);
	if (count (p,WGeographic) > 0) nGeographic = 1;
	if (count (p,WPlanar) > 0) nPlanar = 1;
	if (count (p,WLocal) > 0) nLocal = 1;
	if (nGeographic + nPlanar + nLocal > 1) {
		fprintf (out,"Error (line %d): %s permits only one of %s, %s, or %s\n",
			p->line_number,text_of(p->key),text_of(WGeographic),text_of(WPlanar),text_of(WLocal));
		errors.too_many++;
		err++;
		}
	err += limit (p,1,
		WGeographic,
		WLocal,
		WGeodetic_Model,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Geographic =
 |		Latitude_Resolution +
 |		Longitude_Resolution +
 |		Geographic_Coordinate_Units
\*----------------------------------------------------------------------*/
static int check_Geographic (struct item *p) {
	int err = 0;
	err += allow (p,
		WLatitude_Resolution,
		WLongitude_Resolution,
		WGeographic_Coordinate_Units,
		Wnull);
	err += require (p,
		WLatitude_Resolution,
		WLongitude_Resolution,
		WGeographic_Coordinate_Units,
		Wnull);
	err += limit (p,1,
		WLatitude_Resolution,
		WLongitude_Resolution,
		WGeographic_Coordinate_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Planar =
 |		[Map_Projection |
 |		Grid_Coordinate_System |
 |		Local_Planar] +
 |		Planar_Coordinate_Information
\*----------------------------------------------------------------------*/
static int check_Planar (struct item *p) {
	int err = 0;
	err += allow (p,
		WMap_Projection,
		WGrid_Coordinate_System,
		WLocal_Planar,
		WPlanar_Coordinate_Information,
		Wnull);
	err += allow_one_of (p,
		WMap_Projection,
		WGrid_Coordinate_System,
		WLocal_Planar,
		Wnull);
	err += require_one_of (p,
		WMap_Projection,
		WGrid_Coordinate_System,
		WLocal_Planar,
		Wnull);
	err += require (p,
		WPlanar_Coordinate_Information,
		Wnull);
	err += limit (p,1,
		WMap_Projection,
		WGrid_Coordinate_System,
		WLocal_Planar,
		WPlanar_Coordinate_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Map_Projection =
 |		Map_Projection_Name +
 |		[Albers_Conical_Equal_Area |
 |		Azimuthal_Equidistant |
 |		Equidistant_Conic |
 |		Equirectangular |
 |		General_Vertical_Near-sided_Perspective |
 |		Gnomonic |
 |		Lambert_Azimuthal_Equal_Area |
 |		Lambert_Conformal_Conic |
 |		Mercator |
 |		Modified_Stereographic_for_Alaska |
 |		Miller_Cylindrical |
 |		Oblique_Mercator |
 |		Orthographic |
 |		Polar_Stereographic |
 |		Polyconic |
 |		Robinson |
 |		Sinusoidal |
 |		Space_Oblique_Mercator_(Landsat) |
 |		Stereographic |
 |		Transverse_Mercator |
 |		van_der_Grinten |
 |		Map_Projection_Parameters]
\*----------------------------------------------------------------------*/
static int check_Map_Projection (struct item *p) {
	int err = 0;
	err += allow (p,
		WMap_Projection_Name,
		WAlbers_Conical_Equal_Area,
		WAzimuthal_Equidistant,
		WEquidistant_Conic,
		WEquirectangular,
		WGeneral_Vertical_Near_sided_Perspective,
		WGnomonic,
		WLambert_Azimuthal_Equal_Area,
		WLambert_Conformal_Conic,
		WMercator,
		WModified_Stereographic_for_Alaska,
		WMiller_Cylindrical,
		WOblique_Mercator,
		WOrthographic,
		WPolar_Stereographic,
		WPolyconic,
		WRobinson,
		WSinusoidal,
		WSpace_Oblique_Mercator_Landsat,
		WStereographic,
		WTransverse_Mercator,
		Wvan_der_Grinten,
		WMap_Projection_Parameters,
		Wnull);
	err += allow_one_of (p,
		WAlbers_Conical_Equal_Area,
		WAzimuthal_Equidistant,
		WEquidistant_Conic,
		WEquirectangular,
		WGeneral_Vertical_Near_sided_Perspective,
		WGnomonic,
		WLambert_Azimuthal_Equal_Area,
		WLambert_Conformal_Conic,
		WMercator,
		WModified_Stereographic_for_Alaska,
		WMiller_Cylindrical,
		WOblique_Mercator,
		WOrthographic,
		WPolar_Stereographic,
		WPolyconic,
		WRobinson,
		WSinusoidal,
		WSpace_Oblique_Mercator_Landsat,
		WStereographic,
		WTransverse_Mercator,
		Wvan_der_Grinten,
		WMap_Projection_Parameters,
		Wnull);
	err += require_one_of (p,
		WAlbers_Conical_Equal_Area,
		WAzimuthal_Equidistant,
		WEquidistant_Conic,
		WEquirectangular,
		WGeneral_Vertical_Near_sided_Perspective,
		WGnomonic,
		WLambert_Azimuthal_Equal_Area,
		WLambert_Conformal_Conic,
		WMercator,
		WModified_Stereographic_for_Alaska,
		WMiller_Cylindrical,
		WOblique_Mercator,
		WOrthographic,
		WPolar_Stereographic,
		WPolyconic,
		WRobinson,
		WSinusoidal,
		WSpace_Oblique_Mercator_Landsat,
		WStereographic,
		WTransverse_Mercator,
		Wvan_der_Grinten,
		WMap_Projection_Parameters,
		Wnull);
	err += require (p,
		WMap_Projection_Name,
		Wnull);
	err += limit (p,1,
		WMap_Projection_Name,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Albers_Conical_Equal_Area =
 |		1{Standard_Parallel}2 +
 |		Longitude_of_Central_Meridian +
 |		Latitude_of_Projection_Origin +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Albers_Conical_Equal_Area (struct item *p) {
	int err = 0;
	err += allow (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,2,
		WStandard_Parallel,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Azimuthal_Equidistant =
 |		Longitude_of_Central_Meridian +
 |		Latitude_of_Projection_Origin +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Azimuthal_Equidistant (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Equidistant_Conic =
 |		1{Standard_Parallel}2 +
 |		Longitude_of_Central_Meridian +
 |		Latitude_of_Projection_Origin +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Equidistant_Conic (struct item *p) {
	int err = 0;
	err += allow (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,2,
		WStandard_Parallel,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Equirectangular =
 |		Standard_Parallel +
 |		Longitude_of_Central_Meridian +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Equirectangular (struct item *p) {
	int err = 0;
	err += allow (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	General_Vertical_Near-sided_Perspective =
 |		Height_of_Perspective_Point_Above_Surface +
 |		Longitude_of_Projection_Center +
 |		Latitude_of_Projection_Center +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_General_Vertical_Near_sided_Perspective (struct item *p) {
	int err = 0;
	err += allow (p,
		WHeight_of_Perspective_Point_Above_Surface,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WHeight_of_Perspective_Point_Above_Surface,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WHeight_of_Perspective_Point_Above_Surface,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Gnomonic =
 |		Longitude_of_Projection_Center +
 |		Latitude_of_Projection_Center +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Gnomonic (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Lambert_Azimuthal_Equal_Area =
 |		Longitude_of_Projection_Center +
 |		Latitude_of_Projection_Center +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Lambert_Azimuthal_Equal_Area (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Lambert_Conformal_Conic =
 |		1{Standard_Parallel}2 +
 |		Longitude_of_Central_Meridian +
 |		Latitude_of_Projection_Origin +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Lambert_Conformal_Conic (struct item *p) {
	int err = 0;
	err += allow (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WStandard_Parallel,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,2,
		WStandard_Parallel,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Mercator =
 |		[Standard_Parallel |
 |		Scale_Factor_at_Equator] +
 |		Longitude_of_Central_Meridian +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Mercator (struct item *p) {
	int err = 0;
	err += allow (p,
		WStandard_Parallel,
		WScale_Factor_at_Equator,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += allow_one_of (p,
		WScale_Factor_at_Equator,
		WStandard_Parallel,
		Wnull);
	err += require_one_of (p,
		WScale_Factor_at_Equator,
		WStandard_Parallel,
		Wnull);
	err += require (p,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Modified_Stereographic_for_Alaska =
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Modified_Stereographic_for_Alaska (struct item *p) {
	int err = 0;
	err += allow (p,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Miller_Cylindrical =
 |		Longitude_of_Central_Meridian +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Miller_Cylindrical (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Oblique_Mercator =
 |		Scale_Factor_at_Center_Line +
 |		[Oblique_Line_Azimuth |
 |		Oblique_Line_Point] +
 |		Latitude_of_Projection_Origin +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Oblique_Mercator (struct item *p) {
	int err = 0;
	err += allow (p,
		WScale_Factor_at_Center_Line,
		WOblique_Line_Azimuth,
		WOblique_Line_Point,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += allow_one_of (p,
		WOblique_Line_Azimuth,
		WOblique_Line_Point,
		Wnull);
	err += require_one_of (p,
		WOblique_Line_Azimuth,
		WOblique_Line_Point,
		Wnull);
	err += require (p,
		WScale_Factor_at_Center_Line,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WScale_Factor_at_Center_Line,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Oblique_Line_Azimuth =
 |		Azimuthal_Angle +
 |		Azimuth_Measure_Point_Longitude
\*----------------------------------------------------------------------*/
static int check_Oblique_Line_Azimuth (struct item *p) {
	int err = 0;
	err += allow (p,
		WAzimuthal_Angle,
		WAzimuth_Measure_Point_Longitude,
		Wnull);
	err += require (p,
		WAzimuthal_Angle,
		WAzimuth_Measure_Point_Longitude,
		Wnull);
	err += limit (p,1,
		WAzimuthal_Angle,
		WAzimuth_Measure_Point_Longitude,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Oblique_Line_Point =
 |		2{
 |		Oblique_Line_Latitude +
 |		Oblique_Line_Longitude
 |		}2
\*----------------------------------------------------------------------*/
static int check_Oblique_Line_Point (struct item *p) {
	int err = 0;
	err += allow (p,
		WOblique_Line_Latitude,
		WOblique_Line_Longitude,
		Wnull);
	err += require (p,
		WOblique_Line_Latitude,
		WOblique_Line_Longitude,
		Wnull);
	if (count (p,WOblique_Line_Latitude) < 2) {
		fprintf (out,"Error (line %d): too few %s in %s\n",
			p->line_number,text_of(WOblique_Line_Latitude),text_of(p->key));
		errors.missing++;
		err++;
		}
	if (count (p,WOblique_Line_Longitude) < 2) {
		fprintf (out,"Error (line %d): too few %s in %s\n",
			p->line_number,text_of(WOblique_Line_Longitude),text_of(p->key));
		errors.missing++;
		err++;
		}
	err += limit (p,2,
		WOblique_Line_Latitude,
		WOblique_Line_Longitude,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Orthographic =
 |		Longitude_of_Projection_Center +
 |		Latitude_of_Projection_Center +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Orthographic (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Polar_Stereographic =
 |		Straight-Vertical_Longitude_from_Pole +
 |		[Standard_Parallel |
 |		Scale_Factor_at_Projection_Origin] +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Polar_Stereographic (struct item *p) {
	int err = 0;
	err += allow (p,
		WStraight_Vertical_Longitude_from_Pole,
		WStandard_Parallel,
		WScale_Factor_at_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += allow_one_of (p,
		WStandard_Parallel,
		WScale_Factor_at_Projection_Origin,
		Wnull);
	err += require_one_of (p,
		WStandard_Parallel,
		WScale_Factor_at_Projection_Origin,
		Wnull);
	err += require (p,
		WStraight_Vertical_Longitude_from_Pole,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Polyconic =
 |		Longitude_of_Central_Meridian +
 |		Latitude_of_Projection_Origin +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Polyconic (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Robinson =
 |		Longitude_of_Projection_Center +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Robinson (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Sinusoidal =
 |		Longitude_of_Central_Meridian +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Sinusoidal (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Space_Oblique_Mercator_(Landsat) =
 |		Landsat_Number +
 |		Path_Number +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Space_Oblique_Mercator_Landsat (struct item *p) {
	int err = 0;
	err += allow (p,
		WLandsat_Number,
		WPath_Number,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLandsat_Number,
		WPath_Number,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLandsat_Number,
		WPath_Number,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Stereographic =
 |		Longitude_of_Projection_Center +
 |		Latitude_of_Projection_Center +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Stereographic (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Projection_Center,
		WLatitude_of_Projection_Center,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Transverse_Mercator =
 |		Scale_Factor_at_Central_Meridian +
 |		Longitude_of_Central_Meridian +
 |		Latitude_of_Projection_Origin +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Transverse_Mercator (struct item *p) {
	int err = 0;
	err += allow (p,
		WScale_Factor_at_Central_Meridian,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WScale_Factor_at_Central_Meridian,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WScale_Factor_at_Central_Meridian,
		WLongitude_of_Central_Meridian,
		WLatitude_of_Projection_Origin,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	van_der_Grinten =
 |		Longitude_of_Central_Meridian +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_van_der_Grinten (struct item *p) {
	int err = 0;
	err += allow (p,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += require (p,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	err += limit (p,1,
		WLongitude_of_Central_Meridian,
		WFalse_Easting,
		WFalse_Northing,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Map_Projection_Parameters =
 |		Longitude_of_Central_Meridian +
 |		False_Easting +
 |		False_Northing
\*----------------------------------------------------------------------*/
static int check_Map_Projection_Parameters (struct item *p) {
	int err = 0;
	err += allow (p,
		WAzimuth_Measure_Point_Longitude,
		WAzimuthal_Angle,
		WFalse_Easting,
		WFalse_Northing,
		WHeight_of_Perspective_Point_Above_Surface,
		WLandsat_Number,
		WLatitude_of_Projection_Center,
		WLatitude_of_Projection_Origin,
		WLongitude_of_Central_Meridian,
		WLongitude_of_Projection_Center,
		WOblique_Line_Azimuth,
		WOblique_Line_Point,
		WPath_Number,
		WScale_Factor_at_Center_Line,
		WScale_Factor_at_Central_Meridian,
		WScale_Factor_at_Equator,
		WScale_Factor_at_Projection_Origin,
		WStandard_Parallel,
		WStraight_Vertical_Longitude_from_Pole,
		WOther_Projections_Definition,
		Wnull);
	err += require (p,
		Wnull);
	err += limit (p,1,
		WAzimuth_Measure_Point_Longitude,
		WAzimuthal_Angle,
		WFalse_Easting,
		WFalse_Northing,
		WHeight_of_Perspective_Point_Above_Surface,
		WLandsat_Number,
		WLatitude_of_Projection_Center,
		WLatitude_of_Projection_Origin,
		WLongitude_of_Central_Meridian,
		WLongitude_of_Projection_Center,
		WPath_Number,
		WScale_Factor_at_Center_Line,
		WScale_Factor_at_Central_Meridian,
		WScale_Factor_at_Equator,
		WScale_Factor_at_Projection_Origin,
		WStraight_Vertical_Longitude_from_Pole,
		WOther_Projections_Definition,
		Wnull);
	err += limit (p,2,
		WStandard_Parallel,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Grid_Coordinate_System =
 |		Grid_Coordinate_System_Name +
 |		[Universal_Transverse_Mercator |
 |		Universal_Polar_Stereographic |
 |		State_Plane_Coordinate_System |
 |		ARC_Coordinate_System |
 |		Other_Grid_System's_Definition]
\*----------------------------------------------------------------------*/
static int check_Grid_Coordinate_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WGrid_Coordinate_System_Name,
		WUniversal_Transverse_Mercator,
		WUniversal_Polar_Stereographic,
		WState_Plane_Coordinate_System,
		WARC_Coordinate_System,
		WOther_Grid_Systems_Definition,
		Wnull);
	err += require (p,
		WGrid_Coordinate_System_Name,
		Wnull);
	err += allow_one_of (p,
		WUniversal_Transverse_Mercator,
		WUniversal_Polar_Stereographic,
		WState_Plane_Coordinate_System,
		WARC_Coordinate_System,
		WOther_Grid_Systems_Definition,
		Wnull);
	err += require_one_of (p,
		WUniversal_Transverse_Mercator,
		WUniversal_Polar_Stereographic,
		WState_Plane_Coordinate_System,
		WARC_Coordinate_System,
		WOther_Grid_Systems_Definition,
		Wnull);
	err += limit (p,1,
		WGrid_Coordinate_System_Name,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Universal_Transverse_Mercator =
 |		UTM_Zone_Number +
 |		Transverse_Mercator
\*----------------------------------------------------------------------*/
static int check_Universal_Transverse_Mercator (struct item *p) {
	int err = 0;
	err += allow (p,
		WUTM_Zone_Number,
		WTransverse_Mercator,
		Wnull);
	err += require (p,
		WUTM_Zone_Number,
		WTransverse_Mercator,
		Wnull);
	err += limit (p,1,
		WUTM_Zone_Number,
		WTransverse_Mercator,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Universal_Polar_Stereographic =
 |		UPS_Zone_Identifier +
 |		Polar_Stereographic
\*----------------------------------------------------------------------*/
static int check_Universal_Polar_Stereographic (struct item *p) {
	int err = 0;
	err += allow (p,
		WUPS_Zone_Identifier,
		WPolar_Stereographic,
		Wnull);
	err += require (p,
		WUPS_Zone_Identifier,
		WPolar_Stereographic,
		Wnull);
	err += limit (p,1,
		WUPS_Zone_Identifier,
		WPolar_Stereographic,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	State_Plane_Coordinate_System =
 |		SPCS_Zone_Identifier +
 |		[Lambert_Conformal_Conic |
 |		Transverse_Mercator |
 |		Oblique_Mercator |
 |		Polyconic]
\*----------------------------------------------------------------------*/
static int check_State_Plane_Coordinate_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WSPCS_Zone_Identifier,
		WLambert_Conformal_Conic,
		WTransverse_Mercator,
		WOblique_Mercator,
		WPolyconic,
		Wnull);
	err += require (p,
		WSPCS_Zone_Identifier,
		Wnull);
	err += allow_one_of (p,
		WLambert_Conformal_Conic,
		WTransverse_Mercator,
		WOblique_Mercator,
		WPolyconic,
		Wnull);
	err += require_one_of (p,
		WLambert_Conformal_Conic,
		WTransverse_Mercator,
		WOblique_Mercator,
		WPolyconic,
		Wnull);
	err += limit (p,1,
		WSPCS_Zone_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	ARC_Coordinate_System =
 |		ARC_System_Zone_Identifier +
 |		[Equirectangular |
 |		Azimuthal_Equidistant]
\*----------------------------------------------------------------------*/
static int check_ARC_Coordinate_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WARC_System_Zone_Identifier,
		WEquirectangular,
		WAzimuthal_Equidistant,
		Wnull);
	err += require (p,
		WARC_System_Zone_Identifier,
		Wnull);
	err += allow_one_of (p,
		WEquirectangular,
		WAzimuthal_Equidistant,
		Wnull);
	err += require_one_of (p,
		WEquirectangular,
		WAzimuthal_Equidistant,
		Wnull);
	err += limit (p,1,
		WARC_System_Zone_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Local_Planar =
 |		Local_Planar_Description +
 |		Local_Planar_Georeference_Information
\*----------------------------------------------------------------------*/
static int check_Local_Planar (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocal_Planar_Description,
		WLocal_Planar_Georeference_Information,
		Wnull);
	err += require (p,
		WLocal_Planar_Description,
		WLocal_Planar_Georeference_Information,
		Wnull);
	err += limit (p,1,
		WLocal_Planar_Description,
		WLocal_Planar_Georeference_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Planar_Coordinate_Information =
 |		Planar_Coordinate_Encoding_Method +
 |		[Coordinate_Representation |
 |		Distance_and_Bearing_Representation] +
 |		Planar_Distance_Units
\*----------------------------------------------------------------------*/
static int check_Planar_Coordinate_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WPlanar_Coordinate_Encoding_Method,
		WCoordinate_Representation,
		WDistance_and_Bearing_Representation,
		WPlanar_Distance_Units,
		Wnull);
	err += allow_one_of (p,
		WCoordinate_Representation,
		WDistance_and_Bearing_Representation,
		Wnull);
	err += require_one_of (p,
		WCoordinate_Representation,
		WDistance_and_Bearing_Representation,
		Wnull);
	err += require (p,
		WPlanar_Coordinate_Encoding_Method,
		WPlanar_Distance_Units,
		Wnull);
	err += limit (p,1,
		WPlanar_Coordinate_Encoding_Method,
		WPlanar_Distance_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Coordinate_Representation =
 |		Abscissa_Resolution +
 |		Ordinate_Resolution
\*----------------------------------------------------------------------*/
static int check_Coordinate_Representation (struct item *p) {
	int err = 0;
	err += allow (p,
		WAbscissa_Resolution,
		WOrdinate_Resolution,
		Wnull);
	err += require (p,
		WAbscissa_Resolution,
		WOrdinate_Resolution,
		Wnull);
	err += limit (p,1,
		WAbscissa_Resolution,
		WOrdinate_Resolution,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Distance_and_Bearing_Representation =
 |		Distance_Resolution +
 |		Bearing_Resolution +
 |		Bearing_Units +
 |		Bearing_Reference_Direction +
 |		Bearing_Reference_Meridian
\*----------------------------------------------------------------------*/
static int check_Distance_and_Bearing_Representation (struct item *p) {
	int err = 0;
	err += allow (p,
		WDistance_Resolution,
		WBearing_Resolution,
		WBearing_Units,
		WBearing_Reference_Direction,
		WBearing_Reference_Meridian,
		Wnull);
	err += require (p,
		WDistance_Resolution,
		WBearing_Resolution,
		WBearing_Units,
		WBearing_Reference_Direction,
		WBearing_Reference_Meridian,
		Wnull);
	err += limit (p,1,
		WDistance_Resolution,
		WBearing_Resolution,
		WBearing_Units,
		WBearing_Reference_Direction,
		WBearing_Reference_Meridian,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Local =
 |		Local_Description +
 |		Local_Georeference_Information
\*----------------------------------------------------------------------*/
static int check_Local (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocal_Description,
		WLocal_Georeference_Information,
		Wnull);
	err += require (p,
		WLocal_Description,
		WLocal_Georeference_Information,
		Wnull);
	err += limit (p,1,
		WLocal_Description,
		WLocal_Georeference_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Geodetic_Model =
 |		0{Horizontal_Datum_Name}1 +
 |		Ellipsoid_Name +
 |		Semi-major_Axis +
 |		Denominator_of_Flattening_Ratio
\*----------------------------------------------------------------------*/
static int check_Geodetic_Model (struct item *p) {
	int err = 0;
	err += allow (p,
		WHorizontal_Datum_Name,
		WEllipsoid_Name,
		WSemi_major_Axis,
		WDenominator_of_Flattening_Ratio,
		Wnull);
	err += require (p,
		WEllipsoid_Name,
		WSemi_major_Axis,
		WDenominator_of_Flattening_Ratio,
		Wnull);
	err += limit (p,1,
		WHorizontal_Datum_Name,
		WEllipsoid_Name,
		WSemi_major_Axis,
		WDenominator_of_Flattening_Ratio,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Vertical_Coordinate_System_Definition =
 |		0{Altitude_System_Definition}1 +
 |		0{Depth_System_Definition}1
\*----------------------------------------------------------------------*/
static int check_Vertical_Coordinate_System_Definition (struct item *p) {
	int err = 0;
	err += allow (p,
		WAltitude_System_Definition,
		WDepth_System_Definition,
		Wnull);
	err += limit (p,1,
		WAltitude_System_Definition,
		WDepth_System_Definition,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Altitude_System_Definition =
 |		Altitude_Datum_Name +
 |		1{Altitude_Resolution}n +
 |		[								// Remote-sensing
 |		Altitude_Distance_Units
 |		|								// Remote-sensing
 |		Altitude_Distance_Layer]		// Remote-sensing
 |		+
 |		Altitude_Encoding_Method
\*----------------------------------------------------------------------*/
static int check_Altitude_System_Definition (struct item *p) {
	int err = 0;
	if (rs_profile)
		err += allow (p,
			WAltitude_Datum_Name,
			WAltitude_Resolution,
			WAltitude_Distance_Units,
			WAltitude_Distance_Layer,
			WAltitude_Encoding_Method,
			Wnull);
	else	/* Standard */
		err += allow (p,
			WAltitude_Datum_Name,
			WAltitude_Resolution,
			WAltitude_Distance_Units,
			WAltitude_Encoding_Method,
			Wnull);
	if (rs_profile) {
		err += require (p,
			WAltitude_Datum_Name,
			WAltitude_Resolution,
			WAltitude_Encoding_Method,
			Wnull);
		err += allow_one_of (p,
			WAltitude_Distance_Units,
			WAltitude_Distance_Layer,
			Wnull);
		err += require_one_of (p,
			WAltitude_Distance_Units,
			WAltitude_Distance_Layer,
			Wnull);
		}
	else	/* Standard */
		err += require (p,
			WAltitude_Datum_Name,
			WAltitude_Resolution,
			WAltitude_Distance_Units,
			WAltitude_Encoding_Method,
			Wnull);
	err += limit (p,1,
		WAltitude_Datum_Name,
		WAltitude_Distance_Units,
		WAltitude_Encoding_Method,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Depth_System_Definition =
 |		Depth_Datum_Name +
 |		1{Depth_Resolution}n +
 |		Depth_Distance_Units +
 |		Depth_Encoding_Method
\*----------------------------------------------------------------------*/
static int check_Depth_System_Definition (struct item *p) {
	int err = 0;
	err += allow (p,
		WDepth_Datum_Name,
		WDepth_Resolution,
		WDepth_Distance_Units,
		WDepth_Encoding_Method,
		Wnull);
	err += require (p,
		WDepth_Datum_Name,
		WDepth_Resolution,
		WDepth_Distance_Units,
		WDepth_Encoding_Method,
		Wnull);
	err += limit (p,1,
		WDepth_Datum_Name,
		WDepth_Distance_Units,
		WDepth_Encoding_Method,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Entity_and_Attribute_Information =
 |		[1{Detailed_Description}n |
 |		1{Overview_Description}n |
 |		1{Detailed_Description}n +
 |		1{Overview_Description}n]
\*----------------------------------------------------------------------*/
static int check_Entity_and_Attribute_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WDetailed_Description,
		WOverview_Description,
		Wnull);
	if (count (p,WOverview_Description) == 0 &&
		count (p,WDetailed_Description) == 0) {
		fprintf (out,"Error (line %d): %s requires %s or %s or both\n",
			p->line_number,text_of(p->key),
			text_of(WOverview_Description),
			text_of(WDetailed_Description)
			);
		errors.missing++;
		err++;
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Detailed_Description =
 |		Entity_Type +
 |		0{Attribute}n
\*----------------------------------------------------------------------*/
static int check_Detailed_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WEntity_Type,
		WAttribute,
		Wnull);
	err += require (p,
		WEntity_Type,
		Wnull);
	err += limit (p,1,
		WEntity_Type,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Entity_Type =
 |		Entity_Type_Label +
 |		Entity_Type_Definition +
 |		Entity_Type_Definition_Source
\*----------------------------------------------------------------------*/
static int check_Entity_Type (struct item *p) {
	int err = 0;
	err += allow (p,
		WEntity_Type_Label,
		WEntity_Type_Definition,
		WEntity_Type_Definition_Source,
		Wnull);
	err += require (p,
		WEntity_Type_Label,
		WEntity_Type_Definition,
		WEntity_Type_Definition_Source,
		Wnull);
	err += limit (p,1,
		WEntity_Type_Label,
		WEntity_Type_Definition,
		WEntity_Type_Definition_Source,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Attribute =
 |		Attribute_Label +
 |		Attribute_Definition +
 |		Attribute_Definition_Source +
 |		1{Attribute_Domain_Values}n +
 |		(
 |		1{
 |		Beginning_Date_of_Attribute_Values +
 |		0{Ending_Date_of_Attribute_Values}1
 |		}n
 |		) +
 |		(Attribute_Value_Accuracy_Information) +
 |		(Attribute_Measurement_Frequency)
\*----------------------------------------------------------------------*/
static int check_Attribute (struct item *p) {
	int err = 0;
	err += allow (p,
		WAttribute_Label,
		WAttribute_Definition,
		WAttribute_Definition_Source,
		WAttribute_Domain_Values,
		WBeginning_Date_of_Attribute_Values,
		WEnding_Date_of_Attribute_Values,
		WAttribute_Value_Accuracy_Information,
		WAttribute_Measurement_Frequency,
		Wnull);
	err += require (p,
		WAttribute_Label,
		WAttribute_Definition,
		WAttribute_Definition_Source,
		WAttribute_Domain_Values,
		Wnull);
	if (count (p,WBeginning_Date_of_Attribute_Values) <
		count (p,WEnding_Date_of_Attribute_Values)) {
		fprintf (out,"Error (line %d): %s requires as many %s as %s\n",
			p->line_number,text_of(p->key),
			text_of(WBeginning_Date_of_Attribute_Values),
			text_of(WEnding_Date_of_Attribute_Values)
			);
		errors.missing++;
		err++;
		}
	err += limit (p,1,
		WAttribute_Label,
		WAttribute_Definition,
		WAttribute_Definition_Source,
		WAttribute_Value_Accuracy_Information,
		WAttribute_Measurement_Frequency,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Attribute_Domain_Values =
 |		[1{Enumerated_Domain}n |
 |		Range_Domain |
 |		Codeset_Domain |
 |		Unrepresentable_Domain] +
 |		0{Data_Scaling_Information}1		// Remote-sensing
\*----------------------------------------------------------------------*/
static int check_Attribute_Domain_Values (struct item *p) {
	int err = 0;
	if (rs_profile)
		err += allow (p,
			WEnumerated_Domain,
			WRange_Domain,
			WCodeset_Domain,
			WUnrepresentable_Domain,
			WData_Scaling_Information,
			Wnull);
	else	/* Standard */
		err += allow (p,
			WEnumerated_Domain,
			WRange_Domain,
			WCodeset_Domain,
			WUnrepresentable_Domain,
			Wnull);
	err += require_one_of (p,
		WEnumerated_Domain,
		WRange_Domain,
		WCodeset_Domain,
		WUnrepresentable_Domain,
		Wnull);
	err += allow_one_of (p,
		WEnumerated_Domain,
		WRange_Domain,
		WCodeset_Domain,
		WUnrepresentable_Domain,
		Wnull);
	err += limit (p,1,
		WRange_Domain,
		WCodeset_Domain,
		WUnrepresentable_Domain,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Enumerated_Domain =
 |		Enumerated_Domain_Value +
 |		Enumerated_Domain_Value_Definition +
 |		Enumerated_Domain_Value_Definition_Source +
 |		0{Attribute}n
\*----------------------------------------------------------------------*/
static int check_Enumerated_Domain (struct item *p) {
	int err = 0;
	err += allow (p,
		WEnumerated_Domain_Value,
		WEnumerated_Domain_Value_Definition,
		WEnumerated_Domain_Value_Definition_Source,
		WAttribute,
		Wnull);
	err += require (p,
		WEnumerated_Domain_Value,
		WEnumerated_Domain_Value_Definition,
		WEnumerated_Domain_Value_Definition_Source,
		Wnull);
	err += limit (p,1,
		WEnumerated_Domain_Value,
		WEnumerated_Domain_Value_Definition,
		WEnumerated_Domain_Value_Definition_Source,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Range_Domain =
 |		Range_Domain_Minimum +
 |		Range_Domain_Maximum +
 |		0{Attribute_Units_of_Measure}1 +
 |		(Attribute_Measurement_Resolution) +
 |		0{Attribute}n
\*----------------------------------------------------------------------*/
static int check_Range_Domain (struct item *p) {
	int err = 0;
	err += allow (p,
		WRange_Domain_Minimum,
		WRange_Domain_Maximum,
		WAttribute_Units_of_Measure,
		WAttribute_Measurement_Resolution,
		WAttribute,
		Wnull);
	err += require (p,
		WRange_Domain_Minimum,
		WRange_Domain_Maximum,
		Wnull);
	err += limit (p,1,
		WRange_Domain_Minimum,
		WRange_Domain_Maximum,
		WAttribute_Units_of_Measure,
		WAttribute_Measurement_Resolution,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Codeset_Domain =
 |		Codeset_Name +
 |		Codeset_Source
\*----------------------------------------------------------------------*/
static int check_Codeset_Domain (struct item *p) {
	int err = 0;
	err += allow (p,
		WCodeset_Name,
		WCodeset_Source,
		Wnull);
	err += require (p,
		WCodeset_Name,
		WCodeset_Source,
		Wnull);
	err += limit (p,1,
		WCodeset_Name,
		WCodeset_Source,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Attribute_Value_Accuracy_Information =
 |		Attribute_Value_Accuracy +
 |		Attribute_Value_Accuracy_Explanation
\*----------------------------------------------------------------------*/
static int check_Attribute_Value_Accuracy_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WAttribute_Value_Accuracy,
		WAttribute_Value_Accuracy_Explanation,
		Wnull);
	err += require (p,
		WAttribute_Value_Accuracy,
		WAttribute_Value_Accuracy_Explanation,
		Wnull);
	err += limit (p,1,
		WAttribute_Value_Accuracy,
		WAttribute_Value_Accuracy_Explanation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Overview_Description =
 |		1{Entity_and_Attribute_Overview +
 |		1{Entity_and_Attribute_Detail_Citation}n}n
\*----------------------------------------------------------------------*/
static int check_Overview_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WEntity_and_Attribute_Overview,
		WEntity_and_Attribute_Detail_Citation,
		Wnull);
	err += require (p,
		WEntity_and_Attribute_Overview,
		WEntity_and_Attribute_Detail_Citation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Distribution_Information =
 |		Distributor +
 |		0{Resource_Description}1 +
 |		Distribution_Liability +
 |		0{Standard_Order_Process}n +
 |		0{Custom_Order_Process}1 +
 |		(Technical_Prerequisites) +
 |		(Available_Time_Period)
\*----------------------------------------------------------------------*/
static int check_Distribution_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WDistributor,
		WResource_Description,
		WDistribution_Liability,
		WStandard_Order_Process,
		WCustom_Order_Process,
		WTechnical_Prerequisites,
		WAvailable_Time_Period,
		Wnull);
	err += require (p,
		WDistributor,
		WDistribution_Liability,
		Wnull);
	err += limit (p,1,
		WDistributor,
		WResource_Description,
		WDistribution_Liability,
		WCustom_Order_Process,
		WTechnical_Prerequisites,
		WAvailable_Time_Period,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Distributor =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Distributor (struct item *p) {
	return (check_Point_of_Contact(p));
	}
/*----------------------------------------------------------------------*\
 |	Standard_Order_Process =
 |		[Non-digital_Form |
 |		1{Digital_Form}n] +
 |		Fees +
 |		(Ordering_Instructions) +
 |		(Turnaround)
\*----------------------------------------------------------------------*/
static int check_Standard_Order_Process (struct item *p) {
	int err = 0;
	int nNon_digital_Form;
	int nDigital_Form;
	err += allow (p,
		WNon_digital_Form,
		WDigital_Form,
		WFees,
		WOrdering_Instructions,
		WTurnaround,
		Wnull);
	nNon_digital_Form = count (p,WNon_digital_Form);
	nDigital_Form = count (p,WDigital_Form);
	if (nNon_digital_Form > 0 && nDigital_Form > 0) {
		fprintf (out,"Error (line %d): %s permits only %s or %s but not both\n",
			p->line_number,text_of(p->key),text_of(WNon_digital_Form),text_of(WDigital_Form));
		errors.too_many++;
		err++;
		}
	if (nNon_digital_Form == 0 && nDigital_Form == 0) {
		fprintf (out,"Error (line %d): %s requires at least one of %s or %s\n",
			p->line_number,text_of(p->key),text_of(WNon_digital_Form),text_of(WDigital_Form));
		errors.missing++;
		err++;
		}
	err += require (p,
		WFees,
		Wnull);
	err += limit (p,1,
		WNon_digital_Form,
		WFees,
		WOrdering_Instructions,
		WTurnaround,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Digital_Form =
 |		Digital_Transfer_Information +
 |		Digital_Transfer_Option
\*----------------------------------------------------------------------*/
static int check_Digital_Form (struct item *p) {
	int err = 0;
	err += allow (p,
		WDigital_Transfer_Information,
		WDigital_Transfer_Option,
		Wnull);
	err += require (p,
		WDigital_Transfer_Information,
		WDigital_Transfer_Option,
		Wnull);
	err += limit (p,1,
		WDigital_Transfer_Information,
		WDigital_Transfer_Option,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Digital_Transfer_Information =
 |		Format_Name +
 |		(
 |		[Format_Version_Number |
 |		Format_Version_Date] +
 |		(Format_Specification)
 |		) +
 |		0{ASCII_File_Structure}1 +		// Biological data profile
 |		(Format_Information_Content) +
 |		0{File_Decompression_Technique}1 +
 |		(Transfer_Size)
\*----------------------------------------------------------------------*/
static int check_Digital_Transfer_Information (struct item *p) {
	int err = 0;
	if (bio_profile) {
		err += allow (p,
			WFormat_Name,
			WFormat_Version_Number,
			WFormat_Version_Date,
			WFormat_Specification,
			WASCII_File_Structure,
			WFormat_Information_Content,
			WFile_Decompression_Technique,
			WTransfer_Size,
			Wnull);
		err += limit (p,1,
			WFormat_Name,
			WFormat_Specification,
			WASCII_File_Structure,
			WFormat_Information_Content,
			WFile_Decompression_Technique,
			WTransfer_Size,
			Wnull);
			}
	else {
		err += allow (p,
			WFormat_Name,
			WFormat_Version_Number,
			WFormat_Version_Date,
			WFormat_Specification,
			WFormat_Information_Content,
			WFile_Decompression_Technique,
			WTransfer_Size,
			Wnull);
		err += limit (p,1,
			WFormat_Name,
			WFormat_Specification,
			WFormat_Information_Content,
			WFile_Decompression_Technique,
			WTransfer_Size,
			Wnull);
		}
	if (count (p,WFormat_Specification) > 0) {
		err += allow_one_of (p,
			WFormat_Version_Number,
			WFormat_Version_Date,
			Wnull);
		err += require_one_of (p,
			WFormat_Version_Number,
			WFormat_Version_Date,
			Wnull);
		}
	err += require (p,
		WFormat_Name,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	ASCII_File_Structure =
 |		0{Record_Delimiter}1 +
 |		Number_Header_Lines +
 |		(Description_of_Header_Content) +
 |		Orientation +
 |		Case_Sensitive +
 |		0{Authentication}1 +
 |		0{Quote_Character}1 +
 |		1{Data_Field}n
\*----------------------------------------------------------------------*/
static int check_ASCII_File_Structure (struct item *p) {
	int err = 0;
	err += allow (p,
		WRecord_Delimiter,
		WNumber_Header_Lines,
		WDescription_of_Header_Content,
		WOrientation,
		WCase_Sensitive,
		WAuthentication,
		WQuote_Character,
		WData_Field,
		Wnull);
	err += require (p,
		WNumber_Header_Lines,
		WOrientation,
		WCase_Sensitive,
		WData_Field,
		Wnull);
	err += limit (p,1,
		WRecord_Delimiter,
		WNumber_Header_Lines,
		WDescription_of_Header_Content,
		WOrientation,
		WCase_Sensitive,
		WAuthentication,
		WQuote_Character,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Data_Field =
 |		Data_Field_Name +
 |		0{Missing_Value_Code}1 +
 |		[Data_Field_Width_Delimiter |
 |		Data_Field_Width]
\*----------------------------------------------------------------------*/
static int check_Data_Field (struct item *p) {
	int err = 0;
	err += allow (p,
		WData_Field_Name,
		WMissing_Value_Code,
		WData_Field_Width_Delimiter,
		WData_Field_Width,
		Wnull);
	err += require (p,
		WData_Field_Name,
		Wnull);
	err += limit (p,1,
		WData_Field_Name,
		WMissing_Value_Code,
		Wnull);
	err += allow_one_of (p,
		WData_Field_Width_Delimiter,
		WData_Field_Width,
		Wnull);
	err += require_one_of (p,
		WData_Field_Width_Delimiter,
		WData_Field_Width,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Digital_Transfer_Option =
 |	1{
 |	[Online_Option |
 |	Offline_Option]
 |	}n
\*----------------------------------------------------------------------*/
static int check_Digital_Transfer_Option (struct item *p) {
	int err = 0;
	err += allow (p,
		WOnline_Option,
		WOffline_Option,
		Wnull);
	if ((count (p,WOnline_Option)  == 0) &&
		(count (p,WOffline_Option) == 0)) {
		fprintf (out,"Error (line %d): %s requires at least one %s or %s\n",
			p->line_number,
			text_of(p->key),
			text_of(WOnline_Option),
			text_of(WOffline_Option)
			);
		errors.missing++;
		err++;
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Online_Option =
 |		1{Computer_Contact_Information}n +
 |		(Access_Instructions) +
 |		(Online_Computer_and_Operating_System)
\*----------------------------------------------------------------------*/
static int check_Online_Option (struct item *p) {
	int err = 0;
	err += allow (p,
		WComputer_Contact_Information,
		WAccess_Instructions,
		WOnline_Computer_and_Operating_System,
		Wnull);
	err += require (p,
		WComputer_Contact_Information,
		Wnull);
	err += limit (p,1,
		WAccess_Instructions,
		WOnline_Computer_and_Operating_System,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Computer_Contact_Information =
 |		[Network_Address |
 |		Dialup_Instructions]
\*----------------------------------------------------------------------*/
static int check_Computer_Contact_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WNetwork_Address,
		WDialup_Instructions,
		Wnull);
	err += allow_one_of (p,
		WNetwork_Address,
		WDialup_Instructions,
		Wnull);
	err += require_one_of (p,
		WNetwork_Address,
		WDialup_Instructions,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Network_Address =
 |		1{Network_Resource_Name}n
\*----------------------------------------------------------------------*/
static int check_Network_Address (struct item *p) {
	int err = 0;
	err += allow (p,
		WNetwork_Resource_Name,
		Wnull);
	err += require (p,
		WNetwork_Resource_Name,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Dialup_Instructions =
 |		Lowest_BPS +
 |		0{Highest_BPS}1 +
 |		Number_DataBits +
 |		Number_StopBits +
 |		Parity +
 |		0{Compression_Support}1 +
 |		1{Dialup_Telephone}n +
 |		1{Dialup_File_Name}n
\*----------------------------------------------------------------------*/
static int check_Dialup_Instructions (struct item *p) {
	int err = 0;
	err += allow (p,
		WLowest_BPS,
		WHighest_BPS,
		WNumber_DataBits,
		WNumber_StopBits,
		WParity,
		WCompression_Support,
		WDialup_Telephone,
		WDialup_File_Name,
		Wnull);
	err += require (p,
		WLowest_BPS,
		WNumber_DataBits,
		WNumber_StopBits,
		WParity,
		Wnull);
	err += limit (p,1,
		WLowest_BPS,
		WHighest_BPS,
		WNumber_DataBits,
		WNumber_StopBits,
		WParity,
		WCompression_Support,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Offline_Option =
 |		Offline_Media +
 |		0{Recording_Capacity}1 +
 |		1{Recording_Format}n +
 |		0{Compatibility_Information}1
\*----------------------------------------------------------------------*/
static int check_Offline_Option (struct item *p) {
	int err = 0;
	err += allow (p,
		WOffline_Media,
		WRecording_Capacity,
		WRecording_Format,
		WCompatibility_Information,
		Wnull);
	err += require (p,
		WOffline_Media,
		WRecording_Format,
		Wnull);
	err += limit (p,1,
		WOffline_Media,
		WRecording_Capacity,
		WCompatibility_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Recording_Capacity =
 |		1{Recording Density}n +
 |		Recording_Density_Units
\*----------------------------------------------------------------------*/
static int check_Recording_Capacity (struct item *p) {
	int err = 0;
	err += allow (p,
		WRecording_Density,
		WRecording_Density_Units,
		Wnull);
	err += require (p,
		WRecording_Density,
		WRecording_Density_Units,
		Wnull);
	err += limit (p,1,
		WRecording_Density_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Available_Time_Period =
 |		Time_Period_Information
\*----------------------------------------------------------------------*/
static int check_Available_Time_Period (struct item *p) {
	int err = 0;
	err += allow (p,WTime_Period_Information,Wnull);
	err += require (p,WTime_Period_Information,Wnull);
	err += limit (p,1,WTime_Period_Information,Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Metadata_Reference_Information =
 |		Metadata_Date +
 |		Metadata_Review_Date +
 |		(Metadata_Future_Review_Date) +
 |		Metadata_Contact +
 |		Metadata_Standard_Name +
 |		Metadata_Standard_Version +
 |		0{Metadata_Time_Convention}1 +
 |		(Metadata_Access_Constraints) +
 |		(Metadata_Use_Constraints) +
 |		(Metadata_Security_Information) +
 |		0{Metadata_Extensions}n
\*----------------------------------------------------------------------*/
static int check_Metadata_Reference_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WMetadata_Date,
		WMetadata_Review_Date,
		WMetadata_Future_Review_Date,
		WMetadata_Contact,
		WMetadata_Standard_Name,
		WMetadata_Standard_Version,
		WMetadata_Time_Convention,
		WMetadata_Access_Constraints,
		WMetadata_Use_Constraints,
		WMetadata_Security_Information,
		WMetadata_Extensions,
		WMetadata_Language,
		Wnull);
	err += require (p,
		WMetadata_Date,
		WMetadata_Contact,
		WMetadata_Standard_Name,
		WMetadata_Standard_Version,
		Wnull);
	err += limit (p,1,
		WMetadata_Date,
		WMetadata_Review_Date,
		WMetadata_Future_Review_Date,
		WMetadata_Contact,
		WMetadata_Standard_Name,
		WMetadata_Standard_Version,
		WMetadata_Time_Convention,
		WMetadata_Access_Constraints,
		WMetadata_Use_Constraints,
		WMetadata_Security_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Metadata_Contact =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Metadata_Contact (struct item *p) {
	return (check_Point_of_Contact(p));
	}
/*----------------------------------------------------------------------*\
 |	Metadata_Security_Information =
 |		Metadata_Security_Classification_System +
 |		Metadata_Security_Classification +
 |		Metadata_Security_Handling_Description
\*----------------------------------------------------------------------*/
static int check_Metadata_Security_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WMetadata_Security_Classification_System,
		WMetadata_Security_Classification,
		WMetadata_Security_Handling_Description,
		Wnull);
	err += require (p,
		WMetadata_Security_Classification_System,
		WMetadata_Security_Classification,
		WMetadata_Security_Handling_Description,
		Wnull);
	err += limit (p,1,
		WMetadata_Security_Classification_System,
		WMetadata_Security_Classification,
		WMetadata_Security_Handling_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Metadata_Extensions =
 |		0{Online_Linkage}n +
 |		0{Profile_Name}1
\*----------------------------------------------------------------------*/
static int check_Metadata_Extensions (struct item *p) {
	int err = 0;
	err += allow (p,
		WOnline_Linkage,
		WProfile_Name,
		Wnull);
	err += require (p,
		Wnull);
	err += limit (p,1,
		WProfile_Name,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Citation_Information =
 |		1{Originator}n +
 |		Publication_Date +
 |		(Publication_Time) +
 |		Title +
 |		0{Edition}1 +
 |		0{Geospatial_Data_Presentation_Form}1 +
 |		0{Series_Information}1 +
 |		0{Publication_Information}1 +
 |		0{Other_Citation_Details}1 +
 |		(1{Online_Linkage}n) +
 |		0{Larger_Work_Citation}1
\*----------------------------------------------------------------------*/
static int check_Citation_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WOriginator,
		WPublication_Date,
		WPublication_Time,
		WTitle,
		WEdition,
		WGeospatial_Data_Presentation_Form,
		WSeries_Information,
		WPublication_Information,
		WOther_Citation_Details,
		WOnline_Linkage,
		WLarger_Work_Citation,
		Wnull);
	err += require (p,
		WOriginator,
		WPublication_Date,
		WTitle,
		Wnull);
	if (bio_profile)
		err += require (p,
			WGeospatial_Data_Presentation_Form,
			Wnull);
	err += limit (p,1,
		WPublication_Date,
		WPublication_Time,
		WTitle,
		WEdition,
		WGeospatial_Data_Presentation_Form,
		WSeries_Information,
		WPublication_Information,
		WOther_Citation_Details,
		WLarger_Work_Citation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Series_Information =
 |		Series_Name +
 |		Issue_Identification
\*----------------------------------------------------------------------*/
static int check_Series_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WSeries_Name,
		WIssue_Identification,
		Wnull);
	err += require (p,
		WSeries_Name,
		WIssue_Identification,
		Wnull);
	err += limit (p,1,
		WSeries_Name,
		WIssue_Identification,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Publication_Information =
 |		Publication_Place +
 |		Publisher
\*----------------------------------------------------------------------*/
static int check_Publication_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WPublication_Place,
		WPublisher,
		Wnull);
	err += require (p,
		WPublication_Place,
		WPublisher,
		Wnull);
	err += limit (p,1,
		WPublication_Place,
		WPublisher,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Larger_Work_Citation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Larger_Work_Citation (struct item *p) {
	return (check_Citation(p));
	}
/*----------------------------------------------------------------------*\
 |	Time_Period_Information =
 |		[Single_Date/Time |
 |		Multiple_Dates/Times |
 |		Range_of_Dates/Times]
\*----------------------------------------------------------------------*/
static int check_Time_Period_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		WMultiple_Dates_Times,
		WRange_of_Dates_Times,
		Wnull);
	err += allow_one_of (p,
		WSingle_Date_Time,
		WMultiple_Dates_Times,
		WRange_of_Dates_Times,
		Wnull);
	err += require_one_of (p,
		WSingle_Date_Time,
		WMultiple_Dates_Times,
		WRange_of_Dates_Times,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Single_Date/Time =
 |		[Calendar_Date +
 |		(Time_of_Day) |
 |		Geologic_Age]
\*----------------------------------------------------------------------*/
static int check_Single_Date_Time (struct item *p) {
	int err = 0;
	if (bio_profile) {
		err += allow (p,
			WCalendar_Date,
			WTime_of_Day,
			WGeologic_Age,
			Wnull);
		err += allow_one_of (p,
			WCalendar_Date,
			WGeologic_Age,
			Wnull);
		err += require_one_of (p,
			WCalendar_Date,
			WGeologic_Age,
			Wnull);
		err += limit (p,1,
			WCalendar_Date,
			WTime_of_Day,
			WGeologic_Age,
			Wnull);
		}
	else {
		err += allow (p,
			WCalendar_Date,
			WTime_of_Day,
			Wnull);
		err += require (p,
			WCalendar_Date,
			Wnull);
		err += limit (p,1,
			WCalendar_Date,
			WTime_of_Day,
			Wnull);
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Geologic_Age =
 |		Geologic_Time_Scale +
 |		Geologic_Age_Estimate +
 |		0{Geologic_Age_Uncertainty}1 +
 |		0{Geologic_Age_Explanation}1 +
 |		(1{Geologic_Citation}n)
\*----------------------------------------------------------------------*/
static int check_Geologic_Age (struct item *p) {
	int err = 0;
	err += allow (p,
		WGeologic_Time_Scale,
		WGeologic_Age_Estimate,
		WGeologic_Age_Uncertainty,
		WGeologic_Age_Explanation,
		WGeologic_Citation,
		Wnull);
	err += require (p,
		WGeologic_Time_Scale,
		WGeologic_Age_Estimate,
		Wnull);
	err += limit (p,1,
		WGeologic_Time_Scale,
		WGeologic_Age_Estimate,
		WGeologic_Age_Uncertainty,
		WGeologic_Age_Explanation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Geologic_Citation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Geologic_Citation (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,
		Wnull);
	err += limit (p,1,
		WCitation_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Multiple_Dates/Times =
 |		2{Calendar_Date + (Time_of_Day)}n
\*----------------------------------------------------------------------*/
static int check_Multiple_Dates_Times (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		Wnull);
	if (count (p,WSingle_Date_Time) < 2) {
		fprintf (out,"Error (line %d): %s requires two or more %s\n",
			p->line_number,text_of(p->key),text_of(WSingle_Date_Time));
		errors.missing++;
		err++;
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Range_of_Dates/Times =
 |		[Beginning_Date +
 |		(Beginning_Time) +
 |		Ending_Date +
 |		(Ending_Time) |
 |		Beginning_Geologic_Age +	// Biological data profile
 |		Ending_Geologic_Age]		// Biological data profile
\*----------------------------------------------------------------------*/
static int check_Range_of_Dates_Times (struct item *p) {
	int err = 0;
	if (bio_profile) {
		err += allow (p,
			WBeginning_Date,
			WBeginning_Time,
			WEnding_Date,
			WEnding_Time,
			WBeginning_Geologic_Age,
			WEnding_Geologic_Age,
			Wnull);
		err += allow_one_of (p,
			WBeginning_Date,
			WBeginning_Geologic_Age,
			Wnull);
		err += allow_one_of (p,
			WEnding_Date,
			WEnding_Geologic_Age,
			Wnull);
		if (count (p,WBeginning_Date) > 0 || count (p,WEnding_Date) > 0)
			err += require (p,
				WBeginning_Date,
				WEnding_Date,
				Wnull);
		err += limit (p,1,
			WBeginning_Date,
			WBeginning_Time,
			WEnding_Date,
			WEnding_Time,
			WBeginning_Geologic_Age,
			WEnding_Geologic_Age,
			Wnull);
		}
	else {
		err += allow (p,
			WBeginning_Date,
			WBeginning_Time,
			WEnding_Date,
			WEnding_Time,
			Wnull);
		err += require (p,
			WBeginning_Date,
			WEnding_Date,
			Wnull);
		err += limit (p,1,
			WBeginning_Date,
			WBeginning_Time,
			WEnding_Date,
			WEnding_Time,
			Wnull);
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Beginning_Geologic_Age =
 |		Geologic_Age
\*----------------------------------------------------------------------*/
static int check_Beginning_Geologic_Age (struct item *p) {
	int err = 0;
	err += allow (p,
		WGeologic_Age,
		Wnull);
	err += require (p,
		WGeologic_Age,
		Wnull);
	err += limit (p,1,
		WGeologic_Age,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Ending_Geologic_Age =
 |		Geologic_Age
\*----------------------------------------------------------------------*/
static int check_Ending_Geologic_Age (struct item *p) {
	int err = 0;
	err += allow (p,
		WGeologic_Age,
		Wnull);
	err += require (p,
		WGeologic_Age,
		Wnull);
	err += limit (p,1,
		WGeologic_Age,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Contact_Information =
 |		[Contact_Person_Primary |
 |		Contact_Organization_Primary] +
 |		(Contact_Position) +
 |		1{Contact_Address}n +
 |		1{Contact_Voice_Telephone}n +
 |		0{Contact_TDD/TTY_Telephone}n +
 |		0{Contact_Facsimile_Telephone}n +
 |		0{Contact_Electronic_Mail_Address}n +
 |		(Hours_of_Service) +
 |		(Contact_Instructions)
\*----------------------------------------------------------------------*/
static int check_Contact_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Person_Primary,
		WContact_Organization_Primary,
		WContact_Position,
		WContact_Address,
		WContact_Voice_Telephone,
		WContact_TDD_TTY_Telephone,
		WContact_Facsimile_Telephone,
		WContact_Electronic_Mail_Address,
		WHours_of_Service,
		WContact_Instructions,
		Wnull);
	err += allow_one_of (p,
		WContact_Person_Primary,
		WContact_Organization_Primary,
		Wnull);
	err += require_one_of (p,
		WContact_Person_Primary,
		WContact_Organization_Primary,
		Wnull);
	err += require (p,
		WContact_Address,
		WContact_Voice_Telephone,
		Wnull);
	err += limit (p,1,
		WContact_Position,
		WHours_of_Service,
		WContact_Instructions,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Contact_Person_Primary =
 |		Contact_Person +
 |		(Contact_Organization)
\*----------------------------------------------------------------------*/
static int check_Contact_Person_Primary (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Person,
		WContact_Organization,
		Wnull);
	err += require (p,
		WContact_Person,
		Wnull);
	err += limit (p,1,
		WContact_Person,
		WContact_Organization,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Contact_Organization_Primary =
 |		Contact_Organization +
 |		(Contact_Person)
\*----------------------------------------------------------------------*/
static int check_Contact_Organization_Primary (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Organization,
		WContact_Person,
		Wnull);
	err += require (p,
		WContact_Organization,
		Wnull);
	err += limit (p,1,
		WContact_Organization,
		WContact_Person,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 |	Contact_Address =
 |		Address_Type +
 |		0{Address}n +
 |		City +
 |		State_or_Province +
 |		Postal_Code +
 |		(Country)
\*----------------------------------------------------------------------*/
static int check_Contact_Address (struct item *p) {
	int err = 0;
	err += allow (p,
		WAddress_Type,
		WAddress,
		WCity,
		WState_or_Province,
		WPostal_Code,
		WCountry,
		Wnull);
	err += require (p,
		WAddress_Type,
		WCity,
		WState_or_Province,
		WPostal_Code,
		Wnull);
	err += limit (p,1,
		WAddress_Type,
		WCity,
		WState_or_Province,
		WPostal_Code,
		WCountry,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Shoreline profile elements
\*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*\
 | Marine_Weather_Condition
 |
 | Wind and wave conditions existing over an ocean or lake during the time of data collection.
 |
 |	Marine_Weather_Condition =
 |		0{Wind_Speed}1 +
 |		0{Wind_Direction}1 +
 |		0{Wave_Height}1 +
 |		0{Barometric_Pressure}1
\*----------------------------------------------------------------------*/
static int check_Marine_Weather_Condition (struct item *p) {
	int err = 0;
	err += allow (p,
		WWind_Speed,
		WWind_Direction,
		WWave_Height,
		WBarometric_Pressure,
		Wnull);
	err += limit (p,1,
		WWind_Speed,
		WWind_Direction,
		WWave_Height,
		WBarometric_Pressure,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Tidal_Information
 |
 | Means of encoding tidal information
 |
 |	Tidal_Information =
 |		0{Type_of_Tide}1 +
 |		0{Time_of _Tide}1 +
 |		0{Tide_Table_Reference}1 +
 |		0{Supplemental_Tidal_Information}1
\*----------------------------------------------------------------------*/
static int check_Tidal_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WType_of_Tide,
		WTime_of_Tide,
		WTide_Table_Reference,
		WSupplemental_Tidal_Information,
		Wnull);
	err += limit (p,1,
		WType_of_Tide,
		WTime_of_Tide,
		WSupplemental_Tidal_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Time_of_Tide
 |
 | Time of low and time of high tides the day(s) the data were collected
 |
 |	Time_of_Tide =
 |		0{Time_of_Low_Tide}1 +
 |		0{Time_of_High_Tide}1 +
 |		0{Tidal_Datum}1 +
 |		0{Range_of_Tide}1 +
\*----------------------------------------------------------------------*/
static int check_Time_of_Tide (struct item *p) {
	int err = 0;
	err += allow (p,
		WTime_of_High_Tide,
		WTime_of_Low_Tide,
		WTidal_Datum,
		WRange_of_Tide,
		Wnull);
	err += limit (p,1,
		WTime_of_High_Tide,
		WTime_of_Low_Tide,
		WTidal_Datum,
		WRange_of_Tide,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Remote-sensing profile elements
\*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*\
 | Acquisition_Information
 |
 | Information describing configuration under which data were acquired, including satellite and solar position and time correction.
 |
 |	Acquisition_Information =
 |		Satellite/Local_Zenith_Angle +
 |		Satellite/Local_Azimuth_Angle +
 |		Solar_Zenith_Angle +
 |		Solar_Azimuth_Angle +
 |		0{Relative_Azimuth}1 +
 |		Clock_Time/Drift +
 |		Ascending/Descending_Indicator +
 |		(Nadir)
\*----------------------------------------------------------------------*/
static int check_Acquisition_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WSatellite_Local_Zenith_Angle,
		WSatellite_Local_Azimuth_Angle,
		WSolar_Zenith_Angle,
		WSolar_Azimuth_Angle,
		WRelative_Azimuth,
		WClock_Time_Drift,
		WAscending_Descending_Indicator,
		WNadir,
		Wnull);
	err += require (p,
		WSatellite_Local_Zenith_Angle,
		WSatellite_Local_Azimuth_Angle,
		WSolar_Zenith_Angle,
		WSolar_Azimuth_Angle,
		WClock_Time_Drift,
		WAscending_Descending_Indicator,
		Wnull);
	err += limit (p,1,
		WSatellite_Local_Zenith_Angle,
		WSatellite_Local_Azimuth_Angle,
		WSolar_Zenith_Angle,
		WSolar_Azimuth_Angle,
		WRelative_Azimuth,
		WClock_Time_Drift,
		WAscending_Descending_Indicator,
		WNadir,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Aerotriangulation_Reference
 |
 | Reference containing information describing photogrammetric triangulation using aerial images.
 |
 |	Aerotriangulation_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Aerotriangulation_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Aggregation_Information
 |
 | Information relating a dataset to collections of which it is a component or relating a collection dataset to its components, as described in the section on Data Aggregation Technology.
 |
 |	Aggregation_Information =
 |		(1{Container_Packet_ID}n) +
 |		0{Component_Information}1
\*----------------------------------------------------------------------*/
static int check_Aggregation_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WContainer_Packet_ID,
		WComponent_Information,
		Wnull);
	err += limit (p,1,
		WComponent_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Aggregation_Member_ID
 |
 | Identifier of component of a dataset.
 |
 |	Aggregation_Member_ID =
 |		Dataset_Identifier
\*----------------------------------------------------------------------*/
static int check_Aggregation_Member_ID (struct item *p) {
	int err = 0;
	err += allow (p,
		WDataset_Identifier,
		Wnull);
	err += require (p,
		WDataset_Identifier,
		Wnull);
	err += limit (p,1,
		WDataset_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Change_Description
 |
 | Information included with dataset describing modifications of the algorithm in its development from version to version.
 |
 |	Algorithm_Change_Description =
 |		1{Process_Step}n
\*----------------------------------------------------------------------*/
static int check_Algorithm_Change_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcess_Step,
		Wnull);
	err += require (p,
		WProcess_Step,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WProcess_Step,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Change_History
 |
 | Description of the modifications of the algorithm in its development from version to version.
 |
 |	Algorithm_Change_History =
 |		[Algorithm_Change_Description |
 |		Algorithm_Change_Reference]
\*----------------------------------------------------------------------*/
static int check_Algorithm_Change_History (struct item *p) {
	int err = 0;
	err += allow (p,
		WAlgorithm_Change_Description,
		WAlgorithm_Change_Reference,
		Wnull);
	err += limit (p,1,
		WAlgorithm_Change_Description,
		WAlgorithm_Change_Reference,
		Wnull);
	/* Algorithm_Change_Description is Conditional - present and mandatory if and only if Algorithm_Change_Reference is absent */
	/* Algorithm_Change_Reference is Conditional - present and mandatory if and only if Algorithm_Change_Description is absent */
	err += allow_one_of (p,
		WAlgorithm_Change_Description,
		WAlgorithm_Change_Reference,
		Wnull);
	err += require_one_of (p,
		WAlgorithm_Change_Description,
		WAlgorithm_Change_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Change_Reference
 |
 | Reference to document describing modifications of the algorithm in its development from version to version.
 |
 |	Algorithm_Change_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Algorithm_Change_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Description
 |
 | Kinds of material providing a description of the algorithm used to generate the data.
 |
 |	Algorithm_Description =
 |		[Algorithm_Text_Description |
 |		Algorithm_Reference]
\*----------------------------------------------------------------------*/
static int check_Algorithm_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WAlgorithm_Text_Description,
		WAlgorithm_Reference,
		Wnull);
	err += limit (p,1,
		WAlgorithm_Text_Description,
		WAlgorithm_Reference,
		Wnull);
	/* Algorithm_Text_Description is Conditional - present and mandatory if and only if Algorithm_Reference is absent */
	/* Algorithm_Reference is Conditional - present and mandatory if and only if Algorithm_Text_Description is absent */
	err += allow_one_of (p,
		WAlgorithm_Text_Description,
		WAlgorithm_Reference,
		Wnull);
	err += require_one_of (p,
		WAlgorithm_Text_Description,
		WAlgorithm_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Identifiers
 |
 | Information identifying the algorithm and version or date.
 |
 |	Algorithm_Identifiers =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Algorithm_Identifiers (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Information
 |
 | Details of the methodology by which geographic information was derived from the instrument readings.
 |
 |	Algorithm_Information =
 |		Algorithm_Identifiers +
 |		Algorithm_Description +
 |		1{Algorithm_Change_History}n +
 |		(1{Algorithm_Peer_Review_Information}n)
\*----------------------------------------------------------------------*/
static int check_Algorithm_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WAlgorithm_Identifiers,
		WAlgorithm_Description,
		WAlgorithm_Change_History,
		WAlgorithm_Peer_Review_Information,
		Wnull);
	err += require (p,
		WAlgorithm_Identifiers,
		WAlgorithm_Description,
		WAlgorithm_Change_History,
		Wnull);
	err += limit (p,1,
		WAlgorithm_Identifiers,
		WAlgorithm_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Peer_Review_Description
 |
 | Description accompanying dataset, including dates, of peer review of the algorithm for purposes of ensuring its quality.
 |
 |	Algorithm_Peer_Review_Description =
 |		[1{Process_Step}n
\*----------------------------------------------------------------------*/
static int check_Algorithm_Peer_Review_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcess_Step,
		Wnull);
	err += require (p,
		WProcess_Step,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WProcess_Step,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Peer_Review_Information
 |
 | Description, including dates, of peer review of the algorithm for purposes of ensuring its quality.
 |
 |	Algorithm_Peer_Review_Information =
 |		[Algorithm_Peer_Review_Description |
 |		Algorithm_Peer_Review_Reference]
\*----------------------------------------------------------------------*/
static int check_Algorithm_Peer_Review_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WAlgorithm_Peer_Review_Description,
		WAlgorithm_Peer_Review_Reference,
		Wnull);
	err += limit (p,1,
		WAlgorithm_Peer_Review_Description,
		WAlgorithm_Peer_Review_Reference,
		Wnull);
	/* Algorithm_Peer_Review_Description is Conditional - present and mandatory if and only if Algorithm_Peer_Review_Reference is absent */
	/* Algorithm_Peer_Review_Reference is Conditional - present and mandatory if and only if Algorithm_Peer_Review_Description is absent */
	err += allow_one_of (p,
		WAlgorithm_Peer_Review_Description,
		WAlgorithm_Peer_Review_Reference,
		Wnull);
	err += require_one_of (p,
		WAlgorithm_Peer_Review_Description,
		WAlgorithm_Peer_Review_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Peer_Review_Reference
 |
 | Reference to document describing peer review of the algorithm for purposes of ensuring its quality, including dates.
 |
 |	Algorithm_Peer_Review_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Algorithm_Peer_Review_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Algorithm_Reference
 |
 | Reference to document containing description of algorithm.
 |
 |	Algorithm_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Algorithm_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ancillary_Dataset
 |
 | Data other than input required to process the input data.
 |
 |	Ancillary_Dataset =
 |		0{Ancillary_Dataset_Identifier}1 +
 |		[Ancillary_Description |
 |		Ancillary_Reference]
\*----------------------------------------------------------------------*/
static int check_Ancillary_Dataset (struct item *p) {
	int err = 0;
	err += allow (p,
		WAncillary_Dataset_Identifier,
		WAncillary_Description,
		WAncillary_Reference,
		Wnull);
	err += limit (p,1,
		WAncillary_Dataset_Identifier,
		WAncillary_Description,
		WAncillary_Reference,
		Wnull);
	/* Ancillary_Description is Conditional - present and mandatory if and only if Ancillary_Reference is absent */
	/* Ancillary_Reference is Conditional - present and mandatory if and only if Ancillary_Description is absent */
	err += allow_one_of (p,
		WAncillary_Description,
		WAncillary_Reference,
		Wnull);
	err += require_one_of (p,
		WAncillary_Description,
		WAncillary_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ancillary_Dataset_Identifier
 |
 | Unique identifier for ancillary dataset.
 |
 |	Ancillary_Dataset_Identifier =
 |		Dataset_Identifier
\*----------------------------------------------------------------------*/
static int check_Ancillary_Dataset_Identifier (struct item *p) {
	int err = 0;
	err += allow (p,
		WDataset_Identifier,
		Wnull);
	err += require (p,
		WDataset_Identifier,
		Wnull);
	err += limit (p,1,
		WDataset_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ancillary_Description
 |
 | Description of ancillary data and descriptive parameters used in processing step.
 |
 |	Ancillary_Description =
 |		Ancillary_Dataset_Description +
 |		0{Command_Line_Processing_Parameter}n
\*----------------------------------------------------------------------*/
static int check_Ancillary_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WAncillary_Dataset_Description,
		WCommand_Line_Processing_Parameter,
		Wnull);
	err += require (p,
		WAncillary_Dataset_Description,
		Wnull);
	err += limit (p,1,
		WAncillary_Dataset_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ancillary_Reference
 |
 | Reference to document describing ancillary data.
 |
 |	Ancillary_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Ancillary_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Angle_Dependent_Distortion
 |
 | Lens distortion values provided as a function of the angle from the optical axis.
 |
 |	Angle_Dependent_Distortion =
 |		Radial_Symmetrical_Angle_Interval +
 |		Number_of_Angle_Distortion_Values +
 |		1{Angle_Distortion_Value}n
\*----------------------------------------------------------------------*/
static int check_Angle_Dependent_Distortion (struct item *p) {
	int err = 0;
	err += allow (p,
		WRadial_Symmetrical_Angle_Interval,
		WNumber_of_Angle_Distortion_Values,
		WAngle_Distortion_Value,
		Wnull);
	err += require (p,
		WRadial_Symmetrical_Angle_Interval,
		WNumber_of_Angle_Distortion_Values,
		WAngle_Distortion_Value,
		Wnull);
	err += limit (p,1,
		WRadial_Symmetrical_Angle_Interval,
		WNumber_of_Angle_Distortion_Values,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Axes
 |
 | Orientation of instrument axes.
 |
 |	Axes =
 |		X_Axis_Definition +
 |		Y_Axis_Definition +
 |		Z_Axis_Definition
\*----------------------------------------------------------------------*/
static int check_Axes (struct item *p) {
	int err = 0;
	err += allow (p,
		WX_Axis_Definition,
		WY_Axis_Definition,
		WZ_Axis_Definition,
		Wnull);
	err += require (p,
		WX_Axis_Definition,
		WY_Axis_Definition,
		WZ_Axis_Definition,
		Wnull);
	err += limit (p,1,
		WX_Axis_Definition,
		WY_Axis_Definition,
		WZ_Axis_Definition,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Band_Identification
 |
 | Complete information to identify instrument wavelengths or other channels.
 |
 |	Band_Identification =
 |		Number_of_Bands +
 |		0{Individual_Band_Identification}n
\*----------------------------------------------------------------------*/
static int check_Band_Identification (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Bands,
		WIndividual_Band_Identification,
		Wnull);
	err += require (p,
		WNumber_of_Bands,
		Wnull);
	err += limit (p,1,
		WNumber_of_Bands,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Calibrated_Detector_Positions
 |
 | Position of detectors in sensor grid coordinate system.
 |
 |	Calibrated_Detector_Positions =
 |		Location_Information
\*----------------------------------------------------------------------*/
static int check_Calibrated_Detector_Positions (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocation_Information,
		Wnull);
	err += require (p,
		WLocation_Information,
		Wnull);
	err += limit (p,1,
		WLocation_Information,
		Wnull);
	/* Location_Information is Specified by referencing element. */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Component_Information
 |
 | Information about components aggregated into the dataset.
 |
 |	Component_Information =
 |		1{Aggregation_Member_ID}n +
 |		1{Aggregation_Criteria}n
\*----------------------------------------------------------------------*/
static int check_Component_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WAggregation_Member_ID,
		WAggregation_Criteria,
		Wnull);
	err += require (p,
		WAggregation_Member_ID,
		WAggregation_Criteria,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Container_Packet_ID
 |
 | Identifier of an aggregation of which the dataset is a member.
 |
 |	Container_Packet_ID =
 |		Dataset_Identifier
\*----------------------------------------------------------------------*/
static int check_Container_Packet_ID (struct item *p) {
	int err = 0;
	err += allow (p,
		WDataset_Identifier,
		Wnull);
	err += require (p,
		WDataset_Identifier,
		Wnull);
	err += limit (p,1,
		WDataset_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Control_Point_Authority
 |
 | Contact who can supply ground control point coordinates given identifier.
 |
 |	Control_Point_Authority =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Control_Point_Authority (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Information,
		Wnull);
	err += require (p,
		WContact_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WContact_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Control_Point_Earth_Location
 |
 | Geographic or map location of ground control point.
 |
 |	Control_Point_Earth_Location =
 |		Control_Point_x_Value +
 |		Control_Point_y_Value +
 |		(Control_Point_z_Value)
\*----------------------------------------------------------------------*/
static int check_Control_Point_Earth_Location (struct item *p) {
	int err = 0;
	err += allow (p,
		WControl_Point_x_Value,
		WControl_Point_y_Value,
		WControl_Point_z_Value,
		Wnull);
	err += require (p,
		WControl_Point_x_Value,
		WControl_Point_y_Value,
		Wnull);
	err += limit (p,1,
		WControl_Point_x_Value,
		WControl_Point_y_Value,
		WControl_Point_z_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Control_Point_Identification
 |
 | Information allowing the user to find the location of a control point from a catalogue.
 |
 |	Control_Point_Identification =
 |		Control_Point_ID +
 |		Control_Point_Authority
\*----------------------------------------------------------------------*/
static int check_Control_Point_Identification (struct item *p) {
	int err = 0;
	err += allow (p,
		WControl_Point_ID,
		WControl_Point_Authority,
		Wnull);
	err += require (p,
		WControl_Point_ID,
		WControl_Point_Authority,
		Wnull);
	err += limit (p,1,
		WControl_Point_ID,
		WControl_Point_Authority,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Control_Point_Raster_Position
 |
 | Position in raster array of individual ground control point used in geolocating data.
 |
 |	Control_Point_Raster_Position =
 |		Control_Point_Row +
 |		Control_Point_Column
\*----------------------------------------------------------------------*/
static int check_Control_Point_Raster_Position (struct item *p) {
	int err = 0;
	err += allow (p,
		WControl_Point_Row,
		WControl_Point_Column,
		Wnull);
	err += require (p,
		WControl_Point_Row,
		WControl_Point_Column,
		Wnull);
	err += limit (p,1,
		WControl_Point_Row,
		WControl_Point_Column,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Coordinate_Point
 |
 | Location of a coordinate point described by the referencing element.
 |
 |	Coordinate_Point =
 |		Coordinate_x_Value +
 |		Coordinate_y_Value +
 |		0{Coordinate_z_Value}1
\*----------------------------------------------------------------------*/
static int check_Coordinate_Point (struct item *p) {
	int err = 0;
	err += allow (p,
		WCoordinate_x_Value,
		WCoordinate_y_Value,
		WCoordinate_z_Value,
		Wnull);
	err += require (p,
		WCoordinate_x_Value,
		WCoordinate_y_Value,
		Wnull);
	err += limit (p,1,
		WCoordinate_x_Value,
		WCoordinate_y_Value,
		WCoordinate_z_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Coordinate_System
 |
 | Definition of axes of coordinate system in which location of positions is provided.
 |
 |	Coordinate_System =
 |		[Unreferenced_Coordinate_System |
 |		Referenced_Coordinate_System]
\*----------------------------------------------------------------------*/
static int check_Coordinate_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WUnreferenced_Coordinate_System,
		WReferenced_Coordinate_System,
		Wnull);
	err += limit (p,1,
		WUnreferenced_Coordinate_System,
		WReferenced_Coordinate_System,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Cross_Track_Sweep
 |
 | Description of angular properties of cross-track sweep.
 |
 |	Cross_Track_Sweep =
 |		Number_of_Cross_Track_Samples +
 |		Cross_Track_Start_Angle +
 |		[Cross_Track_Extent_Angle |
 |		Cross_Track_Step_Angle]
\*----------------------------------------------------------------------*/
static int check_Cross_Track_Sweep (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Cross_Track_Samples,
		WCross_Track_Start_Angle,
		WCross_Track_Extent_Angle,
		WCross_Track_Step_Angle,
		Wnull);
	err += require (p,
		WNumber_of_Cross_Track_Samples,
		WCross_Track_Start_Angle,
		Wnull);
	err += limit (p,1,
		WNumber_of_Cross_Track_Samples,
		WCross_Track_Start_Angle,
		WCross_Track_Extent_Angle,
		WCross_Track_Step_Angle,
		Wnull);
	/* Cross_Track_Extent_Angle is Conditional - present and mandatory if and only if Cross_Track_Step_Angle is absent */
	/* Cross_Track_Step_Angle is Conditional - present and mandatory if and only if Cross_Track_Extent_Angle is absent */
	err += allow_one_of (p,
		WCross_Track_Extent_Angle,
		WCross_Track_Step_Angle,
		Wnull);
	err += require_one_of (p,
		WCross_Track_Extent_Angle,
		WCross_Track_Step_Angle,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Cross_Track_Zero
 |
 | Direction relative to which cross-track angles are measured.
 |
 |	Cross_Track_Zero =
 |		Cross_Track_Axis +
 |		Cross_Track_Direction
\*----------------------------------------------------------------------*/
static int check_Cross_Track_Zero (struct item *p) {
	int err = 0;
	err += allow (p,
		WCross_Track_Axis,
		WCross_Track_Direction,
		Wnull);
	err += require (p,
		WCross_Track_Axis,
		WCross_Track_Direction,
		Wnull);
	err += limit (p,1,
		WCross_Track_Axis,
		WCross_Track_Direction,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Data_Dictionary_Reference
 |
 | Reference to a list of terms and their definitions, used in describing the dataset.
 |
 |	Data_Dictionary_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Data_Dictionary_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Data_Scaling_Information
 |
 | Function converting set of values on one scale to another.
 |
 |	Data_Scaling_Information =
 |		[Polynomial_Function |
 |		Non_Polynomial_Scaling]
\*----------------------------------------------------------------------*/
static int check_Data_Scaling_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WPolynomial_Function,
		WNon_Polynomial_Scaling,
		Wnull);
	err += limit (p,1,
		WPolynomial_Function,
		WNon_Polynomial_Scaling,
		Wnull);
	/* Polynomial_Function is Conditional - present and mandatory if and only if Non_Polynomial_Scaling is absent */
	/* Non_Polynomial_Scaling is Conditional - present and mandatory if and only if Polynomial_Function is absent */
	err += allow_one_of (p,
		WPolynomial_Function,
		WNon_Polynomial_Scaling,
		Wnull);
	err += require_one_of (p,
		WPolynomial_Function,
		WNon_Polynomial_Scaling,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Developing_Institution
 |
 | Institution where the film was developed.
 |
 |	Developing_Institution =
 |		Contact_Information
\*----------------------------------------------------------------------*/
static int check_Developing_Institution (struct item *p) {
	int err = 0;
	err += allow (p,
		WContact_Information,
		Wnull);
	err += require (p,
		WContact_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WContact_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Dimension_Description
 |
 | Specification for the independent axes in the coordinate system in which spatial data are located.
 |
 |	Dimension_Description =
 |		Number_of_Data_Dimensions +
 |		1{Dimension_Properties}n
\*----------------------------------------------------------------------*/
static int check_Dimension_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Data_Dimensions,
		WDimension_Properties,
		Wnull);
	err += require (p,
		WNumber_of_Data_Dimensions,
		WDimension_Properties,
		Wnull);
	err += limit (p,1,
		WNumber_of_Data_Dimensions,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Dimension_Properties
 |
 | Description of individual axis in spatial data matrix.
 |
 |	Dimension_Properties =
 |		Name_of_Dimension +
 |		Dimension_Count
\*----------------------------------------------------------------------*/
static int check_Dimension_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WName_of_Dimension,
		WDimension_Count,
		Wnull);
	err += require (p,
		WName_of_Dimension,
		WDimension_Count,
		Wnull);
	err += limit (p,1,
		WName_of_Dimension,
		WDimension_Count,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Distance_Dependent_Distortion
 |
 | Lens distortion values provided as a function of linear distance to the principal point of best symmetry.
 |
 |	Distance_Dependent_Distortion =
 |		Radial_Symmetrical_Distance_Interval +
 |		Number_of_Distance_Distortion_Values +
 |		1{Distance_Distortion_Value}n
\*----------------------------------------------------------------------*/
static int check_Distance_Dependent_Distortion (struct item *p) {
	int err = 0;
	err += allow (p,
		WRadial_Symmetrical_Distance_Interval,
		WNumber_of_Distance_Distortion_Values,
		WDistance_Distortion_Value,
		Wnull);
	err += require (p,
		WRadial_Symmetrical_Distance_Interval,
		WNumber_of_Distance_Distortion_Values,
		WDistance_Distortion_Value,
		Wnull);
	err += limit (p,1,
		WRadial_Symmetrical_Distance_Interval,
		WNumber_of_Distance_Distortion_Values,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Distortion
 |
 | Departure of positions in image from those in scene imaged.
 |
 |	Distortion =
 |		0{Distortion_Type_Radial_Symmetrical}1 +
 |		(Distortion_Type_Radial_Asymmetrical) +
 |		(Distortion_Type_Affine)
\*----------------------------------------------------------------------*/
static int check_Distortion (struct item *p) {
	int err = 0;
	err += allow (p,
		WDistortion_Type_Radial_Symmetrical,
		WDistortion_Type_Radial_Asymmetrical,
		WDistortion_Type_Affine,
		Wnull);
	err += limit (p,1,
		WDistortion_Type_Radial_Symmetrical,
		WDistortion_Type_Radial_Asymmetrical,
		WDistortion_Type_Affine,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Distortion_Type_Affine
 |
 | Errors of the image coordinate system that can be described with an affine transformation of the following form:
x' = C1 * x'  +  C2 * y'
y' = 0
 |
 |	Distortion_Type_Affine =
 |		Affine_Distortion_X_Prime_Coefficient +
 |		Affine_Distortion_Y_Prime_Coefficient
\*----------------------------------------------------------------------*/
static int check_Distortion_Type_Affine (struct item *p) {
	int err = 0;
	err += allow (p,
		WAffine_Distortion_X_Prime_Coefficient,
		WAffine_Distortion_Y_Prime_Coefficient,
		Wnull);
	err += require (p,
		WAffine_Distortion_X_Prime_Coefficient,
		WAffine_Distortion_Y_Prime_Coefficient,
		Wnull);
	err += limit (p,1,
		WAffine_Distortion_X_Prime_Coefficient,
		WAffine_Distortion_Y_Prime_Coefficient,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Distortion_Type_Radial_Asymmetrical
 |
 | Distortion that can be expressed in the form
x' = B1  (r'2  +  2x'2)  +  2B2 * x' * y'
y' = B2  (r'2  +  2x'2)  +  2B1 * x' * y'
 |
 |	Distortion_Type_Radial_Asymmetrical =
 |		Radial_Asymmetrical_Coefficient_B1 +
 |		Radial_Asymmetrical_Coefficient_B2
\*----------------------------------------------------------------------*/
static int check_Distortion_Type_Radial_Asymmetrical (struct item *p) {
	int err = 0;
	err += allow (p,
		WRadial_Asymmetrical_Coefficient_B1,
		WRadial_Asymmetrical_Coefficient_B2,
		Wnull);
	err += require (p,
		WRadial_Asymmetrical_Coefficient_B1,
		WRadial_Asymmetrical_Coefficient_B2,
		Wnull);
	err += limit (p,1,
		WRadial_Asymmetrical_Coefficient_B1,
		WRadial_Asymmetrical_Coefficient_B2,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Distortion_Type_Radial_Symmetrical
 |
 | The shift of an image point towards the center (negative values) or border (positive values) of the image.
 |
 |	Distortion_Type_Radial_Symmetrical =
 |		[Distance_Dependent_Distortion |
 |		Angle_Dependent_Distortion |
 |		Radial_Symmetrical_Distortion_Polynomial]
\*----------------------------------------------------------------------*/
static int check_Distortion_Type_Radial_Symmetrical (struct item *p) {
	int err = 0;
	err += allow (p,
		WDistance_Dependent_Distortion,
		WAngle_Dependent_Distortion,
		WRadial_Symmetrical_Distortion_Polynomial,
		Wnull);
	err += limit (p,1,
		WDistance_Dependent_Distortion,
		WAngle_Dependent_Distortion,
		WRadial_Symmetrical_Distortion_Polynomial,
		Wnull);
	/* Distance_Dependent_Distortion is Conditional - present and mandatory if and only if Angle_Dependent_Distortion and Radial_Symmetrical_Distortion_Polynomial are absent */
	/* Angle_Dependent_Distortion is Conditional - present and mandatory if and only if Distance_Dependent_Distortion and Radial_Symmetrical_Distortion_Polynomial are absent */
	/* Radial_Symmetrical_Distortion_Polynomial is Conditional - present and mandatory if and only if Distance_Dependent_Distortion and Angle_Dependent_Distortion are absent */
	err += allow_one_of (p,
		WDistance_Dependent_Distortion,
		WAngle_Dependent_Distortion,
		WRadial_Symmetrical_Distortion_Polynomial,
		Wnull);
	err += require_one_of (p,
		WDistance_Dependent_Distortion,
		WAngle_Dependent_Distortion,
		WRadial_Symmetrical_Distortion_Polynomial,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Documentation
 |
 | Information about or relevant to the dataset.
 |
 |	Documentation =
 |		(1{Data_Dictionary_Reference}n) +
 |		(1{User's_Guide}n) +
 |		(1{Science_Paper}n)
\*----------------------------------------------------------------------*/
static int check_Documentation (struct item *p) {
	int err = 0;
	err += allow (p,
		WData_Dictionary_Reference,
		WUsers_Guide,
		WScience_Paper,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Elevation_Sweep
 |
 | Description of angular properties of elevation sweep.
 |
 |	Elevation_Sweep =
 |		Number_of_Elevation_Samples +
 |		Elevation_Start_Angle +
 |		[Elevation_Extent_Angle |
 |		Elevation_Step_Angle]
\*----------------------------------------------------------------------*/
static int check_Elevation_Sweep (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Elevation_Samples,
		WElevation_Start_Angle,
		WElevation_Extent_Angle,
		WElevation_Step_Angle,
		Wnull);
	err += require (p,
		WNumber_of_Elevation_Samples,
		WElevation_Start_Angle,
		Wnull);
	err += limit (p,1,
		WNumber_of_Elevation_Samples,
		WElevation_Start_Angle,
		WElevation_Extent_Angle,
		WElevation_Step_Angle,
		Wnull);
	/* Elevation_Extent_Angle is Conditional - present and mandatory if and only if Elevation_Step_Angle is absent */
	/* Elevation_Step_Angle is Conditional - present and mandatory if and only if Elevation_Extent_Angle is absent */
	err += allow_one_of (p,
		WElevation_Extent_Angle,
		WElevation_Step_Angle,
		Wnull);
	err += require_one_of (p,
		WElevation_Extent_Angle,
		WElevation_Step_Angle,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Elevation_Zero
 |
 | Direction relative to which elevation angles are measured.
 |
 |	Elevation_Zero =
 |		Elevation_Axis +
 |		Elevation_Direction
\*----------------------------------------------------------------------*/
static int check_Elevation_Zero (struct item *p) {
	int err = 0;
	err += allow (p,
		WElevation_Axis,
		WElevation_Direction,
		Wnull);
	err += require (p,
		WElevation_Axis,
		WElevation_Direction,
		Wnull);
	err += limit (p,1,
		WElevation_Axis,
		WElevation_Direction,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ephemeris
 |
 | Time at which nominal platform orbit or geostationary position is valid.
 |
 |	Ephemeris =
 |		Single_Date/Time
\*----------------------------------------------------------------------*/
static int check_Ephemeris (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		Wnull);
	err += require (p,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Exterior_Orientation_Accuracy
 |
 | Uncertainties in the parameters of exterior orientation.
 |
 |	Exterior_Orientation_Accuracy =
 |		X_Position_Accuracy +
 |		Y_Position_Accuracy +
 |		Z_Position_Accuracy +
 |		Roll_Accuracy +
 |		Pitch_Accuracy +
 |		Yaw_Accuracy
\*----------------------------------------------------------------------*/
static int check_Exterior_Orientation_Accuracy (struct item *p) {
	int err = 0;
	err += allow (p,
		WX_Position_Accuracy,
		WY_Position_Accuracy,
		WZ_Position_Accuracy,
		WRoll_Accuracy,
		WPitch_Accuracy,
		WYaw_Accuracy,
		Wnull);
	err += require (p,
		WX_Position_Accuracy,
		WY_Position_Accuracy,
		WZ_Position_Accuracy,
		WRoll_Accuracy,
		WPitch_Accuracy,
		WYaw_Accuracy,
		Wnull);
	err += limit (p,1,
		WX_Position_Accuracy,
		WY_Position_Accuracy,
		WZ_Position_Accuracy,
		WRoll_Accuracy,
		WPitch_Accuracy,
		WYaw_Accuracy,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Fiducial
 |
 | Calibrated coordinates for four or more marks attached to the frame of the camera, in millimeters in the image coordinate system.
 |
 |	Fiducial =
 |		Location_Information
\*----------------------------------------------------------------------*/
static int check_Fiducial (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocation_Information,
		Wnull);
	err += require (p,
		WLocation_Information,
		Wnull);
	err += limit (p,1,
		WLocation_Information,
		Wnull);
	/* Location_Information is Specified by referencing element. */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Fiducial_Center
 |
 | Coordinates in millimeters, in the image coordinate system, of center point where lines between the four or more fiducial marks meet.
 |
 |	Fiducial_Center =
 |		Location_Information
\*----------------------------------------------------------------------*/
static int check_Fiducial_Center (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocation_Information,
		Wnull);
	err += require (p,
		WLocation_Information,
		Wnull);
	err += limit (p,1,
		WLocation_Information,
		Wnull);
	/* Location_Information is Specified by referencing element. */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Filter_on_Camera
 |
 | Device placed in front of camera lens limiting the range of wavelengths that can pass through.
 |
 |	Filter_on_Camera =
 |		Filter_on_Camera_Indicator +
 |		0{Filter_Type}1 +
\*----------------------------------------------------------------------*/
static int check_Filter_on_Camera (struct item *p) {
	int err = 0;
	err += allow (p,
		WFilter_on_Camera_Indicator,
		WFilter_Type,
		Wnull);
	err += require (p,
		WFilter_on_Camera_Indicator,
		Wnull);
	err += limit (p,1,
		WFilter_on_Camera_Indicator,
		WFilter_Type,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Flight_Protocol
 |
 | Description of circumstances and properties of the flight track relevant to use of the images and data.
 |
 |	Flight_Protocol =
 |		Flying_Height +
 |		(GPS_Information_System_Availability) +
 |		(INS_Reading_Availability)
\*----------------------------------------------------------------------*/
static int check_Flight_Protocol (struct item *p) {
	int err = 0;
	err += allow (p,
		WFlying_Height,
		WGPS_Information_System_Availability,
		WINS_Reading_Availability,
		Wnull);
	err += require (p,
		WFlying_Height,
		Wnull);
	err += limit (p,1,
		WFlying_Height,
		WGPS_Information_System_Availability,
		WINS_Reading_Availability,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Area
 |
 | Geographical area covered by individual frame.
 |
 |	Frame_Area =
 |		Frame_Area_Value +
 |		Frame_Area_Units
\*----------------------------------------------------------------------*/
static int check_Frame_Area (struct item *p) {
	int err = 0;
	err += allow (p,
		WFrame_Area_Value,
		WFrame_Area_Units,
		Wnull);
	err += require (p,
		WFrame_Area_Value,
		WFrame_Area_Units,
		Wnull);
	err += limit (p,1,
		WFrame_Area_Value,
		WFrame_Area_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Camera
 |
 | Description of  photographic system using a central perspective projection, with the detector, normally film, pressed against a calibrated frame during the exposure.
 |
 |	Frame_Camera =
 |		(Frame_Hardware) +
 |		Frame_Optics +
 |		Frame_Geometric_Properties +
 |		(Frame_Operation) +
 |		(Frame_Radiometric_Properties) +
 |		(Frame_Spectral_Properties)
\*----------------------------------------------------------------------*/
static int check_Frame_Camera (struct item *p) {
	int err = 0;
	err += allow (p,
		WFrame_Hardware,
		WFrame_Optics,
		WFrame_Geometric_Properties,
		WFrame_Operation,
		WFrame_Radiometric_Properties,
		WFrame_Spectral_Properties,
		Wnull);
	err += require (p,
		WFrame_Optics,
		WFrame_Geometric_Properties,
		Wnull);
	err += limit (p,1,
		WFrame_Hardware,
		WFrame_Optics,
		WFrame_Geometric_Properties,
		WFrame_Operation,
		WFrame_Radiometric_Properties,
		WFrame_Spectral_Properties,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Geometric_Properties
 |
 | Geometric characteristics of instrument used to derive single frame images.
 |
 |	Frame_Geometric_Properties =
 |		(Image_Size) +
 |		[Fiducial |
 |		Reseau |
 |		Sensor_System] +
 |		0{Principal_Point_of_Autocollimation}1 +
 |		(Quality_of_Principal_Point_of_Autocollimation) +
 |		(Principal_Point_of_Symmetry) +
 |		(Quality_of_Principal_Point_of_Symmetry) +
 |		(Fiducial_Center) +
 |		(Sensor_Element_Location) +
 |		0{Distortion}1
\*----------------------------------------------------------------------*/
static int check_Frame_Geometric_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WImage_Size,
		WFiducial,
		WReseau,
		WSensor_System,
		WPrincipal_Point_of_Autocollimation,
		WQuality_of_Principal_Point_of_Autocollimation,
		WPrincipal_Point_of_Symmetry,
		WQuality_of_Principal_Point_of_Symmetry,
		WFiducial_Center,
		WSensor_Element_Location,
		WDistortion,
		Wnull);
	err += limit (p,1,
		WImage_Size,
		WFiducial,
		WReseau,
		WSensor_System,
		WPrincipal_Point_of_Autocollimation,
		WQuality_of_Principal_Point_of_Autocollimation,
		WPrincipal_Point_of_Symmetry,
		WQuality_of_Principal_Point_of_Symmetry,
		WFiducial_Center,
		WSensor_Element_Location,
		WDistortion,
		Wnull);
	/* Fiducial is Conditional - present and mandatory if and only if Reseau and Sensor_System are absent */
	/* Reseau is Conditional - present and mandatory if and only if Fiducial and Sensor_System are absent */
	/* Sensor_System is Conditional - present and mandatory if and only if Fiducial and Reseau are absent */
	err += allow_one_of (p,
		WFiducial,
		WReseau,
		WSensor_System,
		Wnull);
	err += require_one_of (p,
		WFiducial,
		WReseau,
		WSensor_System,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Hardware
 |
 | Physical description of camera and film.
 |
 |	Frame_Hardware =
 |		(Camera_Type) +
 |		(Camera_Identifier) +
 |		(Lens) +
 |		(Magazine_Identifier) +
 |		(Film_Type) +
 |		(Aerial_Film_Speed) +
 |		(Effective_Aerial_Film_Speed) +
 |		(Developing_Institution)
\*----------------------------------------------------------------------*/
static int check_Frame_Hardware (struct item *p) {
	int err = 0;
	err += allow (p,
		WCamera_Type,
		WCamera_Identifier,
		WLens,
		WMagazine_Identifier,
		WFilm_Type,
		WAerial_Film_Speed,
		WEffective_Aerial_Film_Speed,
		WDeveloping_Institution,
		Wnull);
	err += limit (p,1,
		WCamera_Type,
		WCamera_Identifier,
		WLens,
		WMagazine_Identifier,
		WFilm_Type,
		WAerial_Film_Speed,
		WEffective_Aerial_Film_Speed,
		WDeveloping_Institution,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Operation
 |
 | Information describing the configuration or motion of the camera mounting.
 |
 |	Frame_Operation =
 |		(Stabilized_Mount) +
 |		(Forward_Motion_Compensation)
\*----------------------------------------------------------------------*/
static int check_Frame_Operation (struct item *p) {
	int err = 0;
	err += allow (p,
		WStabilized_Mount,
		WForward_Motion_Compensation,
		Wnull);
	err += limit (p,1,
		WStabilized_Mount,
		WForward_Motion_Compensation,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Optics
 |
 | Physical description of the photographic system.
 |
 |	Frame_Optics =
 |		(Photographic_Resolving_Power) +
 |		(Relative_Aperture) +
 |		(Exposure_Time) +
 |		Calibrated_Focal_Length +
 |		(Quality_of_Focal_Length) +
 |		(Last_Calibration)
\*----------------------------------------------------------------------*/
static int check_Frame_Optics (struct item *p) {
	int err = 0;
	err += allow (p,
		WPhotographic_Resolving_Power,
		WRelative_Aperture,
		WExposure_Time,
		WCalibrated_Focal_Length,
		WQuality_of_Focal_Length,
		WLast_Calibration,
		Wnull);
	err += require (p,
		WCalibrated_Focal_Length,
		Wnull);
	err += limit (p,1,
		WPhotographic_Resolving_Power,
		WRelative_Aperture,
		WExposure_Time,
		WCalibrated_Focal_Length,
		WQuality_of_Focal_Length,
		WLast_Calibration,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Radiometric_Calibration
 |
 | Transformation from units in which electronic detector measures to physical units.
 |
 |	Frame_Radiometric_Calibration =
 |		Data_Scaling_Information
\*----------------------------------------------------------------------*/
static int check_Frame_Radiometric_Calibration (struct item *p) {
	int err = 0;
	err += allow (p,
		WData_Scaling_Information,
		Wnull);
	err += require (p,
		WData_Scaling_Information,
		Wnull);
	err += limit (p,1,
		WData_Scaling_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Radiometric_Properties
 |
 | Information on the relation between radiation received and measured by a detector system.
 |
 |	Frame_Radiometric_Properties =
 |		0{Frame_Radiometric_Calibration}1 +
 |		(Light_Drop)
\*----------------------------------------------------------------------*/
static int check_Frame_Radiometric_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WFrame_Radiometric_Calibration,
		WLight_Drop,
		Wnull);
	err += limit (p,1,
		WFrame_Radiometric_Calibration,
		WLight_Drop,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Spectral_Information
 |
 | Information about wavelength sensitivity of detector.
 |
 |	Frame_Spectral_Information =
 |		Spectral_Information
\*----------------------------------------------------------------------*/
static int check_Frame_Spectral_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WSpectral_Information,
		Wnull);
	err += require (p,
		WSpectral_Information,
		Wnull);
	err += limit (p,1,
		WSpectral_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Frame_Spectral_Properties
 |
 | Wavelength-dependent characteristics of system.
 |
 |	Frame_Spectral_Properties =
 |		(Frame_Spectral_Information) +
 |		(Filter_on_Camera) +
 |		(Spectral_Limit)
\*----------------------------------------------------------------------*/
static int check_Frame_Spectral_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WFrame_Spectral_Information,
		WFilter_on_Camera,
		WSpectral_Limit,
		Wnull);
	err += limit (p,1,
		WFrame_Spectral_Information,
		WFilter_on_Camera,
		WSpectral_Limit,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Georectified_Raster
 |
 | Raster whose cells are regularly spaced in a geographic or map coordinate system defined in some Spatial_Referencing_System, such that any cell can be geolocated given its raster coordinate and the raster origin, cell spacing, and orientation, possibly including a terrain model. (Note: Let amn be the  pixel grid point in the  mth row and the nth column, with (x,y) the position of that grid point in map coordinates.  Let the map position corresponding to the first element of the grid a11 be (x0,y0).  Then x= x0 + (m-1)xm +(n-1)ym and y= y0  + (m-1)xn +(n-1)yn, where the  terms are defined in the elements below. The overlay is shown in Figure 3, with definitions of the individual pixels.)
 |
 |	Georectified_Raster =
 |		Pixel_Resolution +
 |		Grid_First_Element +
 |		Grid_Orientation +
 |		Point_Position_In_Pixel +
 |		Storage_Order
\*----------------------------------------------------------------------*/
static int check_Georectified_Raster (struct item *p) {
	int err = 0;
	err += allow (p,
		WPixel_Resolution,
		WGrid_First_Element,
		WGrid_Orientation,
		WPoint_Position_In_Pixel,
		WStorage_Order,
		Wnull);
	err += require (p,
		WPixel_Resolution,
		WGrid_First_Element,
		WGrid_Orientation,
		WPoint_Position_In_Pixel,
		WStorage_Order,
		Wnull);
	err += limit (p,1,
		WPixel_Resolution,
		WGrid_First_Element,
		WGrid_Orientation,
		WPoint_Position_In_Pixel,
		WStorage_Order,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Georeferenceable_Raster
 |
 | Raster whose cells may be irregularly spaced in any geographic or map projection coordinate system, whose cells can be geolocated using geolocation information supplied with the data but not from the raster properties alone.
 |
 |	Georeferenceable_Raster =
 |		1{Georeferencing_Description}n +
 |		(1{Aerotriangulation_Reference}n) +
 |		0{Swath_Track_Information}1
\*----------------------------------------------------------------------*/
static int check_Georeferenceable_Raster (struct item *p) {
	int err = 0;
	err += allow (p,
		WGeoreferencing_Description,
		WAerotriangulation_Reference,
		WSwath_Track_Information,
		Wnull);
	err += require (p,
		WGeoreferencing_Description,
		Wnull);
	err += limit (p,1,
		WSwath_Track_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Georeferencing_Description
 |
 | Description of information provided in metadata that allows the geographic or map location of raster points to be located.
 |
 |	Georeferencing_Description =
 |		[Ground_Control_Point_Information |
 |		Instrument_Specific_Georeferencing |
 |		Referencing_Polynomial |
 |		Other_Georeferencing_Description]
\*----------------------------------------------------------------------*/
static int check_Georeferencing_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WGround_Control_Point_Information,
		WInstrument_Specific_Georeferencing,
		WReferencing_Polynomial,
		WOther_Georeferencing_Description,
		Wnull);
	err += limit (p,1,
		WGround_Control_Point_Information,
		WInstrument_Specific_Georeferencing,
		WReferencing_Polynomial,
		WOther_Georeferencing_Description,
		Wnull);
	/* Ground_Control_Point_Information is Conditional - mandatory if neither Instrument_Specific_Georeferencing, Referencing_Polynomial, nor Other_Georeferencing_Description is present; otherwise optional */
	/* Instrument_Specific_Georeferencing is Conditional - mandatory if neither Ground_Control_Point_Information, Referencing_Polynomial, nor Other_Georeferencing_Description is present; otherwise optional */
	/* Referencing_Polynomial is Conditional - mandatory if neither Ground_Control_Point_Information, Instrument_Specific_Georeferencing, nor Other_Georeferencing_Description is present; otherwise optional */
	/* Other_Georeferencing_Description is Conditional - mandatory if neither Ground_Control_Point_Information, Instrument_Specific_Georeferencing, nor Referencing_Polynomial is present; otherwise optional */
	err += allow_one_of (p,
		WGround_Control_Point_Information,
		WInstrument_Specific_Georeferencing,
		WReferencing_Polynomial,
		WOther_Georeferencing_Description,
		Wnull);
	err += require_one_of (p,
		WGround_Control_Point_Information,
		WInstrument_Specific_Georeferencing,
		WReferencing_Polynomial,
		WOther_Georeferencing_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Georeferencing_Information
 |
 | Information that will allow determination of geographical location of raster points.
 |
 |	Georeferencing_Information =
 |		[Georectified_Raster |
 |		Georeferenceable_Raster]
\*----------------------------------------------------------------------*/
static int check_Georeferencing_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WGeorectified_Raster,
		WGeoreferenceable_Raster,
		Wnull);
	err += limit (p,1,
		WGeorectified_Raster,
		WGeoreferenceable_Raster,
		Wnull);
	/* Georectified_Raster is Conditional - present and mandatory if and only if Georeferenceable_Raster is absent */
	/* Georeferenceable_Raster is Conditional - present and mandatory if and only if Georectified_Raster is absent */
	err += allow_one_of (p,
		WGeorectified_Raster,
		WGeoreferenceable_Raster,
		Wnull);
	err += require_one_of (p,
		WGeorectified_Raster,
		WGeoreferenceable_Raster,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Grid_First_Element
 |
 | Point on map (x0,y0) corresponding to first element of the pixel array.
 |
 |	Grid_First_Element =
 |		Grid_First_Element_Map_X_Coordinate +
 |		Grid_First_Element_Map_Y_Coordinate
\*----------------------------------------------------------------------*/
static int check_Grid_First_Element (struct item *p) {
	int err = 0;
	err += allow (p,
		WGrid_First_Element_Map_X_Coordinate,
		WGrid_First_Element_Map_Y_Coordinate,
		Wnull);
	err += require (p,
		WGrid_First_Element_Map_X_Coordinate,
		WGrid_First_Element_Map_Y_Coordinate,
		Wnull);
	err += limit (p,1,
		WGrid_First_Element_Map_X_Coordinate,
		WGrid_First_Element_Map_Y_Coordinate,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Grid_Orientation
 |
 | Orientation of image pixel grid relative to map on which it is overlaid.
 |
 |	Grid_Orientation =
 |		Row_Delta_X +
 |		Row_Delta_Y +
 |		Column_Delta_X +
 |		Column_Delta_Y
\*----------------------------------------------------------------------*/
static int check_Grid_Orientation (struct item *p) {
	int err = 0;
	err += allow (p,
		WRow_Delta_X,
		WRow_Delta_Y,
		WColumn_Delta_X,
		WColumn_Delta_Y,
		Wnull);
	err += require (p,
		WRow_Delta_X,
		WRow_Delta_Y,
		WColumn_Delta_X,
		WColumn_Delta_Y,
		Wnull);
	err += limit (p,1,
		WRow_Delta_X,
		WRow_Delta_Y,
		WColumn_Delta_X,
		WColumn_Delta_Y,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ground_Control_Point_Description
 |
 | Lineage and applicability of ground control points.
 |
 |	Ground_Control_Point_Description =
 |		Control_Point_Type +
 |		(Control_Point_Origin) +
 |		(Control_Point_Use_Flag) +
 |		(Control_Point_Horizontal_X_Accuracy) +
 |		(Control_Point_Horizontal_Y_Accuracy) +
 |		(Control_Point_Vertical_Accuracy)
\*----------------------------------------------------------------------*/
static int check_Ground_Control_Point_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WControl_Point_Type,
		WControl_Point_Origin,
		WControl_Point_Use_Flag,
		WControl_Point_Horizontal_X_Accuracy,
		WControl_Point_Horizontal_Y_Accuracy,
		WControl_Point_Vertical_Accuracy,
		Wnull);
	err += require (p,
		WControl_Point_Type,
		Wnull);
	err += limit (p,1,
		WControl_Point_Type,
		WControl_Point_Origin,
		WControl_Point_Use_Flag,
		WControl_Point_Horizontal_X_Accuracy,
		WControl_Point_Horizontal_Y_Accuracy,
		WControl_Point_Vertical_Accuracy,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ground_Control_Point_Information
 |
 | Information describing data points for which both raster and geographic locations are available that can be used to relate raster and geographic coordinates at other points.
 |
 |	Ground_Control_Point_Information =
 |		Ground_Control_Point_Organization +
 |		[Ground_Control_Point_Description +
 |		1{Ground_Control_Point_Position}n |
 |		1{Ground_Control_Point_Description +
 |		Ground_Control_Point_Position}n]
 |
 |	NOTE: this is bad syntax, will break if order is not maintained. PNS
\*----------------------------------------------------------------------*/
static int check_Ground_Control_Point_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WGround_Control_Point_Organization,
		WGround_Control_Point_Description,
		WGround_Control_Point_Position,
		Wnull);
	err += require (p,
		WGround_Control_Point_Organization,
		WGround_Control_Point_Description,
		WGround_Control_Point_Position,
		Wnull);
	err += limit (p,1,
		WGround_Control_Point_Organization,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Ground_Control_Point_Position
 |
 | Location of individual control points, defined separately for every point, in both raster and geographic or map coordinate systems.
 |
 |	Ground_Control_Point_Position =
 |		Control_Point_Raster_Position +
 |		[Control_Point_Earth_Location |
 |		Control_Point_Identification]
\*----------------------------------------------------------------------*/
static int check_Ground_Control_Point_Position (struct item *p) {
	int err = 0;
	err += allow (p,
		WControl_Point_Raster_Position,
		WControl_Point_Earth_Location,
		WControl_Point_Identification,
		Wnull);
	err += require (p,
		WControl_Point_Raster_Position,
		Wnull);
	err += limit (p,1,
		WControl_Point_Raster_Position,
		WControl_Point_Earth_Location,
		WControl_Point_Identification,
		Wnull);
	/* Control_Point_Earth_Location is Conditional - present and mandatory if and only if value of Ground_Control_Point_Organization is "location" */
	/* Control_Point_Identification is Conditional - present and mandatory if and only if value of Ground_Control_Point_Organization is "library" */
	err += allow_one_of  (p,
		WControl_Point_Earth_Location,
		WControl_Point_Identification,
		Wnull);
	err += require_one_of  (p,
		WControl_Point_Earth_Location,
		WControl_Point_Identification,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | ID_Overlapping_Dataset
 |
 | Identifier for external frame imaging some areas in common.
 |
 |	ID_Overlapping_Dataset =
 |		Dataset_Identifier
\*----------------------------------------------------------------------*/
static int check_ID_Overlapping_Dataset (struct item *p) {
	int err = 0;
	err += allow (p,
		WDataset_Identifier,
		Wnull);
	err += require (p,
		WDataset_Identifier,
		Wnull);
	err += limit (p,1,
		WDataset_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Image_Size
 |
 | Metric length and width of the image.
 |
 |	Image_Size =
 |		Image_Size_x_Value +
 |		Image_Size_y_Value
\*----------------------------------------------------------------------*/
static int check_Image_Size (struct item *p) {
	int err = 0;
	err += allow (p,
		WImage_Size_x_Value,
		WImage_Size_y_Value,
		Wnull);
	err += require (p,
		WImage_Size_x_Value,
		WImage_Size_y_Value,
		Wnull);
	err += limit (p,1,
		WImage_Size_x_Value,
		WImage_Size_y_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Individual_Band_Identification
 |
 | Complete information to identify a single instrument band.
 |
 |	Individual_Band_Identification =
 |		Band_ID +
 |		Band_Measurement_Mode_ID
\*----------------------------------------------------------------------*/
static int check_Individual_Band_Identification (struct item *p) {
	int err = 0;
	err += allow (p,
		WBand_ID,
		WBand_Measurement_Mode_ID,
		Wnull);
	err += require (p,
		WBand_ID,
		WBand_Measurement_Mode_ID,
		Wnull);
	err += limit (p,1,
		WBand_ID,
		WBand_Measurement_Mode_ID,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Input_Dataset_Identifier
 |
 | Unique identifier for input dataset.
 |
 |	Input_Dataset_Identifier =
 |		Dataset_Identifier
\*----------------------------------------------------------------------*/
static int check_Input_Dataset_Identifier (struct item *p) {
	int err = 0;
	err += allow (p,
		WDataset_Identifier,
		Wnull);
	err += require (p,
		WDataset_Identifier,
		Wnull);
	err += limit (p,1,
		WDataset_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Input_Level
 |
 | Data distributor's code that identifies the degree of radiometric and geometric processing applied to the data defined in Processing_Input_Dataset.
 |
 |	Input_Level =
 |		Processing_Level
\*----------------------------------------------------------------------*/
static int check_Input_Level (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcessing_Level,
		Wnull);
	err += require (p,
		WProcessing_Level,
		Wnull);
	err += limit (p,1,
		WProcessing_Level,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Input_Reference
 |
 | Reference to document describing input to processing.
 |
 |	Input_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Input_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Instantaneous_Field_of_View
 |
 | Ground or target area viewed by a sensor at a given time.
 |
 |	Instantaneous_Field_of_View =
 |		IFOV_Units +
 |		IFOV_x_Definition +
 |		IFOV_x_Value +
 |		IFOV_y_Definition +
 |		IFOV_y_Value
\*----------------------------------------------------------------------*/
static int check_Instantaneous_Field_of_View (struct item *p) {
	int err = 0;
	err += allow (p,
		WIFOV_Units,
		WIFOV_x_Definition,
		WIFOV_x_Value,
		WIFOV_y_Definition,
		WIFOV_y_Value,
		Wnull);
	err += require (p,
		WIFOV_Units,
		WIFOV_x_Definition,
		WIFOV_x_Value,
		WIFOV_y_Definition,
		WIFOV_y_Value,
		Wnull);
	err += limit (p,1,
		WIFOV_Units,
		WIFOV_x_Definition,
		WIFOV_x_Value,
		WIFOV_y_Definition,
		WIFOV_y_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Instrument_Description
 |
 | Characteristics and behavior of instrument.
 |
 |	Instrument_Description =
 |		Instrument_Type +
 |		0{Operational_Mode}1 +
 |		Collection_Type +
 |		(Sensor_Orientation) +
 |		[Frame_Camera |
 |		Scan |
 |		Other_Collector_Description] +
 |		(Instrument_Properties_Description)
\*----------------------------------------------------------------------*/
static int check_Instrument_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WInstrument_Type,
		WOperational_Mode,
		WCollection_Type,
		WSensor_Orientation,
		WFrame_Camera,
		WScan,
		WOther_Collector_Description,
		WInstrument_Properties_Description,
		Wnull);
	err += require (p,
		WInstrument_Type,
		WCollection_Type,
		Wnull);
	err += limit (p,1,
		WInstrument_Type,
		WOperational_Mode,
		WCollection_Type,
		WSensor_Orientation,
		WFrame_Camera,
		WScan,
		WOther_Collector_Description,
		WInstrument_Properties_Description,
		Wnull);
	/* Frame_Camera is Conditional - present and mandatory if and only if Scan and Other_Collector_Description are absent */
	/* Scan is Conditional - present and mandatory if and only if Frame_Camera and Other_Collector_Description are absent */
	/* Other_Collector_Description is Conditional - present and mandatory if and only if Frame_Camera and Scan are absent */
	err += allow_one_of (p,
		WFrame_Camera,
		WScan,
		WOther_Collector_Description,
		Wnull);
	err += require_one_of (p,
		WFrame_Camera,
		WScan,
		WOther_Collector_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Instrument_Information
 |
 | Instrument properties and behavior.
 |
 |	Instrument_Information =
 |		[1{Instrument_Description}n |
 |		1{Instrument_Reference}n |
 |		1{Instrument_Description}n +
 |		1{Instrument_Reference}n]
\*----------------------------------------------------------------------*/
static int check_Instrument_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WInstrument_Description,
		WInstrument_Reference,
		Wnull);
	err += require (p,
		Wnull);
	err += limit (p,1,
		Wnull);
	/* Instrument_Description is Conditional - mandatory if no instances of Instrument_Reference present, otherwise optional */
	/* Instrument_Reference is Conditional - mandatory if no instances of Instrument_Description present, otherwise optional */
	err += require_one_of (p,
		WInstrument_Description,
		WInstrument_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Instrument_Reference
 |
 | Reference providing description of instrument properties and behavior.
 |
 |	Instrument_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Instrument_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Instrument_Specific_Georeferencing
 |
 | Information relating coordinate system of a particular instrument to ground coordinate system.
 |
 |	Instrument_Specific_Georeferencing =
 |		1{Positional_Information}n +
 |		(Exterior_Orientation_Accuracy) +
 |		Rotation_Sequence +
 |		Axis_Rotation_Convention
\*----------------------------------------------------------------------*/
static int check_Instrument_Specific_Georeferencing (struct item *p) {
	int err = 0;
	err += allow (p,
		WPositional_Information,
		WExterior_Orientation_Accuracy,
		WRotation_Sequence,
		WAxis_Rotation_Convention,
		Wnull);
	err += require (p,
		WPositional_Information,
		WRotation_Sequence,
		WAxis_Rotation_Convention,
		Wnull);
	err += limit (p,1,
		WExterior_Orientation_Accuracy,
		WRotation_Sequence,
		WAxis_Rotation_Convention,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Keplerian_Orbit
 |
 | Nominal Keplerian elements of platform orbit.
 |
 |	Keplerian_Orbit =
 |		[Semimajor_Axis |
 |		Orbit_Period |
 |		Semimajor_Axis +
 |		Orbit_Period] +
 |		Eccentricity +
 |		Orbit_Angle_Units +
 |		Inclination +
 |		Right_Ascension_of_Ascending_Node +
 |		Argument_of_Perigee +
 |		Perigee_Passage_Time
\*----------------------------------------------------------------------*/
static int check_Keplerian_Orbit (struct item *p) {
	int err = 0;
	err += allow (p,
		WSemimajor_Axis,
		WOrbit_Period,
		WEccentricity,
		WOrbit_Angle_Units,
		WInclination,
		WRight_Ascension_of_Ascending_Node,
		WArgument_of_Perigee,
		WPerigee_Passage_Time,
		Wnull);
	err += require (p,
		WEccentricity,
		WOrbit_Angle_Units,
		WInclination,
		WRight_Ascension_of_Ascending_Node,
		WArgument_of_Perigee,
		WPerigee_Passage_Time,
		Wnull);
	err += limit (p,1,
		WSemimajor_Axis,
		WOrbit_Period,
		WEccentricity,
		WOrbit_Angle_Units,
		WInclination,
		WRight_Ascension_of_Ascending_Node,
		WArgument_of_Perigee,
		WPerigee_Passage_Time,
		Wnull);
	/* Semimajor_Axis is Conditional - mandatory if Orbit_Period is absent; otherwise optional */
	/* Orbit_Period is Conditional - mandatory if Semimajor_Axis is absent; otherwise optional */
	err += require_one_of (p,
		WSemimajor_Axis,
		WOrbit_Period,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Last_Calibration
 |
 | Description of most recent camera calibration.
 |
 |	Last_Calibration =
 |		Date_of_Last_Calibration +
 |		(Method_of_Last_Calibration) +
 |		(Institution_of_Last_Calibration)
\*----------------------------------------------------------------------*/
static int check_Last_Calibration (struct item *p) {
	int err = 0;
	err += allow (p,
		WDate_of_Last_Calibration,
		WMethod_of_Last_Calibration,
		WInstitution_of_Last_Calibration,
		Wnull);
	err += require (p,
		WDate_of_Last_Calibration,
		Wnull);
	err += limit (p,1,
		WDate_of_Last_Calibration,
		WMethod_of_Last_Calibration,
		WInstitution_of_Last_Calibration,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Layer_Name
 |
 | Description of one kind of geospatial information represented by the dataset.
 |
 |	Layer_Name =
 |		Theme
\*----------------------------------------------------------------------*/
static int check_Layer_Name (struct item *p) {
	int err = 0;
	err += allow (p,
		WTheme,
		Wnull);
	err += require (p,
		WTheme,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WTheme,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Lens
 |
 | Optical component that uses refraction to focus light on the image plane.
 |
 |	Lens =
 |		Lens_Type +
 |		Lens_Identifier
\*----------------------------------------------------------------------*/
static int check_Lens (struct item *p) {
	int err = 0;
	err += allow (p,
		WLens_Type,
		WLens_Identifier,
		Wnull);
	err += require (p,
		WLens_Type,
		WLens_Identifier,
		Wnull);
	err += limit (p,1,
		WLens_Type,
		WLens_Identifier,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Location_Information
 |
 | Information about the location of a set of one or more points.  (Note:  this section provides a means of describing position in a coordinate system relevant to the calling element and is used by other sections of the metadata extensions.  This section is never used alone.  It differs from the Spatial Reference Information in that it provides positions in a coordinate system relevant to metadata elements, whereas the Spatial Reference Information refers only to positions at which the data are located.)
 |
 |	Location_Information =
 |		Number_of_Points +
 |		0{Coordinate_System}1 +
 |		0{Coordinate_XY_Units}1 +
 |		(Coordinate_Z_Units) +
 |		1{Coordinate_Point}n
\*----------------------------------------------------------------------*/
static int check_Location_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Points,
		WCoordinate_System,
		WCoordinate_XY_Units,
		WCoordinate_Z_Units,
		WCoordinate_Point,
		Wnull);
	err += require (p,
		WNumber_of_Points,
		WCoordinate_Point,
		Wnull);
	err += limit (p,1,
		WNumber_of_Points,
		WCoordinate_System,
		WCoordinate_XY_Units,
		WCoordinate_Z_Units,
		Wnull);
	/* Coordinate_System is Conditional -  present and mandatory if and only if not defined in referencing element */
	/* Coordinate_XY_Units is Conditional - present and mandatory if and only if  the coordinates correspond to physical dimensions and are not specified elsewhere. */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Mission_Completion
 |
 | Scheduled or actual end date of mission during which data were taken.
 |
 |	Mission_Completion =
 |		Single_Date/Time
\*----------------------------------------------------------------------*/
static int check_Mission_Completion (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		Wnull);
	err += require (p,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Mission_History
 |
 | Significant events and dates over the history of the mission.
 |
 |	Mission_History =
 |		Mission_Start_Date +
 |		(1{Mission_Significant_Event}n) +
 |		0{Mission_Completion}1
\*----------------------------------------------------------------------*/
static int check_Mission_History (struct item *p) {
	int err = 0;
	err += allow (p,
		WMission_Start_Date,
		WMission_Significant_Event,
		WMission_Completion,
		Wnull);
	err += require (p,
		WMission_Start_Date,
		Wnull);
	err += limit (p,1,
		WMission_Start_Date,
		WMission_Completion,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Mission_Information
 |
 | General information about the overall data gathering program to which the data contribute.
 |
 |	Mission_Information =
 |		(Mission_Description) +
 |		(Mission_History)
\*----------------------------------------------------------------------*/
static int check_Mission_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WMission_Description,
		WMission_History,
		Wnull);
	err += limit (p,1,
		WMission_Description,
		WMission_History,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Mission_Significant_Event
 |
 | Date and description of a major occurrence during mission.
 |
 |	Mission_Significant_Event =
 |		Process_Step
\*----------------------------------------------------------------------*/
static int check_Mission_Significant_Event (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcess_Step,
		Wnull);
	err += require (p,
		WProcess_Step,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WProcess_Step,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Mission_Start_Date
 |
 | Date that mission during which data were taken began.
 |
 |	Mission_Start_Date =
 |		Single_Date/Time
\*----------------------------------------------------------------------*/
static int check_Mission_Start_Date (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		Wnull);
	err += require (p,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Multiple_Image_Alignment
 |
 | Positioning of other frame imaging some areas in common.
 |
 |	Multiple_Image_Alignment =
 |		ID_Overlapping_Dataset +
 |		Type_of_Overlap +
 |		Percentage_of_Overlap
\*----------------------------------------------------------------------*/
static int check_Multiple_Image_Alignment (struct item *p) {
	int err = 0;
	err += allow (p,
		WID_Overlapping_Dataset,
		WType_of_Overlap,
		WPercentage_of_Overlap,
		Wnull);
	err += require (p,
		WID_Overlapping_Dataset,
		WType_of_Overlap,
		WPercentage_of_Overlap,
		Wnull);
	err += limit (p,1,
		WID_Overlapping_Dataset,
		WType_of_Overlap,
		WPercentage_of_Overlap,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Nadir
 |
 | Location of point directly underneath platform.
 |
 |	Nadir =
 |		Nadir_Latitude +
 |		Nadir_Longitude
\*----------------------------------------------------------------------*/
static int check_Nadir (struct item *p) {
	int err = 0;
	err += allow (p,
		WNadir_Latitude,
		WNadir_Longitude,
		Wnull);
	err += require (p,
		WNadir_Latitude,
		WNadir_Longitude,
		Wnull);
	err += limit (p,1,
		WNadir_Latitude,
		WNadir_Longitude,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Nominal_Geostationary_Position
 |
 | Nominal location of platform designed to remain stationary over one point on earth.
 |
 |	Nominal_Geostationary_Position =
 |		Platform_Nominal_Longitude +
 |		Platform_Nominal_Altitude
\*----------------------------------------------------------------------*/
static int check_Nominal_Geostationary_Position (struct item *p) {
	int err = 0;
	err += allow (p,
		WPlatform_Nominal_Longitude,
		WPlatform_Nominal_Altitude,
		Wnull);
	err += require (p,
		WPlatform_Nominal_Longitude,
		WPlatform_Nominal_Altitude,
		Wnull);
	err += limit (p,1,
		WPlatform_Nominal_Longitude,
		WPlatform_Nominal_Altitude,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Nominal_Spatial_Resolution
 |
 | Smallest distance between which separate points can be distinguished, as specified in instrument design.
 |
 |	Nominal_Spatial_Resolution =
 |		Spatial_Resolution_Units +
 |		Spatial_Resolution_Value
\*----------------------------------------------------------------------*/
static int check_Nominal_Spatial_Resolution (struct item *p) {
	int err = 0;
	err += allow (p,
		WSpatial_Resolution_Units,
		WSpatial_Resolution_Value,
		Wnull);
	err += require (p,
		WSpatial_Resolution_Units,
		WSpatial_Resolution_Value,
		Wnull);
	err += limit (p,1,
		WSpatial_Resolution_Units,
		WSpatial_Resolution_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Number_of_Wavelength_Bands
 |
 | Number of separate wavelength ranges at which system measures.
 |
 |	Number_of_Wavelength_Bands =
 |		Number_of_Bands
\*----------------------------------------------------------------------*/
static int check_Number_of_Wavelength_Bands (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Bands,
		Wnull);
	err += require (p,
		WNumber_of_Bands,
		Wnull);
	err += limit (p,1,
		WNumber_of_Bands,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Orbit_Period
 |
 | Time from one perigee to the next.  (Note: The orbit period is related to the semimajor axis of the orbit by P2=42a3/[G(M+m)], where P is the orbit period, a is the semimajor axis, G the universal gravitational constant, M the mass of the Earth, and m the mass of the satellite. In practice, because the product GM is easier to obtain than G or M, and because m<<M, the form P2=42a3/GM is often used.)
 |
 |	Orbit_Period =
 |		Orbit_Period_Units +
 |		Orbit_Period_Value
\*----------------------------------------------------------------------*/
static int check_Orbit_Period (struct item *p) {
	int err = 0;
	err += allow (p,
		WOrbit_Period_Units,
		WOrbit_Period_Value,
		Wnull);
	err += require (p,
		WOrbit_Period_Units,
		WOrbit_Period_Value,
		Wnull);
	err += limit (p,1,
		WOrbit_Period_Units,
		WOrbit_Period_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Perigee_Passage_Time
 |
 | One date and time where platform was at closest point to earth in its orbit.
 |
 |	Perigee_Passage_Time =
 |		Single_Date/Time
\*----------------------------------------------------------------------*/
static int check_Perigee_Passage_Time (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		Wnull);
	err += require (p,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Photographic_Resolving_Power
 |
 | Resolving power of the camera at different field angles.
 |
 |	Photographic_Resolving_Power =
 |		Number_of_Resolution_Values +
 |		1{Resolution_Value_Set}n +
 |		(Area_Weighted_Average_Resolution)
\*----------------------------------------------------------------------*/
static int check_Photographic_Resolving_Power (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Resolution_Values,
		WResolution_Value_Set,
		WArea_Weighted_Average_Resolution,
		Wnull);
	err += require (p,
		WNumber_of_Resolution_Values,
		WResolution_Value_Set,
		Wnull);
	err += limit (p,1,
		WNumber_of_Resolution_Values,
		WArea_Weighted_Average_Resolution,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Pixel_Description
 |
 | Description of angular dimensions and location of scanner picture cell.
 |
 |	Pixel_Description =
 |		0{Pixel_Cross_Track_Size}1 +
 |		0{Pixel_Elevation_Size}1 +
 |		0{Pixel_Profile_Size}1 +
 |		(Pixel_Height_Above_Ellipsoid) +
 |		(Pixel_Point_Spread_Function)
\*----------------------------------------------------------------------*/
static int check_Pixel_Description (struct item *p) {
	int err = 0;
	err += allow (p,
		WPixel_Cross_Track_Size,
		WPixel_Elevation_Size,
		WPixel_Profile_Size,
		WPixel_Height_Above_Ellipsoid,
		WPixel_Point_Spread_Function,
		Wnull);
	err += require (p,
		Wnull);
	err += limit (p,1,
		WPixel_Cross_Track_Size,
		WPixel_Elevation_Size,
		WPixel_Profile_Size,
		WPixel_Height_Above_Ellipsoid,
		WPixel_Point_Spread_Function,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Pixel_Resolution
 |
 | Geographic dimensions corresponding to one raster pixel of processed data.
 |
 |	Pixel_Resolution =
 |		Coordinate_Representation
 |		Planar_Distance_Units
\*----------------------------------------------------------------------*/
static int check_Pixel_Resolution (struct item *p) {
	int err = 0;
	err += allow (p,
		WCoordinate_Representation,
		WPlanar_Distance_Units,
		Wnull);
	err += require (p,
		WCoordinate_Representation,		/* Assumed */
		WPlanar_Distance_Units,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCoordinate_Representation,		/* Assumed */
		WPlanar_Distance_Units,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Platform_and_Instrument_Identification
 |
 | Designations for the measuring instruments and their bands, the platform carrying them, and the mission to which the data contribute.
 |
 |	Platform_and_Instrument_Identification =
 |		(Mission_Name) +
 |		Platform_Full_Name +
 |		(Platform_Short_Name) +
 |		(Platform_Serial_Identifier) +
 |		Instrument_Full_Name +
 |		0{Instrument_Short_Name}1
\*----------------------------------------------------------------------*/
static int check_Platform_and_Instrument_Identification (struct item *p) {
	int err = 0;
	err += allow (p,
		WMission_Name,
		WPlatform_Full_Name,
		WPlatform_Short_Name,
		WPlatform_Serial_Identifier,
		WInstrument_Full_Name,
		WInstrument_Short_Name,
		Wnull);
	err += require (p,
		WPlatform_Full_Name,
		WInstrument_Full_Name,
		Wnull);
	err += limit (p,1,
		WMission_Name,
		WPlatform_Full_Name,
		WPlatform_Short_Name,
		WPlatform_Serial_Identifier,
		WInstrument_Full_Name,
		WInstrument_Short_Name,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Platform_and_Mission_Information
 |
 | Descriptive information about the platform from which the measurements that produced the data and about the program of which the data collection was a part.
 |
 |	Platform_and_Mission_Information =
 |		(Mission_Information) +
 |		(1{Platform_Information}n)
\*----------------------------------------------------------------------*/
static int check_Platform_and_Mission_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WMission_Information,
		WPlatform_Information,
		Wnull);
	err += require (p,
		Wnull);
	err += limit (p,1,
		WMission_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Platform_Information
 |
 | General information about the platform from which the data were taken.
 |
 |	Platform_Information =
 |		Platform_Start_Date +
 |		(1{Platform_Sponsor}n) +
 |		(Platform_Description)
 |		(Platform_Orbit) +
 |		(Flight_Protocol)
\*----------------------------------------------------------------------*/
static int check_Platform_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WPlatform_Start_Date,
		WPlatform_Sponsor,
		WPlatform_Description,
		WPlatform_Orbit,
		WFlight_Protocol,
		Wnull);
	err += require (p,
		WPlatform_Start_Date,
		Wnull);
	err += limit (p,1,
		WPlatform_Start_Date,
		WPlatform_Description,
		WPlatform_Orbit,
		WFlight_Protocol,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Platform_Nominal_Altitude
 |
 | Nominal altitude of geostationary satellite above the surface given by Altitude_Datum_Name defined in base standard.
 |
 |	Platform_Nominal_Altitude =
 |		Platform_Nominal_Altitude_Units +
 |		Platform_Nominal_Altitude_Value
\*----------------------------------------------------------------------*/
static int check_Platform_Nominal_Altitude (struct item *p) {
	int err = 0;
	err += allow (p,
		WPlatform_Nominal_Altitude_Units,
		WPlatform_Nominal_Altitude_Value,
		Wnull);
	err += require (p,
		WPlatform_Nominal_Altitude_Units,
		WPlatform_Nominal_Altitude_Value,
		Wnull);
	err += limit (p,1,
		WPlatform_Nominal_Altitude_Units,
		WPlatform_Nominal_Altitude_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Platform_Nominal_Altitude_Units
 |
 | Units of measure in which nominal altitude for platform is expressed.
 |
 |	Platform_Nominal_Altitude_Units =
 |		Altitude_Distance_Units
\*----------------------------------------------------------------------*/
static int check_Platform_Nominal_Altitude_Units (struct item *p) {
	int err = 0;
	err += allow (p,
		WAltitude_Distance_Units,
		Wnull);
	err += require (p,
		WAltitude_Distance_Units,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WAltitude_Distance_Units,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Platform_Orbit
 |
 | Orbital parameters of instrument platform.
 |
 |	Platform_Orbit =
 |		Ephemeris +
 |		[Keplerian_Orbit |
 |		Nominal_Geostationary_Position]
\*----------------------------------------------------------------------*/
static int check_Platform_Orbit (struct item *p) {
	int err = 0;
	err += allow (p,
		WEphemeris,
		WKeplerian_Orbit,
		WNominal_Geostationary_Position,
		Wnull);
	err += require (p,
		WEphemeris,
		Wnull);
	err += limit (p,1,
		WEphemeris,
		WKeplerian_Orbit,
		WNominal_Geostationary_Position,
		Wnull);
	/* Keplerian_Orbit is Conditional - present and mandatory only if Nominal_Geostationary_Position is absent */
	/* Nominal_Geostationary_Position is Conditional - present and mandatory only if Keplerian_Orbit is absent */
	err += allow_one_of (p,
		WKeplerian_Orbit,
		WNominal_Geostationary_Position,
		Wnull);
	err += require_one_of (p,
		WKeplerian_Orbit,
		WNominal_Geostationary_Position,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Platform_Start_Date
 |
 | Start date of platform operation.
 |
 |	Platform_Start_Date =
 |		Single_Date/Time
\*----------------------------------------------------------------------*/
static int check_Platform_Start_Date (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		Wnull);
	err += require (p,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Polarization_Characteristics
 |
 | Degree of polarization of band.
 |
 |	Polarization_Characteristics =
 |		Receiver_Polarization +
 |		0{Sender_Polarization}1
\*----------------------------------------------------------------------*/
static int check_Polarization_Characteristics (struct item *p) {
	int err = 0;
	err += allow (p,
		WReceiver_Polarization,
		WSender_Polarization,
		Wnull);
	err += require (p,
		WReceiver_Polarization,
		Wnull);
	err += limit (p,1,
		WReceiver_Polarization,
		WSender_Polarization,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Polynomial_Denominator
 |
 | The divisor of a polynomial function that is a ratio. (Note: If absent, assumed equal to 1.)
 |
 |	Polynomial_Denominator =
 |		Number_of_Denominator_Terms +
 |		1{Polynomial_Coefficient}n
\*----------------------------------------------------------------------*/
static int check_Polynomial_Denominator (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Denominator_Terms,
		WPolynomial_Coefficient,
		Wnull);
	err += require (p,
		WNumber_of_Denominator_Terms,
		WPolynomial_Coefficient,
		Wnull);
	err += limit (p,1,
		WNumber_of_Denominator_Terms,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Polynomial_Function
 |
 | A function in successive powers of the independent variable, or the ratio of such functions, used in a transformation, one example of which is scaling, derivation of a set of values on one scale or coordinate system from the value in another, in the sense derived value = polynomial (initial value).
 |
 |	Polynomial_Function =
 |		Polynomial_Numerator +
 |		0{Polynomial_Denominator}1
\*----------------------------------------------------------------------*/
static int check_Polynomial_Function (struct item *p) {
	int err = 0;
	err += allow (p,
		WPolynomial_Numerator,
		WPolynomial_Denominator,
		Wnull);
	err += require (p,
		WPolynomial_Numerator,
		Wnull);
	err += limit (p,1,
		WPolynomial_Numerator,
		WPolynomial_Denominator,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Polynomial_Numerator
 |
 | The polynomial function when not a ratio, and the dividend of the ratio when it is.
 |
 |	Polynomial_Numerator =
 |		Number_of_Numerator_Terms +
 |		1{Polynomial_Coefficient}n
\*----------------------------------------------------------------------*/
static int check_Polynomial_Numerator (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Numerator_Terms,
		WPolynomial_Coefficient,
		Wnull);
	err += require (p,
		WNumber_of_Numerator_Terms,
		WPolynomial_Coefficient,
		Wnull);
	err += limit (p,1,
		WNumber_of_Numerator_Terms,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Positional_Information
 |
 | Orientation of instrument and detector projection.
 |
 |	Positional_Information =
 |		Projection_Center_X_Position +
 |		Projection_Center_Y_Position +
 |		Projection_Center_Z_Position +
 |		Roll +
 |		Pitch +
 |		Yaw +
 |		Attitude_Angular_Units
\*----------------------------------------------------------------------*/
static int check_Positional_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WProjection_Center_X_Position,
		WProjection_Center_Y_Position,
		WProjection_Center_Z_Position,
		WRoll,
		WPitch,
		WYaw,
		WAttitude_Angular_Units,
		Wnull);
	err += require (p,
		WProjection_Center_X_Position,
		WProjection_Center_Y_Position,
		WProjection_Center_Z_Position,
		WRoll,
		WPitch,
		WYaw,
		WAttitude_Angular_Units,
		Wnull);
	err += limit (p,1,
		WProjection_Center_X_Position,
		WProjection_Center_Y_Position,
		WProjection_Center_Z_Position,
		WRoll,
		WPitch,
		WYaw,
		WAttitude_Angular_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Principal_Point_of_Autocollimation
 |
 | The point (x0, y0) where the plumb line coming from the projection center crosses the image plane, given in millimeters in the image coordinate system, determined by projecting an illuminated object to infinity, reflecting its image from a flat mirror surface, and adjusting the instrument until both the object and image are in focus at the same plane.
 |
 |	Principal_Point_of_Autocollimation =
 |		Location_Information
\*----------------------------------------------------------------------*/
static int check_Principal_Point_of_Autocollimation (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocation_Information,
		Wnull);
	err += require (p,
		WLocation_Information,
		Wnull);
	err += limit (p,1,
		WLocation_Information,
		Wnull);
	/* Location_Information is Specified by referencing element. */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Principal_Point_of_Symmetry
 |
 | The coordinate of the center of the circles of equal distortion of the lens (xs,ys) in millimeters in the image coordinate system.
 |
 |	Principal_Point_of_Symmetry =
 |		Location_Information
\*----------------------------------------------------------------------*/
static int check_Principal_Point_of_Symmetry (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocation_Information,
		Wnull);
	err += require (p,
		WLocation_Information,
		Wnull);
	err += limit (p,1,
		WLocation_Information,
		Wnull);
	/* Location_Information is Specified by referencing element. */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Change_History
 |
 | Description of the changes in processing procedure from version to version.
 |
 |	Processing_Change_History =
 |		1{Process_Step}n
\*----------------------------------------------------------------------*/
static int check_Processing_Change_History (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcess_Step,
		Wnull);
	err += require (p,
		WProcess_Step,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WProcess_Step,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Documentation
 |
 | Reference to documentation describing the processing.
 |
 |	Processing_Documentation =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Processing_Documentation (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Environment
 |
 | The environment in which the processing was carried out, including, but not limited to, the platform, the operating system name and version, and other configuration control information.
 |
 |	Processing_Environment =
 |		Native_Data_Set_Environment
\*----------------------------------------------------------------------*/
static int check_Processing_Environment (struct item *p) {
	int err = 0;
	err += allow (p,
		WNative_Data_Set_Environment,
		Wnull);
	err += require (p,
		WNative_Data_Set_Environment,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WNative_Data_Set_Environment,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Identifiers
 |
 | Information to identify processing package that produced the data.
 |
 |	Processing_Identifiers =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Processing_Identifiers (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Information
 |
 | Comprehensive information about the procedure by which the algorithm was applied to derive geographic data from the raw instrument measurements, such as datasets, software used, and the processing environment.
 |
 |	Processing_Information =
 |		Processing_Identifiers +
 |		1{Processing_Input_Dataset}n +
 |		(1{Ancillary_Dataset}n) +
 |		Processing_Software +
 |		Processing_Procedure +
 |		0{Processing_Change_History}1 +
 |		(1{Processing_Documentation}n)
\*----------------------------------------------------------------------*/
static int check_Processing_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcessing_Identifiers,
		WProcessing_Input_Dataset,
		WAncillary_Dataset,
		WProcessing_Software,
		WProcessing_Procedure,
		WProcessing_Change_History,
		WProcessing_Documentation,
		Wnull);
	err += require (p,
		WProcessing_Identifiers,
		WProcessing_Input_Dataset,
		WAncillary_Dataset,
		WProcessing_Software,
		WProcessing_Procedure,
		Wnull);
	err += limit (p,1,
		WProcessing_Identifiers,
		WProcessing_Software,
		WProcessing_Procedure,
		WProcessing_Change_History,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Input_Dataset
 |
 | The data used as input to single or multistage processing used to derive product.
 |
 |	Processing_Input_Dataset =
 |		Input_Dataset_Identifier +
 |		[Input_Description |
 |		Input_Reference] +
 |		0{Input_Level}1
\*----------------------------------------------------------------------*/
static int check_Processing_Input_Dataset (struct item *p) {
	int err = 0;
	err += allow (p,
		WInput_Dataset_Identifier,
		WInput_Description,
		WInput_Reference,
		WInput_Level,
		Wnull);
	err += require (p,
		WInput_Dataset_Identifier,
		Wnull);
	err += limit (p,1,
		WInput_Dataset_Identifier,
		WInput_Description,
		WInput_Reference,
		WInput_Level,
		Wnull);
	/* Input_Description is Conditional - present and mandatory if and only if Input_Reference is absent */
	/* Input_Reference is Conditional - present and mandatory if and only if Input_Description is absent */
	err += allow_one_of (p,
		WInput_Description,
		WInput_Reference,
		Wnull);
	err += require_one_of (p,
		WInput_Description,
		WInput_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Level
 |
 | Degree of data processing applied to the measurements, as exemplified in Appendixes AC.
 |
 |	Processing_Level =
 |		Processing_Level_Identifier +
 |		Processing_Level_Authority
\*----------------------------------------------------------------------*/
static int check_Processing_Level (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcessing_Level_Identifier,
		WProcessing_Level_Authority,
		Wnull);
	err += require (p,
		WProcessing_Level_Identifier,
		WProcessing_Level_Authority,
		Wnull);
	err += limit (p,1,
		WProcessing_Level_Identifier,
		WProcessing_Level_Authority,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Level_Authority
 |
 | Reference for the definition of the product level designations used.
 |
 |	Processing_Level_Authority =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Processing_Level_Authority (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Procedure
 |
 | Description of decision parameters in and circumstances and methods of processing.
 |
 |	Processing_Procedure =
 |		Processing_Run_History +
 |		Processing_Environment +
 |		(Processing_Procedure_Description)
\*----------------------------------------------------------------------*/
static int check_Processing_Procedure (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcessing_Run_History,
		WProcessing_Environment,
		WProcessing_Procedure_Description,
		Wnull);
	err += require (p,
		WProcessing_Run_History,
		WProcessing_Environment,
		Wnull);
	err += limit (p,1,
		WProcessing_Run_History,
		WProcessing_Environment,
		WProcessing_Procedure_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Run_History
 |
 | History of processing runs that create data set described by metadata.
 |
 |	Processing_Run_History =
 |		1{Process_Step}n
\*----------------------------------------------------------------------*/
static int check_Processing_Run_History (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcess_Step,
		Wnull);
	err += require (p,
		WProcess_Step,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WProcess_Step,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Software
 |
 | The computer programs used to process data from one level to another.
 |
 |	Processing_Software =
 |		[Processing_Software_Description |
 |		Processing_Software_Reference]
\*----------------------------------------------------------------------*/
static int check_Processing_Software (struct item *p) {
	int err = 0;
	err += allow (p,
		WProcessing_Software_Description,
		WProcessing_Software_Reference,
		Wnull);
	err += require (p,
		Wnull);
	err += limit (p,1,
		WProcessing_Software_Description,
		WProcessing_Software_Reference,
		Wnull);
	/* Processing_Software_Description is Conditional - present and mandatory if and only if Processing_Software_Reference is absent */
	/* Processing_Software_Reference is Conditional - present and mandatory if and only if Processing_Software_Description is absent */
	err += allow_one_of (p,
		WProcessing_Software_Description,
		WProcessing_Software_Reference,
		Wnull);
	err += require_one_of (p,
		WProcessing_Software_Description,
		WProcessing_Software_Reference,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Processing_Software_Reference
 |
 | Reference to document describing processing software.
 |
 |	Processing_Software_Reference =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Processing_Software_Reference (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Profile_Properties
 |
 | Description of data sampling in vertical direction.
 |
 |	Profile_Properties =
 |		[Profile_Sounding |
 |		Profile_Fixed] +
 |		(Profile_Description)
\*----------------------------------------------------------------------*/
static int check_Profile_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WProfile_Sounding,
		WProfile_Fixed,
		WProfile_Description,
		Wnull);
	err += limit (p,1,
		WProfile_Sounding,
		WProfile_Fixed,
		WProfile_Description,
		Wnull);
	/* Profile_Sounding is Conditional - present and mandatory if and only if Profile_Fixed is absent */
	/* Profile_Fixed is Conditional - present and mandatory if and only if Profile_Sounding is absent */
	err += allow_one_of (p,
		WProfile_Sounding,
		WProfile_Fixed,
		Wnull);
	err += require_one_of (p,
		WProfile_Sounding,
		WProfile_Fixed,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Profile_Sounding
 |
 | Description of process of profile sampling.
 |
 |	Profile_Sounding =
 |		Number_of_Profile_Samples +
 |		Profiling_Direction +
 |		Profile_Start +
 |		[Profile_Extent |
 |		Profile_Step]
\*----------------------------------------------------------------------*/
static int check_Profile_Sounding (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Profile_Samples,
		WProfiling_Direction,
		WProfile_Start,
		WProfile_Extent,
		WProfile_Step,
		Wnull);
	err += require (p,
		WNumber_of_Profile_Samples,
		WProfiling_Direction,
		WProfile_Start,
		Wnull);
	err += limit (p,1,
		WNumber_of_Profile_Samples,
		WProfiling_Direction,
		WProfile_Start,
		WProfile_Extent,
		WProfile_Step,
		Wnull);
	/* Profile_Extent is Conditional - present and mandatory if and only if Profile_Step is absent */
	/* Profile_Step is Conditional - present and mandatory if and only if Profile_Extent is absent */
	err += allow_one_of (p,
		WProfile_Extent,
		WProfile_Step,
		Wnull);
	err += require_one_of (p,
		WProfile_Extent,
		WProfile_Step,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Quality_of_Principal_Point_of_Autocollimation
 |
 | Uncertainty in the location of the principal point of autocollimation.
 |
 |	Quality_of_Principal_Point_of_Autocollimation =
 |		Quality_of_Autocollimation_Principal_Point_x_Value +
 |		Quality_of_Autocollimation_Principal_Point_y_Value
\*----------------------------------------------------------------------*/
static int check_Quality_of_Principal_Point_of_Autocollimation (struct item *p) {
	int err = 0;
	err += allow (p,
		WQuality_of_Autocollimation_Principal_Point_x_Value,
		WQuality_of_Autocollimation_Principal_Point_y_Value,
		Wnull);
	err += require (p,
		WQuality_of_Autocollimation_Principal_Point_x_Value,
		WQuality_of_Autocollimation_Principal_Point_y_Value,
		Wnull);
	err += limit (p,1,
		WQuality_of_Autocollimation_Principal_Point_x_Value,
		WQuality_of_Autocollimation_Principal_Point_y_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Quality_of_Principal_Point_of_Symmetry
 |
 | Uncertainty in the location of the principal point of symmetry.
 |
 |	Quality_of_Principal_Point_of_Symmetry =
 |		Quality_of_Symmetry_Principal_Point_x_Value +
 |		Quality_of_Symmetry_Principal_Point_y_Value
\*----------------------------------------------------------------------*/
static int check_Quality_of_Principal_Point_of_Symmetry (struct item *p) {
	int err = 0;
	err += allow (p,
		WQuality_of_Symmetry_Principal_Point_x_Value,
		WQuality_of_Symmetry_Principal_Point_y_Value,
		Wnull);
	err += require (p,
		WQuality_of_Symmetry_Principal_Point_x_Value,
		WQuality_of_Symmetry_Principal_Point_y_Value,
		Wnull);
	err += limit (p,1,
		WQuality_of_Symmetry_Principal_Point_x_Value,
		WQuality_of_Symmetry_Principal_Point_y_Value,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Radial_Symmetrical_Distortion_Polynomial
 |
 | Lens distortion in micrometers that is a function of the distance to the principal point of best symmetry,  presented in the form of an odd-power polynomial: r = K0 * r  +  K1 * r3  +  K2 * r5  +  K3 * r7 . . .
 |
 |	Radial_Symmetrical_Distortion_Polynomial =
 |		Polynomial_Function
\*----------------------------------------------------------------------*/
static int check_Radial_Symmetrical_Distortion_Polynomial (struct item *p) {
	int err = 0;
	err += allow (p,
		WPolynomial_Function,
		Wnull);
	err += require (p,
		WPolynomial_Function,
		Wnull);
	err += limit (p,1,
		WPolynomial_Function,
		Wnull);
	/* Polynomial_Function is Conditional - present and mandatory if and only if Non_Polynomial_Scaling is absent */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Referenced_Coordinate_System
 |
 | Coordinate system that can be georeferenced..
 |
 |	Referenced_Coordinate_System =
 |		Spatial_Reference_Information
\*----------------------------------------------------------------------*/
static int check_Referenced_Coordinate_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WSpatial_Reference_Information,
		Wnull);
	err += require (p,
		WSpatial_Reference_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WSpatial_Reference_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Referencing_Polynomial
 |
 | Polynomial function used to relate image and ground positions.
 |
 |	Referencing_Polynomial =
 |		Polynomial_Function
\*----------------------------------------------------------------------*/
static int check_Referencing_Polynomial (struct item *p) {
	int err = 0;
	err += allow (p,
		WPolynomial_Function,
		Wnull);
	err += require (p,
		WPolynomial_Function,
		Wnull);
	err += limit (p,1,
		WPolynomial_Function,
		Wnull);
	/* Polynomial_Function is Conditional - present and mandatory if and only if Non_Polynomial_Scaling is absent */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Reseau
 |
 | Calibrated positions of engraved rseau-crosses that are pressed against the film during exposure, given in millimeters in the image coordinate system.
 |
 |	Reseau =
 |		Location_Information
\*----------------------------------------------------------------------*/
static int check_Reseau (struct item *p) {
	int err = 0;
	err += allow (p,
		WLocation_Information,
		Wnull);
	err += require (p,
		WLocation_Information,
		Wnull);
	err += limit (p,1,
		WLocation_Information,
		Wnull);
	/* Location_Information is Specified by referencing element. */
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Resolution_Value_Set
 |
 | Resolving power of the camera at different field angles.
 |
 |	Resolution_Value_Set =
 |		Resolving_Angle +
 |		Resolving_Value_Radial +
 |		Resolving_Value_Tangential
\*----------------------------------------------------------------------*/
static int check_Resolution_Value_Set (struct item *p) {
	int err = 0;
	err += allow (p,
		WResolving_Angle,
		WResolving_Value_Radial,
		WResolving_Value_Tangential,
		Wnull);
	err += require (p,
		WResolving_Angle,
		WResolving_Value_Radial,
		WResolving_Value_Tangential,
		Wnull);
	err += limit (p,1,
		WResolving_Angle,
		WResolving_Value_Radial,
		WResolving_Value_Tangential,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Sample_Description_Units
 |
 | Units in which pixel properties are provided.
 |
 |	Sample_Description_Units =
 |		0{Sample_Angle_Units}1 +
 |		0{Sample_Profile_Units}1
\*----------------------------------------------------------------------*/
static int check_Sample_Description_Units (struct item *p) {
	int err = 0;
	err += allow (p,
		WSample_Angle_Units,
		WSample_Profile_Units,
		Wnull);
	err += limit (p,1,
		WSample_Angle_Units,
		WSample_Profile_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Sample_Profile_Units
 |
 | Units used to measure profile heights and distances.
 |
 |	Sample_Profile_Units =
 |		Altitude_Distance_Units
\*----------------------------------------------------------------------*/
static int check_Sample_Profile_Units (struct item *p) {
	int err = 0;
	err += allow (p,
		WAltitude_Distance_Units,
		Wnull);
	err += require (p,
		WAltitude_Distance_Units,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WAltitude_Distance_Units,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Sample_Properties
 |
 | Description of sensor pixel properties.
 |
 |	Sample_Properties =
 |		Sample_Description_Units +
 |		1{Pixel_Description}n
\*----------------------------------------------------------------------*/
static int check_Sample_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WSample_Description_Units,
		WPixel_Description,
		Wnull);
	err += require (p,
		WSample_Description_Units,
		WPixel_Description,
		Wnull);
	err += limit (p,1,
		WSample_Description_Units,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan
 |
 | Properties of sensor whose detector view moves over the ground in a direction roughly perpendicular to the track of a moving point.
 |
 |	Scan =
 |		1{Scan_Geometric_Properties}n +
 |		Sample_Properties +
 |		Scan_Radiometric_Properties +
 |		0{Scan_Spectral_Properties}1
\*----------------------------------------------------------------------*/
static int check_Scan (struct item *p) {
	int err = 0;
	err += allow (p,
		WScan_Geometric_Properties,
		WSample_Properties,
		WScan_Radiometric_Properties,
		WScan_Spectral_Properties,
		Wnull);
	err += require (p,
		WScan_Geometric_Properties,
		WSample_Properties,
		WScan_Radiometric_Properties,
		Wnull);
	err += limit (p,1,
		WSample_Properties,
		WScan_Radiometric_Properties,
		WScan_Spectral_Properties,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan_Cross_Track_Properties
 |
 | Description of data sampling in direction approximately perpendicular to track in horizontal direction.
 |
 |	Scan_Cross_Track_Properties =
 |		Cross_Track_Zero +
 |		[Cross_Track_Sweep |
 |		Cross_Track_Fixed_Angle] +
 |		(Cross_Track_Description)
\*----------------------------------------------------------------------*/
static int check_Scan_Cross_Track_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WCross_Track_Zero,
		WCross_Track_Sweep,
		WCross_Track_Fixed_Angle,
		WCross_Track_Description,
		Wnull);
	err += require (p,
		WCross_Track_Zero,
		Wnull);
	err += limit (p,1,
		WCross_Track_Zero,
		WCross_Track_Sweep,
		WCross_Track_Fixed_Angle,
		WCross_Track_Description,
		Wnull);
	/* Cross_Track_Sweep is Conditional - present and mandatory if and only if Cross_Track_Fixed_Angle is absent */
	/* Cross_Track_Fixed_Angle is Conditional - present and mandatory if and only if Cross_Track_Sweep is absent */
	err += allow_one_of (p,
		WCross_Track_Sweep,
		WCross_Track_Fixed_Angle,
		Wnull);
	err += require_one_of (p,
		WCross_Track_Sweep,
		WCross_Track_Fixed_Angle,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan_Elevation_Properties
 |
 | Description of data sampling in direction approximately perpendicular to track and cross-track sweep direction.
 |
 |	Scan_Elevation_Properties =
 |		Elevation_Zero +
 |		[Elevation_Sweep |
 |		Elevation_Fixed_Angle] +
 |		(Elevation_Description)
\*----------------------------------------------------------------------*/
static int check_Scan_Elevation_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WElevation_Zero,
		WElevation_Sweep,
		WElevation_Fixed_Angle,
		WElevation_Description,
		Wnull);
	err += require (p,
		WElevation_Zero,
		Wnull);
	err += limit (p,1,
		WElevation_Zero,
		WElevation_Sweep,
		WElevation_Fixed_Angle,
		WElevation_Description,
		Wnull);
	/* Elevation_Sweep is Conditional - present and mandatory if and only if Elevation_Fixed_Angle is absent */
	/* Elevation_Fixed_Angle is Conditional - present and mandatory if and only if Elevation_Sweep is absent */
	err += allow_one_of (p,
		WElevation_Sweep,
		WElevation_Fixed_Angle,
		Wnull);
	err += require_one_of (p,
		WElevation_Sweep,
		WElevation_Fixed_Angle,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan_Geometric_Properties
 |
 | Spatial and temporal description of scan.
 |
 |	Scan_Geometric_Properties =
 |		Scan_Angle_Units +
 |		Scan_Time_Units +
 |		Scan_Distance_Units +
 |		0{Scan_Cross_Track_Properties}1 +
 |		0{Scan_Elevation_Properties}1 +
 |		0{Profile_Properties}1 +
 |		(Scan_Timing) +
 |		Instantaneous_Field_of_View
\*----------------------------------------------------------------------*/
static int check_Scan_Geometric_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WScan_Angle_Units,
		WScan_Time_Units,
		WScan_Distance_Units,
		WScan_Cross_Track_Properties,
		WScan_Elevation_Properties,
		WProfile_Properties,
		WScan_Timing,
		WInstantaneous_Field_of_View,
		Wnull);
	err += require (p,
		WScan_Angle_Units,
		WScan_Time_Units,
		WScan_Distance_Units,
		WInstantaneous_Field_of_View,
		Wnull);
	err += limit (p,1,
		WScan_Angle_Units,
		WScan_Time_Units,
		WScan_Distance_Units,
		WScan_Cross_Track_Properties,
		WScan_Elevation_Properties,
		WProfile_Properties,
		WScan_Timing,
		WInstantaneous_Field_of_View,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan_Radiometric_Properties
 |
 | Function used to convert quantity in detector units to physical units.
 |
 |	Scan_Radiometric_Properties =
 |		Data_Scaling_Information
\*----------------------------------------------------------------------*/
static int check_Scan_Radiometric_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WData_Scaling_Information,
		Wnull);
	err += require (p,
		WData_Scaling_Information,
		Wnull);
	err += limit (p,1,
		WData_Scaling_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan_Spectral_Properties
 |
 | Design specifications for wavelength-dependent scanner properties.
 |
 |	Scan_Spectral_Properties =
 |		Spectral_Information
\*----------------------------------------------------------------------*/
static int check_Scan_Spectral_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WSpectral_Information,
		Wnull);
	err += require (p,
		WSpectral_Information,
		Wnull);
	err += limit (p,1,
		WSpectral_Information,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan_Start_Time
 |
 | Time at start of scan.
 |
 |	Scan_Start_Time =
 |		Single_Date/Time
\*----------------------------------------------------------------------*/
static int check_Scan_Start_Time (struct item *p) {
	int err = 0;
	err += allow (p,
		WSingle_Date_Time,
		Wnull);
	err += require (p,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WSingle_Date_Time,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scan_Timing
 |
 | Schedule for scans.
 |
 |	Scan_Timing =
 |		Scan_Start_Time +
 |		[Scan_Duration |
 |		Scan_Step_Time] +
 |		Scan_Repeat_Time
\*----------------------------------------------------------------------*/
static int check_Scan_Timing (struct item *p) {
	int err = 0;
	err += allow (p,
		WScan_Start_Time,
		WScan_Duration,
		WScan_Step_Time,
		WScan_Repeat_Time,
		Wnull);
	err += require (p,
		WScan_Start_Time,
		WScan_Repeat_Time,
		Wnull);
	err += limit (p,1,
		WScan_Start_Time,
		WScan_Duration,
		WScan_Step_Time,
		WScan_Repeat_Time,
		Wnull);
	/* Scan_Duration is Conditional - present and mandatory if and only if Scan_Step_Time is absent */
	/* Scan_Step_Time is Conditional - present and mandatory if and only if Scan_Duration is absent */
	err += allow_one_of (p,
		WScan_Duration,
		WScan_Step_Time,
		Wnull);
	err += require_one_of (p,
		WScan_Duration,
		WScan_Step_Time,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Science_Paper
 |
 | Reference information for scientific papers relevant to the dataset.
 |
 |	Science_Paper =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Science_Paper (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Sensor_Element_Location
 |
 | Physical position of individual scanner pixels, in the image coordinate system.
 |
 |	Sensor_Element_Location =
 |		Availability_of_Element_Locations +
 |		(Source_of_Element_Locations)
\*----------------------------------------------------------------------*/
static int check_Sensor_Element_Location (struct item *p) {
	int err = 0;
	err += allow (p,
		WAvailability_of_Element_Locations,
		WSource_of_Element_Locations,
		Wnull);
	err += require (p,
		WAvailability_of_Element_Locations,
		Wnull);
	err += limit (p,1,
		WAvailability_of_Element_Locations,
		WSource_of_Element_Locations,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Sensor_Grid
 |
 | Number of cells along axes of sensor grid.
 |
 |	Sensor_Grid =
 |		Raster_Object_Type
\*----------------------------------------------------------------------*/
static int check_Sensor_Grid (struct item *p) {
	int err = 0;
	err += allow (p,
		WRaster_Object_Type,
		Wnull);
	err += require (p,
		WRaster_Object_Type,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WRaster_Object_Type,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Sensor_Orientation
 |
 | Positioning and direction of instrument components on platform.
 |
 |	Sensor_Orientation =
 |		Axes +
 |		(Rotation_Description) +
 |		(Translation_Description)
\*----------------------------------------------------------------------*/
static int check_Sensor_Orientation (struct item *p) {
	int err = 0;
	err += allow (p,
		WAxes,
		WRotation_Description,
		WTranslation_Description,
		Wnull);
	err += require (p,
		WAxes,
		Wnull);
	err += limit (p,1,
		WAxes,
		WRotation_Description,
		WTranslation_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Sensor_System
 |
 | Image coordinate system defined by the pixels of the scanner.
 |
 |	Sensor_System =
 |		Sensor_Grid +
 |		Calibrated_Detector_Positions
\*----------------------------------------------------------------------*/
static int check_Sensor_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WSensor_Grid,
		WCalibrated_Detector_Positions,
		Wnull);
	err += require (p,
		WSensor_Grid,
		WCalibrated_Detector_Positions,
		Wnull);
	err += limit (p,1,
		WSensor_Grid,
		WCalibrated_Detector_Positions,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Source_of_Element_Locations
 |
 | Citation for reference providing sensor element location information.
 |
 |	Source_of_Element_Locations =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Source_of_Element_Locations (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Spectral_Information
 |
 | Wavelength-dependent properties of optical systems.
 |
 |	Spectral_Information =
 |		Number_of_Wavelength_Bands +
 |		1{Wavelength_Band_Properties}n
\*----------------------------------------------------------------------*/
static int check_Spectral_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Wavelength_Bands,
		WWavelength_Band_Properties,
		Wnull);
	err += require (p,
		WNumber_of_Wavelength_Bands,
		WWavelength_Band_Properties,
		Wnull);
	err += limit (p,1,
		WNumber_of_Wavelength_Bands,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Swath_Track_Information
 |
 | Properties of the swath track on the ground.
 |
 |	Swath_Track_Information =
 |		Ground_Shape +
 |		Cross_Track_Motion
\*----------------------------------------------------------------------*/
static int check_Swath_Track_Information (struct item *p) {
	int err = 0;
	err += allow (p,
		WGround_Shape,
		WCross_Track_Motion,
		Wnull);
	err += require (p,
		WGround_Shape,
		WCross_Track_Motion,
		Wnull);
	err += limit (p,1,
		WGround_Shape,
		WCross_Track_Motion,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Thematic_Layer_Identification
 |
 | Listing of the kinds of geospatial information represented by the dataset.
 |
 |	Thematic_Layer_Identification =
 |		Number_of_Thematic_Layers +
 |		1{Layer_Name}n
\*----------------------------------------------------------------------*/
static int check_Thematic_Layer_Identification (struct item *p) {
	int err = 0;
	err += allow (p,
		WNumber_of_Thematic_Layers,
		WLayer_Name,
		Wnull);
	err += require (p,
		WNumber_of_Thematic_Layers,
		WLayer_Name,
		Wnull);
	err += limit (p,1,
		WNumber_of_Thematic_Layers,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | User's_Guide
 |
 | Reference information for User's Guides.
 |
 |	User's_Guide =
 |		Citation_Information
\*----------------------------------------------------------------------*/
static int check_Users_Guide (struct item *p) {
	int err = 0;
	err += allow (p,
		WCitation_Information,
		Wnull);
	err += require (p,
		WCitation_Information,		/* Assumed */
		Wnull);
	err += limit (p,1,
		WCitation_Information,		/* Assumed */
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Wavelength_Band_Properties
 |
 | Design specifications for properties of an individual wavelength range.
 |
 |	Wavelength_Band_Properties =
 |		Wavelength_Units +
 |		(Band_Boundary_Definition) +
 |		Minimum_Wavelength +
 |		Maximum_Wavelength +
 |		(Peak_Wavelength) +
 |		(Wavelength_Region) +
 |		(Nominal_Spatial_Resolution) +
 |		(Band_Quality) +
 |		0{Polarization_Characteristics}n +
 |		(Band_Description)
\*----------------------------------------------------------------------*/
static int check_Wavelength_Band_Properties (struct item *p) {
	int err = 0;
	err += allow (p,
		WWavelength_Units,
		WBand_Boundary_Definition,
		WMinimum_Wavelength,
		WMaximum_Wavelength,
		WPeak_Wavelength,
		WWavelength_Region,
		WNominal_Spatial_Resolution,
		WBand_Quality,
		WPolarization_Characteristics,
		WBand_Description,
		Wnull);
	err += require (p,
		WWavelength_Units,
		WMinimum_Wavelength,
		WMaximum_Wavelength,
		Wnull);
	err += limit (p,1,
		WWavelength_Units,
		WBand_Boundary_Definition,
		WMinimum_Wavelength,
		WMaximum_Wavelength,
		WPeak_Wavelength,
		WWavelength_Region,
		WNominal_Spatial_Resolution,
		WBand_Quality,
		WBand_Description,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Worldwide_Reference_System
 |
 | Global notation system for Landsat data.
 |
 |	Worldwide_Reference_System =
 |		Path +
 |		Row
\*----------------------------------------------------------------------*/
static int check_Worldwide_Reference_System (struct item *p) {
	int err = 0;
	err += allow (p,
		WPath,
		WRow,
		Wnull);
	err += require (p,
		WPath,
		WRow,
		Wnull);
	err += limit (p,1,
		WPath,
		WRow,
		Wnull);
	return (err);
	}
/*----------------------------------------------------------------------*\
 | End remote-sensing element checking routines
\*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*\
 | items of type Wunknown should not have children other than Wblank.	|
\*----------------------------------------------------------------------*/
static int check_unknown (struct item *p) {
	int err = 0;
	struct item *q;
	if (p->child) {
		if (p->child->key == Wblank) {
			if (q = p->child->child) {
				fprintf (out,"Warning (line %d): %s found as child of %s.\n",
					q->line_number,text_of(q->key),text_of(p->child->key));
				fprintf (out,"ICE 0: This shouldn't happen.  Please email a copy of your input file to pschweitzer@usgs.gov indicating you have ICE 0.\n");
				}
			}
		else
			if (p->child->key == Wunknown) {
				/*----------------------------------------------------------*\
				 | Unknown found as child of unknown.  This problem should	|
				 | have been fixed in the parser, so if it still occurs,	|
				 | generate an ICE and ask the user to contact me.			|
				\*----------------------------------------------------------*/
				fprintf (out,"Warning (line %d): %s found as child of %s.\n",
					p->line_number,text_of(p->child->key),text_of(p->key));
				fprintf (out,"ICE 1: This shouldn't happen.  Please email a copy of your input file to pschweitzer@usgs.gov indicating you have ICE 1.\n");
				}
			else {
				fprintf (out,"Error (line %d): element of unknown type has child %s\n",
					p->line_number,text_of(p->key));
				err++;
				}
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
 | Scalar children can be checked automatically only if their domains	|
 | are fairly restricted.												|
\*----------------------------------------------------------------------*/
static int check_date (char *string) {
	char *s = string;
	int prefix = 0;
	while (*s && isspace(*s)) s++;
	if (!isdigit(*s)) {
		if (memcmp (s,"bc",2) == 0 ||
			memcmp (s,"cc",2) == 0 ||
			memcmp (s,"cd",2) == 0) {
			s += 2;
			prefix = 1;
			}
		else return (1);
		}
	/* legal dates are at represented as at least 4 decimal digits */
	if (!isdigit(*s++)) return (1);
	if (!isdigit(*s++)) return (1);
	if (!isdigit(*s++)) return (1);
	if (!isdigit(*s++)) return (1);
	if (!prefix) {
		/* Try to convince people not to use month 00 or day 00 */
		if (memcmp (s,"0000",4)== 0) return (1);
		if (memcmp (s,"00",2)== 0) return (1);
		}
	return (0);
	}
static int check_time (char *string) {
	char *s = string;
	int h,m;
	while (*s && isspace(*s)) s++;
	/* legal times are 0000 to 2359 */
	if (!isdigit(*s)) return (1);
	h = 10 * (*s++ - '0');
	if (!isdigit(*s)) return (1);
	h += *s++ - '0';
	if (h > 23) return (1);
	if (!isdigit(*s)) return (1);
	m = 10 * (*s++ - '0');
	if (!isdigit(*s)) return (1);
	m += *s++ - '0';
	if (m > 59) return (1);
	return (0);
	}
static void strip_quotes (char *string) {
	char *s = string;
	char *t = string + strlen (string) - 1;
	while (*s && isspace (*s)) s++;
	while (t > string && isspace (*t)) t--;
	if (*s == '\"' && *t == '\"') {
		s++;
		t--;
		if (s < t) {
			memcpy (string,s,t-s+1);
			string[t-s+1] = 0;
			}
		}
	}
static int check_scalar_children (struct item *p) {
	int err = 0;
	struct item *q;
	long v;
	double d;
	char *s;
	if (!p->child) {
		fprintf (out,"Warning (line %d): %s does not have a value\n",
			p->line_number,text_of(p->key));
		errors.empty++;
		err++;
		return (err);
		}
	for (q=p->child; q; q=q->next) {
		if (q->key != Wunknown && q->key != Wblank && q->d) {
			/*----------------------------------------------------------*\
			 | A keyword has occurred at the beginning of a text value.	|
			 | Issue a warning and reclassify the node as unknown.  If	|
			 | there is a child associated with this value (i.e. more	|
			 | text on the line containing the keyword), concatenate	|
			 | the child's text with that of the keyword and delete the	|
			 | child node.												|
			 |															|
			 | The test of q->d above ensures that this code will not	|
			 | be run when the input is XML.  In that case, the XML is	|
			 | structurally incorrect.  Bad things will likely happen	|
			 | later, but let's not screw them up now any more than we	|
			 | have to.													|
			\*----------------------------------------------------------*/
			fprintf (out,"Warning (line %d): in the value of %s, the line beginning with the element name %s is treated as plain text.\n",
				q->line_number,
				text_of(p->key),
				text_of(q->key));
			q->key = Wunknown;
			if (q->child) {
				/*------------------------------------------------------*\
				 | With the text encoding scheme, the child's text is	|
				 | certain to begin on the first non-blank character	|
				 | after the end of the keyword, so we need only remove	|
				 | the null character after the keyword to join the		|
				 | text of this node with that of its child.			|
				 |														|
				 | If some other encoding is used, the text may not be	|
				 | arranged so neatly; allocate space for the combined	|
				 | string and concatenate them with a space in between.	|
				\*------------------------------------------------------*/
				if (q->line_number == q->child->line_number) {
					s = q->d + strlen (q->d);
					*s = ' ';
					}
				else
					if (s = (char *) malloc (strlen(q->d) + strlen(q->child->d) + 2)) {
						strcpy (s,q->d);
						strcat (s," ");
						strcat (s,q->child->d);
						q->d = s;
						}
				deallocate_item (q->child);
				q->child = NULL;
				}
			}
		else {
			if (q->key != Wblank && q->d)	/* don't do this if q->d is NULL (could happen in XML) */
				switch (p->key) {
					/* restricted text values */
					case WProgress:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Complete") &&
								stricmp (q->d,"In work") &&
								stricmp (q->d,"Planned")) {
								err++;
								}
						break;
					case WDirect_Spatial_Reference_Method:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Point") &&
								stricmp (q->d,"Vector") &&
								stricmp (q->d,"Raster")) {
								err++;
								}
						break;
					case WSDTS_Point_and_Vector_Object_Type:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Point") &&
								stricmp (q->d,"Entity point" ) &&
								stricmp (q->d,"Label point" ) &&
								stricmp (q->d,"Area point" ) &&
								stricmp (q->d,"Node, planar graph" ) &&
								stricmp (q->d,"Node, network" ) &&
								stricmp (q->d,"String" ) &&
								stricmp (q->d,"Link" ) &&
								stricmp (q->d,"Complete chain" ) &&
								stricmp (q->d,"Area chain" ) &&
								stricmp (q->d,"Network chain, planar graph" ) &&
								stricmp (q->d,"Network chain, nonplanar graph" ) &&
								stricmp (q->d,"Circular arc, three point center" ) &&
								stricmp (q->d,"Elliptical arc" ) &&
								stricmp (q->d,"Uniform B-spline" ) &&
								stricmp (q->d,"Piecewise Bezier" ) &&
								stricmp (q->d,"Ring with mixed composition" ) &&
								stricmp (q->d,"Ring composed of strings" ) &&
								stricmp (q->d,"Ring composed of chains" ) &&
								stricmp (q->d,"Ring composed of arcs" ) &&
								stricmp (q->d,"G-polygon" ) &&
								stricmp (q->d,"GT-polygon composed of rings" ) &&
								stricmp (q->d,"GT-polygon composed of chains" ) &&
								stricmp (q->d,"Universe polygon composed of rings" ) &&
								stricmp (q->d,"Universe polygon composed of chains" ) &&
								stricmp (q->d,"Void polygon composed of rings" ) &&
								stricmp (q->d,"Void polygon composed of chains")) {
								err++;
								}
						break;
					case WVPF_Point_and_Vector_Object_Type:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Node") &&
								stricmp (q->d,"Edge") &&
								stricmp (q->d,"Face") &&
								stricmp (q->d,"Text")) {
								err++;
								}
						break;
					case WRaster_Object_Type:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Point") &&
								stricmp (q->d,"Pixel") &&
								stricmp (q->d,"Grid Cell") &&
								stricmp (q->d,"Voxel")) {
								err++;
								}
						break;
					case WGeographic_Coordinate_Units:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Decimal degrees") &&
								stricmp (q->d,"Decimal minutes") &&
								stricmp (q->d,"Decimal seconds") &&
								stricmp (q->d,"Degrees and decimal minutes") &&
								stricmp (q->d,"Degrees, minutes, and decimal seconds") &&
								stricmp (q->d,"Radians") &&
								stricmp (q->d,"Grads")) {
								err++;
								}
						break;
					case WGrid_Coordinate_System_Name:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Universal Transverse Mercator") &&
								stricmp (q->d,"Universal Polar Stereographic") &&
								stricmp (q->d,"State Plane Coordinate System 1927") &&
								stricmp (q->d,"State Plane Coordinate System 1983") &&
								stricmp (q->d,"ARC Coordinate System") &&
								stricmp (q->d,"other grid system")) {
								err++;
								}
						break;
					case WUPS_Zone_Identifier:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"A") &&
								stricmp (q->d,"B") &&
								stricmp (q->d,"Y") &&
								stricmp (q->d,"Z")) {
								err++;
								}
						break;
					case WSPCS_Zone_Identifier:
						strip_quotes (q->d);
						break;
					case WPlanar_Coordinate_Encoding_Method:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"coordinate pair") &&
								stricmp (q->d,"distance and bearing") &&
								stricmp (q->d,"row and column")) {
								err++;
								}
						break;
					case WBearing_Units:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Decimal degrees") &&
								stricmp (q->d,"Decimal minutes") &&
								stricmp (q->d,"Decimal seconds") &&
								stricmp (q->d,"Degrees and decimal minutes") &&
								stricmp (q->d,"Degrees, minutes, and decimal seconds") &&
								stricmp (q->d,"Radians") &&
								stricmp (q->d,"Grads")) {
								err++;
								}
						break;
					case WBearing_Reference_Direction:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"North") &&
								stricmp (q->d,"South")) {
								err++;
								}
						break;
					case WBearing_Reference_Meridian:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Assumed") &&
								stricmp (q->d,"Grid") &&
								stricmp (q->d,"Magnetic") &&
								stricmp (q->d,"Astronomic") &&
								stricmp (q->d,"Geodetic")) {
								err++;
								}
						break;
					case WAltitude_Encoding_Method:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Explicit elevation coordinate included with horizontal coordinates") &&
								stricmp (q->d,"Implicit coordinate") &&
								stricmp (q->d,"Attribute values")) {
								err++;
								}
						break;
					case WDepth_Encoding_Method:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Explicit depth coordinate included with horizontal coordinates") &&
								stricmp (q->d,"Implicit coordinate") &&
								stricmp (q->d,"Attribute values")) {
								err++;
								}
						break;
					case WParity:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"None") &&
								stricmp (q->d,"Odd") &&
								stricmp (q->d,"Even") &&
								stricmp (q->d,"Mark") &&
								stricmp (q->d,"Space")) {
								err++;
								}
						break;
					case WMetadata_Time_Convention:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"local time") &&
								stricmp (q->d,"local time with time differential factor") &&
								stricmp (q->d,"universal time")) {
								err++;
								}
						break;
					case WCase_Sensitive:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"Y") &&
								stricmp (q->d,"N")) {
								err++;
								}
						break;
					/* integer values */
					case WSource_Scale_Denominator:
						/* Source Scale Denominator > 1 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v <= 1) err++;
						break;
					case WCloud_Cover:
						/* 0 <= Cloud Cover <= 100  "Unknown" */
						if (stricmp (q->d,"Unknown") != 0) {
							v = strtol (q->d,&s,0);
							if (s == q->d || v < 0 || v > 100) err++;
							}
						break;
					case WPoint_and_Vector_Object_Count:
						/* Point and Vector Object Count > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v <= 0) err++;
						break;
					case WVPF_Topology_Level:
						/* 0 <= VPF Topology Level <= 3 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v < 0 || v > 3) err++;
						break;
					case WRow_Count:
						/* Row Count > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v <= 0) err++;
						break;
					case WColumn_Count:
						/* Column Count > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v <= 0) err++;
						break;
					case WVertical_Count:
						/* Depth Count > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v <= 0) err++;
						break;
					case WLandsat_Number:
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						break;
					case WPath_Number:
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						break;
					case WUTM_Zone_Number:
						/* 1 <= UTM Zone Number <= 60 for the northern hemisphere;
						 -60 <= UTM Zone Number <= -1 for the southern hemisphere */
						v = strtol (q->d,&s,0);
						if (s == q->d || v < -60 || v > 60) err++;
						break;
					case WARC_System_Zone_Identifier:
						/* 1 <= ARC System Zone Identifier <= 18 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v <= 0 || v > 18) err++;
						break;
					case WLowest_BPS:
						/* Lowest BPS >= 110 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v < 110) err++;
						break;
					case WHighest_BPS:
						/* Highest BPS > Lowest BPS */
						v = strtol (q->d,&s,0);
						if (s == q->d || v < 110) err++;
						break;
					case WNumber_DataBits:
						/* 7 <= Number DataBits <= 8 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v < 7 || v > 8) err++;
						break;
					case WNumber_StopBits:
						/* 1 <= Number StopBits <= 2 */
						v = strtol (q->d,&s,0);
						if (s == q->d || v < 1 || v > 2) err++;
						break;
					/* real values */
					case WWest_Bounding_Coordinate:
						/* -180.0 <= West Bounding Coordinate < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WEast_Bounding_Coordinate:
						/* -180.0 <= East Bounding Coordinate <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WNorth_Bounding_Coordinate:
						/* -90.0 <= North Bounding Coordinate <= 90.0;
							North Bounding Coordinate >= South Bounding Coordinate */
						d = strtod (q->d,&s);
						if (s == q->d || d < -90.0 || d > 90.0) err++;
						break;
					case WSouth_Bounding_Coordinate:
						/* -90.0 <= South Bounding Coordinate <= 90.0;
							South Bounding Coordinate <= North Bounding Coordinate */
						d = strtod (q->d,&s);
						if (s == q->d || d < -90.0 || d > 90.0) err++;
						break;
					case WG_Ring_Latitude:
						/* -90.0 <= G-Ring Latitude <= 90.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -90.0 || d > 90.0) err++;
						break;
					case WG_Ring_Longitude:
						/* -180.0 <= G-Ring Longitude < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WHorizontal_Positional_Accuracy_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WVertical_Positional_Accuracy_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WLatitude_Resolution:
						/* Latitude Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WLongitude_Resolution:
						/* Longitude Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WStandard_Parallel:
						/* -90.0 <= Standard Parallel <= 90.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -90.0 || d > 90.0) err++;
						break;
					case WLongitude_of_Central_Meridian:
						/* -180.0 <= Longitude of Central Meridian < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WLatitude_of_Projection_Origin:
						/* -90.0 <= Latitude of Projection Origin <= 90.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -90.0 || d > 90.0) err++;
						break;
					case WFalse_Easting:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WFalse_Northing:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WScale_Factor_at_Equator:
						/* Scale Factor at Equator > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WHeight_of_Perspective_Point_Above_Surface:
						/* Height of Perspective Point Above Surface > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WLongitude_of_Projection_Center:
						/* -180.0 <= Longitude of Projection Center < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WLatitude_of_Projection_Center:
						/* -90.0 <= Latitude of Projection Center <= 90.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -90.0 || d > 90.0) err++;
						break;
					case WScale_Factor_at_Center_Line:
						/* Scale Factor at Center Line > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WAzimuthal_Angle:
						/* 0.0 <= Azimuthal Angle < 360.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < 0.0 || d >= 360.0) err++;
						break;
					case WAzimuth_Measure_Point_Longitude:
						/* -180.0 <= Azimuth Measure Point Longitude < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WOblique_Line_Latitude:
						/* -90.0 <= Oblique Line Latitude <= 90.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -90.0 || d > 90.0) err++;
						break;
					case WOblique_Line_Longitude:
						/* -180.0 <= Oblique Line Longitude < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WStraight_Vertical_Longitude_from_Pole:
						/* -180.0 <= Straight Vertical Longitude from Pole < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d < -180.0 || d > 180.0) err++;
						break;
					case WScale_Factor_at_Projection_Origin:
						/* Scale Factor at Projection Origin > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WScale_Factor_at_Central_Meridian:
						/* Scale Factor at Central Meridian > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WAbscissa_Resolution:
						/* Abscissa Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WOrdinate_Resolution:
						/* Ordinate Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WDistance_Resolution:
						/* Distance Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WBearing_Resolution:
						/* Bearing Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WSemi_major_Axis:
						/* Semi-major Axis > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WDenominator_of_Flattening_Ratio:
						/* Denominator of Flattening > 0.0 */
						if (strcmp (q->d,"infinite") != 0) {
							d = strtod (q->d,&s);
							if (s == q->d || d <= 0.0) err++;
							}
						break;
					case WAltitude_Resolution:
						/* Altitude Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WDepth_Resolution:
						/* Depth Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WAttribute_Measurement_Resolution:
						/* Attribute Measurement Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WAttribute_Value_Accuracy:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WTransfer_Size:
						/* Transfer Size > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					case WRecording_Density:
						/* Recording Density > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d || d <= 0.0) err++;
						break;
					/* date values */
					case WProcess_Date:
						/* "Unknown" "Not complete" free date */
						if (stricmp (q->d,"Unknown") &&
							stricmp (q->d,"Not complete"))
							err += check_date (q->d);
						break;
					case WBeginning_Date_of_Attribute_Values:
						/* free date */
						err += check_date (q->d);
						break;
					case WEnding_Date_of_Attribute_Values:
						/* free date */
						err += check_date (q->d);
						break;
					case WFormat_Version_Date:
						/* free date */
						err += check_date (q->d);
						break;
					case WMetadata_Date:
						/* free date */
						err += check_date (q->d);
						break;
					case WMetadata_Review_Date:
						/* free date; Metadata Review Date later than Metadata Date */
						err += check_date (q->d);
						break;
					case WMetadata_Future_Review_Date:
						/* free date; Metadata Future Review Date later than Metadata Review Date */
						err += check_date (q->d);
						break;
					case WPublication_Date:
						/* "Unknown" "Unpublished material" free date */
						if (stricmp (q->d,"Unknown") &&
							stricmp (q->d,"Unpublished material"))
							err += check_date (q->d);
						break;
					case WCalendar_Date:
						/* "Unknown" free date */
						if (stricmp (q->d,"Unknown"))
							err += check_date (q->d);
						break;
					case WBeginning_Date:
						/* "Unknown" free date */
						if (stricmp (q->d,"Unknown"))
							err += check_date (q->d);
						break;
					case WEnding_Date:
						/* "Unknown" "Present" free date */
						if (stricmp (q->d,"Unknown") &&
							stricmp (q->d,"Present"))
							err += check_date (q->d);
						break;
					/* time values */
					case WProcess_Time:
						/* free time */
						err += check_time(q->d);
						break;
					case WPublication_Time:
						/* "Unknown" free time */
						if (stricmp (q->d,"Unknown")) err += check_time(q->d);
						break;
					case WTime_of_Day:
						/* "Unknown" free time */
						if (stricmp (q->d,"Unknown")) err += check_time(q->d);
						break;
					case WBeginning_Time:
						/* "Unknown" free time */
						if (stricmp (q->d,"Unknown")) err += check_time(q->d);
						break;
					case WEnding_Time:
						/* "Unknown" free time */
						if (stricmp (q->d,"Unknown")) err += check_time(q->d);
						break;
					/*--------------------------------------------------*\
					 | Shoreline elements
					\*--------------------------------------------------*/
					/* Text values that can be checked */
					case WType_of_Tide:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"semidiurnal") &&
								stricmp (q->d,"mainly semidiurnal") &&
								stricmp (q->d,"mainly diurnal") &&
								stricmp (q->d,"diurnal")) {
								err++;
								}
						break;
					/* Real values that can be checked */
					case WBarometric_Pressure:
						/* Barometric_Pressure > 0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WRange_of_Tide:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					/* Integer values that can be checked */
					case WWave_Height:
						/* Wave_Height > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WWind_Direction:
						/* 0 <= Wind_Direction <=  360 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0 || v > 360) err++;
						break;
					case WWind_Speed:
						/* Wind_Speed > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					/* Time values that can be checked */
					case WTime_of_High_Tide:
						/* free time (local) */
						err += check_time (q->d);
						break;
					case WTime_of_Low_Tide:
						/* free time (local) */
						err += check_time (q->d);
						break;
					/*--------------------------------------------------*\
					 | Remote-sensing elements
					\*--------------------------------------------------*/
					/* Text values that can be checked */
					case WAscending_Descending_Indicator:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"0") &&
								stricmp (q->d,"1")) {
								err++;
								}
						break;
					case WAvailability_of_Element_Locations:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"available") &&
								stricmp (q->d,"not available")) {
								err++;
								}
						break;
					case WAxis_Rotation_Convention:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"rotated") &&
								stricmp (q->d,"fixed")) {
								err++;
								}
						break;
					case WControl_Point_Type:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"full") &&
								stricmp (q->d,"horizontal") &&
								stricmp (q->d,"vertical")) {
								err++;
								}
						break;
					case WCross_Track_Direction:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"positive") &&
								stricmp (q->d,"negative")) {
								err++;
								}
						break;
					case WElevation_Direction:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"positive") &&
								stricmp (q->d,"negative")) {
								err++;
								}
						break;
					case WFilter_on_Camera_Indicator:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"yes") &&
								stricmp (q->d,"no")) {
								err++;
								}
						break;
					case WForward_Motion_Compensation:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"yes") &&
								stricmp (q->d,"no")) {
								err++;
								}
						break;
					case WGPS_Information_System_Availability:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"available") &&
								stricmp (q->d,"not available")) {
								err++;
								}
						break;
					case WGround_Control_Point_Organization:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"location") &&
								stricmp (q->d,"library")) {
								err++;
								}
						break;
					case WINS_Reading_Availability:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"available") &&
								stricmp (q->d,"not available")) {
								err++;
								}
						break;
					case WMethod_of_Last_Calibration:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"optical") &&
								stricmp (q->d,"photographic")) {
								err++;
								}
						break;
					case WProfiling_Direction:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"upward") &&
								stricmp (q->d,"downward")) {
								err++;
								}
						break;
					case WRotation_Sequence:
						strip_quotes (q->d);
						if (check_text_values)
							if (stricmp (q->d,"123") &&
								stricmp (q->d,"132") &&
								stricmp (q->d,"213") &&
								stricmp (q->d,"231") &&
								stricmp (q->d,"312") &&
								stricmp (q->d,"321")) {
								err++;
								}
						break;
					/* Real values that can be checked */
					case WAerial_Film_Speed:
						/* Aerial_Film_Speed > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WAffine_Distortion_X_Prime_Coefficient:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WAffine_Distortion_Y_Prime_Coefficient:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WAngle_Distortion_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WArea_Weighted_Average_Resolution:
						/* Area_Weighted_Average_Resolution > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WArgument_of_Perigee:
						/* 0.0 <= Argument_of_Perigee < 360.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0 || d >= 360.0) err++;
						break;
					case WCalibrated_Focal_Length:
						/* Calibrated_Focal_Length > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WClock_Time_Drift:
						/* -75.0 <= Clock_Time/Drift <= 75.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 75.0 || d > 75.0) err++;
						break;
					case WColumn_Delta_X:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WColumn_Delta_Y:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WControl_Point_Column:
						/* Control_Point_Column >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WControl_Point_Horizontal_X_Accuracy:
						/* Control_Point_Horizontal_X_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WControl_Point_Horizontal_Y_Accuracy:
						/* Control_Point_Horizontal_Y_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WControl_Point_Row:
						/* Control_Point_Row >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WControl_Point_Vertical_Accuracy:
						/* Control_Point_Vertical_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WControl_Point_x_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WControl_Point_y_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WControl_Point_z_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WCoordinate_x_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WCoordinate_y_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WCoordinate_z_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WCross_Track_Extent_Angle:
						/* Cross_Track_Extent_Angle > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WCross_Track_Fixed_Angle:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WCross_Track_Start_Angle:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WCross_Track_Step_Angle:
						/* Cross_Track_Step_Angle > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WDistance_Distortion_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WEccentricity:
						/* 0.0 <= Eccentricity < 1.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0 || d >= 1.0) err++;
						break;
					case WEffective_Aerial_Film_Speed:
						/* Effective_Aerial_Film_Speed > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WElevation_Extent_Angle:
						/* Elevation_Extent_Angle > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WElevation_Fixed_Angle:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WElevation_Start_Angle:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WElevation_Step_Angle:
						/* Elevation_Step_Angle > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WExposure_Time:
						/* Exposure_Time > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WFlying_Height:
						/* Flying_Height > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WFrame_Area_Value:
						/* Frame_Area_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WGrid_First_Element_Map_X_Coordinate:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WGrid_First_Element_Map_Y_Coordinate:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WIFOV_x_Value:
						/* IFOV_x_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WIFOV_y_Value:
						/* IFOV_y_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WImage_Size_x_Value:
						/* Image_Size_x_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WImage_Size_y_Value:
						/* Image_Size_y_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WInclination:
						/* 0.0 <= Inclination <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0 || d > 180.0) err++;
						break;
					case WLight_Drop:
						/* 0.0 <= Light_Drop <= 100.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0 || d > 100.0) err++;
						break;
					case WMaximum_Wavelength:
						/* Maximum_Wavelength  >= Minimum_Wavelength */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WMinimum_Wavelength:
						/* Minimum_Wavelength > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WNadir_Latitude:
						/* -90.0 <= Nadir_Latitude <= 90.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < -90.0 || d > 90.0) err++;
						break;
					case WNadir_Longitude:
						/* -180.0 <= Nadir_Longitude < 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < -180.0 || d >= 180.0) err++;
						break;
					case WOrbit_Period_Value:
						/* Orbit_Period_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WPeak_Wavelength:
						/* Minimum_Wavelength <= Peak_Wavelength <= Maximum_Wavelength */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WPercentage_of_Overlap:
						/* 0.0 <= Percentage_of_Overlap <= 100.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0 || d > 100.0) err++;
						break;
					case WPitch:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WPitch_Accuracy:
						/* Pitch_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WPixel_Cross_Track_Size:
						/* Pixel_Cross_Track_Size > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WPixel_Elevation_Size:
						/* Pixel_Elevation_Size > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WPixel_Height_Above_Ellipsoid:
						/* Pixel_Height_Above_Ellipsoid > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WPixel_Profile_Size:
						/* Pixel_Profile_Size > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WPlatform_Nominal_Altitude_Value:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WPlatform_Nominal_Longitude:
						/* -180.0 < Platform_Nominal_Longitude <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= -180.0 || d > 180.0) err++;
						break;
					case WPolynomial_Coefficient:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WProfile_Extent:
						/* Profile_Extent > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WProfile_Fixed:
						/* Profile_Fixed > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WProfile_Start:
						/* Profile_Start > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WProfile_Step:
						/* Profile_Step > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WProjection_Center_X_Position:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WProjection_Center_Y_Position:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WProjection_Center_Z_Position:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WQuality_of_Autocollimation_Principal_Point_x_Value:
						/* Quality_of_Autocollimation_Principal_Point_x_Value >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WQuality_of_Autocollimation_Principal_Point_y_Value:
						/* Quality_of_Autocollimation_Principal_Point_y_Value >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WQuality_of_Focal_Length:
						/* Quality_of_Focal_Length > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WQuality_of_Symmetry_Principal_Point_x_Value:
						/* Quality_of_Symmetry_Principal_Point_x_Value >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WQuality_of_Symmetry_Principal_Point_y_Value:
						/* Quality_of_Symmetry_Principal_Point_y_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WRadial_Asymmetrical_Coefficient_B1:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WRadial_Asymmetrical_Coefficient_B2:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WRadial_Symmetrical_Angle_Interval:
						/* Radial_Symmetrical_Angle_Interval > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WRadial_Symmetrical_Distance_Interval:
						/* Radial_Symmetrical_Distance_Interval > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WRelative_Aperture:
						/* Relative_Aperture > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WRelative_Azimuth:
						/* -180.0 <= Relative_Azimuth <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < -180.0 || d > 180.0) err++;
						break;
					case WResolving_Angle:
						/* Resolving_Angle >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WResolving_Value_Radial:
						/* Resolving_Value_Radial > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WResolving_Value_Tangential:
						/* Resolving_Value_Tangential > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WRight_Ascension_of_Ascending_Node:
						/* 0.0 <= Right_Ascension_of_Ascending_Node < 360.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0 || d >= 360.0) err++;
						break;
					case WRoll:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WRoll_Accuracy:
						/* Roll_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WRow_Delta_X:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WRow_Delta_Y:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WSatellite_Local_Azimuth_Angle:
						/* -180.0 <= Satellite/Local_Azimuth_Angle <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < -180.0 || d > 180.0) err++;
						break;
					case WSatellite_Local_Zenith_Angle:
						/* -180.0 <= Satellite/Local_Zenith_Angle <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < -180.0 || d > 180.0) err++;
						break;
					case WScan_Duration:
						/* Scan_Duration > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WScan_Repeat_Time:
						/* Scan_Repeat_Time > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WScan_Step_Time:
						/* Scan_Step_Time > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WSemimajor_Axis:
						/* 6378.2 < Semimajor axis < 2.61x105 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 6378.2 || d >= 2.61E5) err++;
						break;
					case WSolar_Azimuth_Angle:
						/* -180.0 <= Solar_Azimuth_Angle <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < -180.0 || d > 180.0) err++;
						break;
					case WSolar_Zenith_Angle:
						/* -180.0 <= Solar_Zenith_Angle <= 180.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < -180.0 || d > 180.0) err++;
						break;
					case WSpatial_Resolution_Value:
						/* Spatial_Resolution_Value > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WSpectral_Limit:
						/* Spectral_Limit > 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d <= 0.0) err++;
						break;
					case WX_Position_Accuracy:
						/* X_Position_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WY_Position_Accuracy:
						/* Y_Position_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WYaw:
						/* free real */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						break;
					case WYaw_Accuracy:
						/* Yaw_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					case WZ_Position_Accuracy:
						/* Z_Position_Accuracy >= 0.0 */
						d = strtod (q->d,&s);
						if (s == q->d) err++;
						else
							if (d < 0.0) err++;
						break;
					/* Integer values that can be checked */
					case WDimension_Count:
						/* Dimension_Count >= 1 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v < 1) err++;
						break;
					case WNumber_of_Angle_Distortion_Values:
						/* Number_of_Angle_Distortion_Values > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Bands:
						/* Number_of_Bands > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Cross_Track_Samples:
						/* Number_of_Cross_Track_Samples > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Data_Dimensions:
						/* Number_of_Data_Dimensions > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Denominator_Terms:
						/* Number_of_Denominator_Terms >=1 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v < 1) err++;
						break;
					case WNumber_of_Distance_Distortion_Values:
						/* Number_of_Distance_Distortion_Values > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Elevation_Samples:
						/* Number_of_Elevation_Samples > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Numerator_Terms:
						/* Number_of_Numerator_Terms >=1 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v < 1) err++;
						break;
					case WNumber_of_Points:
						/* Number_of_Points > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Profile_Samples:
						/* Number_of_Profile_Samples > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WNumber_of_Resolution_Values:
						/* Number_of_Resolution_Values >= 1 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v < 1) err++;
						break;
					case WNumber_of_Thematic_Layers:
						/* Number_of_Thematic_Layers > 0 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0) err++;
						break;
					case WPath:
						/* 0 < Path <= 251 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0 || v > 251) err++;
						break;
					case WRow:
						/* 0 < Row <= 248 */
						v = strtol (q->d,&s,0);
						if (s == q->d) err++;
						else
							if (v <= 0 || v > 248) err++;
						break;
					/* Date values that can be checked */
					case WDate_of_Last_Calibration:
						/* free date */
						err += check_date (q->d);
						break;
					/* End remote-sensing elements */
					/* other values cannot be checked automatically */
					default:
						break;
					}
			if (err) {
				fprintf (out,"Error (line %d): improper value for %s\n",
					q->line_number,text_of(p->key));
				errors.bad_value++;
				}
			/*----------------------------------------------------------*\
			 | In XML files, if someone puts an element into a scalar	|
			 | then the scalar will be checked for a value but there	|
			 | won't be one (q->d == NULL); instead there will be an	|
			 | element whose key q->key can be identified as the source	|
			 | of the error.  This is a "misplaced element" error.		|
			\*----------------------------------------------------------*/
			if (q->key != Wblank && q->key != Wunknown && q->d == NULL) {
				fprintf (out,"Error (line %d): %s is not permitted in %s\n",
					q->line_number,text_of(q->key),text_of(p->key));
				errors.misplaced++;
				}
			}
		}
	return (err);
	}
/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/
int check_extension (struct item *p) {
	int err = 0;
	struct item *q;
	char *s;
	for (q=p->child; q; q=q->next)
		if (parent_child (p->key,q->key) == 0)
			if (q->key == Wunknown) {
				fprintf (out,"Error (line %d): no element recognized in \"%s\"; text is not permitted in %s\n",
					q->line_number,q->d,text_of(p->key));
				errors.unrecognized++;
				err++;
				}
			else
				if (extension_is_compound (p->key)) {
					fprintf (out,"Error (line %d): %s is not permitted in %s\n",
						p->line_number,text_of(q->key),text_of(p->key));
					errors.misplaced++;
					err++;
					}
				else
					if (q->d) {
						/*----------------------------------------------*\
						 | q->d might be NULL if input was XML.  But in	|
						 | that case, the problem is a structural one	|
						 | in the XML itself and cannot easily be fixed	|
						 | at this point.								|
						\*----------------------------------------------*/
						/*--------------------------------------------------*\
						 | An element name appears at the beginning of the	|
						 | text value of an extension.  Issue a warning and	|
						 | reclassify the node as unknown.  If there is a	|
						 | child associated with this value (i.e. more text	|
						 | on the line containing the keyword), concatenate	|
						 | the child's text with that of the keyword and	|
						 | delete the child node.							|
						\*--------------------------------------------------*/
						fprintf (out,"Warning (line %d): in the value of %s, the line beginning with the element name %s is treated as plain text.\n",
							q->line_number,
							text_of(p->key),
							text_of(q->key));
						q->key = Wunknown;
						if (q->child) {
							/*----------------------------------------------*\
							 | With the text encoding scheme, the child's	|
							 | text is certain to begin on the first non-	|
							 | blank character after the end of the keyword,|
							 | so we need only remove the null character	|
							 | after the keyword to join the text of this	|
							 | node with that of its child.  If some other	|
							 | encoding is used, the text may not be		|
							 | arranged so neatly; allocate space for the	|
							 | combined string and concatenate them with a	|
							 | space in between.							|
							\*----------------------------------------------*/
							if (q->line_number == q->child->line_number) {
								s = q->d + strlen (q->d);
								*s = ' ';
								}
							else
								if (s = (char *) malloc (strlen(q->d) + strlen(q->child->d) + 2)) {
									strcpy (s,q->d);
									strcat (s," ");
									strcat (s,q->child->d);
									q->d = s;
									}
							deallocate_item (q->child);
							q->child = NULL;
							}
						}
	return (err);
	}
/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/
struct rule {
	enum fgdc_keyword key;
	int (*check)(struct item *p);
	};
static struct rule rule_table[] = {
	{WMetadata,
		check_Metadata},
	{WIdentification_Information,
		check_Identification_Information},
	{WCitation,
		check_Citation},
	{WDescription,
		check_Description},
	{WTime_Period_of_Content,
		check_Time_Period_of_Content},
	{WStatus,
		check_Status},
	{WSpatial_Domain,
		check_Spatial_Domain},
	{WBounding_Coordinates,
		check_Bounding_Coordinates},
	{WData_Set_G_Polygon,
		check_Data_Set_G_Polygon},
	{WData_Set_G_Polygon_Outer_G_Ring,
		check_Data_Set_G_Polygon_Outer_G_Ring},
	{WData_Set_G_Polygon_Exclusion_G_Ring,
		check_Data_Set_G_Polygon_Exclusion_G_Ring},
	{WG_Ring_Point,
		check_G_Ring_Point},
	{WKeywords,
		check_Keywords},
	{WTheme,
		check_Theme},
	{WPlace,
		check_Place},
	{WStratum,
		check_Stratum},
	{WTemporal,
		check_Temporal},
	{WPoint_of_Contact,
		check_Point_of_Contact},
	{WBrowse_Graphic,
		check_Browse_Graphic},
	{WSecurity_Information,
		check_Security_Information},
	{WCross_Reference,
		check_Cross_Reference},
	{WData_Quality_Information,
		check_Data_Quality_Information},
	{WAttribute_Accuracy,
		check_Attribute_Accuracy},
	{WQuantitative_Attribute_Accuracy_Assessment,
		check_Quantitative_Attribute_Accuracy_Assessment},
	{WPositional_Accuracy,
		check_Positional_Accuracy},
	{WHorizontal_Positional_Accuracy,
		check_Horizontal_Positional_Accuracy},
	{WQuantitative_Horizontal_Positional_Accuracy_Assessment,
		check_Quantitative_Horizontal_Positional_Accuracy_Assessment},
	{WVertical_Positional_Accuracy,
		check_Vertical_Positional_Accuracy},
	{WQuantitative_Vertical_Positional_Accuracy_Assessment,
		check_Quantitative_Vertical_Positional_Accuracy_Assessment},
	{WLineage,
		check_Lineage},
	{WSource_Information,
		check_Source_Information},
	{WSource_Citation,
		check_Source_Citation},
	{WSource_Time_Period_of_Content,
		check_Source_Time_Period_of_Content},
	{WProcess_Step,
		check_Process_Step},
	{WProcess_Contact,
		check_Process_Contact},
	{WSpatial_Data_Organization_Information,
		check_Spatial_Data_Organization_Information},
	{WPoint_and_Vector_Object_Information,
		check_Point_and_Vector_Object_Information},
	{WSDTS_Terms_Description,
		check_SDTS_Terms_Description},
	{WVPF_Terms_Description,
		check_VPF_Terms_Description},
	{WVPF_Point_and_Vector_Object_Information,
		check_VPF_Point_and_Vector_Object_Information},
	{WRaster_Object_Information,
		check_Raster_Object_Information},
	{WSpatial_Reference_Information,
		check_Spatial_Reference_Information},
	{WHorizontal_Coordinate_System_Definition,
		check_Horizontal_Coordinate_System_Definition},
	{WGeographic,
		check_Geographic},
	{WPlanar,
		check_Planar},
	{WMap_Projection,
		check_Map_Projection},
	{WAlbers_Conical_Equal_Area,
		check_Albers_Conical_Equal_Area},
	{WAzimuthal_Equidistant,
		check_Azimuthal_Equidistant},
	{WEquidistant_Conic,
		check_Equidistant_Conic},
	{WEquirectangular,
		check_Equirectangular},
	{WGeneral_Vertical_Near_sided_Perspective,
		check_General_Vertical_Near_sided_Perspective},
	{WGnomonic,
		check_Gnomonic},
	{WLambert_Azimuthal_Equal_Area,
		check_Lambert_Azimuthal_Equal_Area},
	{WLambert_Conformal_Conic,
		check_Lambert_Conformal_Conic},
	{WMercator,
		check_Mercator},
	{WModified_Stereographic_for_Alaska,
		check_Modified_Stereographic_for_Alaska},
	{WMiller_Cylindrical,
		check_Miller_Cylindrical},
	{WOblique_Mercator,
		check_Oblique_Mercator},
	{WOblique_Line_Azimuth,
		check_Oblique_Line_Azimuth},
	{WOblique_Line_Point,
		check_Oblique_Line_Point},
	{WOrthographic,
		check_Orthographic},
	{WPolar_Stereographic,
		check_Polar_Stereographic},
	{WPolyconic,
		check_Polyconic},
	{WRobinson,
		check_Robinson},
	{WSinusoidal,
		check_Sinusoidal},
	{WSpace_Oblique_Mercator_Landsat,
		check_Space_Oblique_Mercator_Landsat},
	{WStereographic,
		check_Stereographic},
	{WTransverse_Mercator,
		check_Transverse_Mercator},
	{Wvan_der_Grinten,
		check_van_der_Grinten},
	{WMap_Projection_Parameters,
		check_Map_Projection_Parameters},
	{WGrid_Coordinate_System,
		check_Grid_Coordinate_System},
	{WUniversal_Transverse_Mercator,
		check_Universal_Transverse_Mercator},
	{WUniversal_Polar_Stereographic,
		check_Universal_Polar_Stereographic},
	{WState_Plane_Coordinate_System,
		check_State_Plane_Coordinate_System},
	{WARC_Coordinate_System,
		check_ARC_Coordinate_System},
	{WLocal_Planar,
		check_Local_Planar},
	{WPlanar_Coordinate_Information,
		check_Planar_Coordinate_Information},
	{WCoordinate_Representation,
		check_Coordinate_Representation},
	{WDistance_and_Bearing_Representation,
		check_Distance_and_Bearing_Representation},
	{WLocal,
		check_Local},
	{WGeodetic_Model,
		check_Geodetic_Model},
	{WVertical_Coordinate_System_Definition,
		check_Vertical_Coordinate_System_Definition},
	{WAltitude_System_Definition,
		check_Altitude_System_Definition},
	{WDepth_System_Definition,
		check_Depth_System_Definition},
	{WEntity_and_Attribute_Information,
		check_Entity_and_Attribute_Information},
	{WDetailed_Description,
		check_Detailed_Description},
	{WEntity_Type,
		check_Entity_Type},
	{WAttribute,
		check_Attribute},
	{WAttribute_Domain_Values,
		check_Attribute_Domain_Values},
	{WEnumerated_Domain,
		check_Enumerated_Domain},
	{WRange_Domain,
		check_Range_Domain},
	{WCodeset_Domain,
		check_Codeset_Domain},
	{WAttribute_Value_Accuracy_Information,
		check_Attribute_Value_Accuracy_Information},
	{WOverview_Description,
		check_Overview_Description},
	{WDistribution_Information,
		check_Distribution_Information},
	{WDistributor,
		check_Distributor},
	{WStandard_Order_Process,
		check_Standard_Order_Process},
	{WDigital_Form,
		check_Digital_Form},
	{WDigital_Transfer_Information,
		check_Digital_Transfer_Information},
	{WDigital_Transfer_Option,
		check_Digital_Transfer_Option},
	{WOnline_Option,
		check_Online_Option},
	{WComputer_Contact_Information,
		check_Computer_Contact_Information},
	{WNetwork_Address,
		check_Network_Address},
	{WDialup_Instructions,
		check_Dialup_Instructions},
	{WOffline_Option,
		check_Offline_Option},
	{WRecording_Capacity,
		check_Recording_Capacity},
	{WAvailable_Time_Period,
		check_Available_Time_Period},
	{WMetadata_Reference_Information,
		check_Metadata_Reference_Information},
	{WMetadata_Contact,
		check_Metadata_Contact},
	{WMetadata_Security_Information,
		check_Metadata_Security_Information},
	{WMetadata_Extensions,
		check_Metadata_Extensions},
	{WCitation_Information,
		check_Citation_Information},
	{WSeries_Information,
		check_Series_Information},
	{WPublication_Information,
		check_Publication_Information},
	{WLarger_Work_Citation,
		check_Larger_Work_Citation},
	{WTime_Period_Information,
		check_Time_Period_Information},
	{WSingle_Date_Time,
		check_Single_Date_Time},
	{WMultiple_Dates_Times,
		check_Multiple_Dates_Times},
	{WRange_of_Dates_Times,
		check_Range_of_Dates_Times},
	{WContact_Information,
		check_Contact_Information},
	{WContact_Person_Primary,
		check_Contact_Person_Primary},
	{WContact_Organization_Primary,
		check_Contact_Organization_Primary},
	{WContact_Address,
		check_Contact_Address},
	/* Biological data profile */
	{WBounding_Altitudes,
		check_Bounding_Altitudes},
	{WTaxonomy,
	 	check_Taxonomy},
	{WKeywords_Taxon,
	 	check_Keywords_Taxon},
	{WTaxonomic_System,
	 	check_Taxonomic_System},
	{WClassification_System_Authority,
	 	check_Classification_System_Authority},
	{WClassification_System_Citation,
	 	check_Classification_System_Citation},
	{WIdentification_Reference,
	 	check_Identification_Reference},
	{WIdentifier,
	 	check_Identifier},
	{WVouchers,
	 	check_Vouchers},
	{WRepository,
	 	check_Repository},
	{WTaxonomic_Classification,
	 	check_Taxonomic_Classification},
	{WAnalytical_Tool,
	 	check_Analytical_Tool},
	{WTool_Access_Information,
	 	check_Tool_Access_Information},
	{WTool_Contact,
	 	check_Tool_Contact},
	{WTool_Citation,
	 	check_Tool_Citation},
	{WMethodology,
	 	check_Methodology},
	{WMethodology_Identifier,
	 	check_Methodology_Identifier},
	{WMethodology_Citation,
	 	check_Methodology_Citation},
	{WASCII_File_Structure,
	 	check_ASCII_File_Structure},
	{WData_Field,
	 	check_Data_Field},
	{WBeginning_Geologic_Age,
	 	check_Beginning_Geologic_Age},
	{WEnding_Geologic_Age,
	 	check_Ending_Geologic_Age},
	{WGeologic_Age,
	 	check_Geologic_Age},
	{WGeologic_Citation,
	 	check_Geologic_Citation},
	/* Shoreline profile */
	{WMarine_Weather_Condition,
		check_Marine_Weather_Condition},
	{WTidal_Information,
		check_Tidal_Information},
	{WTime_of_Tide,
		check_Time_of_Tide},
	/* Remotes-sensing profile */
	{WAcquisition_Information,
		check_Acquisition_Information},
	{WAerotriangulation_Reference,
		check_Aerotriangulation_Reference},
	{WAggregation_Information,
		check_Aggregation_Information},
	{WAggregation_Member_ID,
		check_Aggregation_Member_ID},
	{WAlgorithm_Change_Description,
		check_Algorithm_Change_Description},
	{WAlgorithm_Change_History,
		check_Algorithm_Change_History},
	{WAlgorithm_Change_Reference,
		check_Algorithm_Change_Reference},
	{WAlgorithm_Description,
		check_Algorithm_Description},
	{WAlgorithm_Identifiers,
		check_Algorithm_Identifiers},
	{WAlgorithm_Information,
		check_Algorithm_Information},
	{WAlgorithm_Peer_Review_Description,
		check_Algorithm_Peer_Review_Description},
	{WAlgorithm_Peer_Review_Information,
		check_Algorithm_Peer_Review_Information},
	{WAlgorithm_Peer_Review_Reference,
		check_Algorithm_Peer_Review_Reference},
	{WAlgorithm_Reference,
		check_Algorithm_Reference},
	{WAncillary_Dataset,
		check_Ancillary_Dataset},
	{WAncillary_Dataset_Identifier,
		check_Ancillary_Dataset_Identifier},
	{WAncillary_Description,
		check_Ancillary_Description},
	{WAncillary_Reference,
		check_Ancillary_Reference},
	{WAngle_Dependent_Distortion,
		check_Angle_Dependent_Distortion},
	{WAxes,
		check_Axes},
	{WBand_Identification,
		check_Band_Identification},
	{WCalibrated_Detector_Positions,
		check_Calibrated_Detector_Positions},
	{WComponent_Information,
		check_Component_Information},
	{WContainer_Packet_ID,
		check_Container_Packet_ID},
	{WControl_Point_Authority,
		check_Control_Point_Authority},
	{WControl_Point_Earth_Location,
		check_Control_Point_Earth_Location},
	{WControl_Point_Identification,
		check_Control_Point_Identification},
	{WControl_Point_Raster_Position,
		check_Control_Point_Raster_Position},
	{WCoordinate_Point,
		check_Coordinate_Point},
	{WCoordinate_System,
		check_Coordinate_System},
	{WCross_Track_Sweep,
		check_Cross_Track_Sweep},
	{WCross_Track_Zero,
		check_Cross_Track_Zero},
	{WData_Dictionary_Reference,
		check_Data_Dictionary_Reference},
	{WData_Scaling_Information,
		check_Data_Scaling_Information},
	{WDeveloping_Institution,
		check_Developing_Institution},
	{WDimension_Description,
		check_Dimension_Description},
	{WDimension_Properties,
		check_Dimension_Properties},
	{WDistance_Dependent_Distortion,
		check_Distance_Dependent_Distortion},
	{WDistortion,
		check_Distortion},
	{WDistortion_Type_Affine,
		check_Distortion_Type_Affine},
	{WDistortion_Type_Radial_Asymmetrical,
		check_Distortion_Type_Radial_Asymmetrical},
	{WDistortion_Type_Radial_Symmetrical,
		check_Distortion_Type_Radial_Symmetrical},
	{WDocumentation,
		check_Documentation},
	{WElevation_Sweep,
		check_Elevation_Sweep},
	{WElevation_Zero,
		check_Elevation_Zero},
	{WEphemeris,
		check_Ephemeris},
	{WExterior_Orientation_Accuracy,
		check_Exterior_Orientation_Accuracy},
	{WFiducial,
		check_Fiducial},
	{WFiducial_Center,
		check_Fiducial_Center},
	{WFilter_on_Camera,
		check_Filter_on_Camera},
	{WFlight_Protocol,
		check_Flight_Protocol},
	{WFrame_Area,
		check_Frame_Area},
	{WFrame_Camera,
		check_Frame_Camera},
	{WFrame_Geometric_Properties,
		check_Frame_Geometric_Properties},
	{WFrame_Hardware,
		check_Frame_Hardware},
	{WFrame_Operation,
		check_Frame_Operation},
	{WFrame_Optics,
		check_Frame_Optics},
	{WFrame_Radiometric_Calibration,
		check_Frame_Radiometric_Calibration},
	{WFrame_Radiometric_Properties,
		check_Frame_Radiometric_Properties},
	{WFrame_Spectral_Information,
		check_Frame_Spectral_Information},
	{WFrame_Spectral_Properties,
		check_Frame_Spectral_Properties},
	{WGeorectified_Raster,
		check_Georectified_Raster},
	{WGeoreferenceable_Raster,
		check_Georeferenceable_Raster},
	{WGeoreferencing_Description,
		check_Georeferencing_Description},
	{WGeoreferencing_Information,
		check_Georeferencing_Information},
	{WGrid_First_Element,
		check_Grid_First_Element},
	{WGrid_Orientation,
		check_Grid_Orientation},
	{WGround_Control_Point_Description,
		check_Ground_Control_Point_Description},
	{WGround_Control_Point_Information,
		check_Ground_Control_Point_Information},
	{WGround_Control_Point_Position,
		check_Ground_Control_Point_Position},
	{WID_Overlapping_Dataset,
		check_ID_Overlapping_Dataset},
	{WImage_Size,
		check_Image_Size},
	{WIndividual_Band_Identification,
		check_Individual_Band_Identification},
	{WInput_Dataset_Identifier,
		check_Input_Dataset_Identifier},
	{WInput_Level,
		check_Input_Level},
	{WInput_Reference,
		check_Input_Reference},
	{WInstantaneous_Field_of_View,
		check_Instantaneous_Field_of_View},
	{WInstrument_Description,
		check_Instrument_Description},
	{WInstrument_Information,
		check_Instrument_Information},
	{WInstrument_Reference,
		check_Instrument_Reference},
	{WInstrument_Specific_Georeferencing,
		check_Instrument_Specific_Georeferencing},
	{WKeplerian_Orbit,
		check_Keplerian_Orbit},
	{WLast_Calibration,
		check_Last_Calibration},
	{WLayer_Name,
		check_Layer_Name},
	{WLens,
		check_Lens},
	{WLocation_Information,
		check_Location_Information},
	{WMission_Completion,
		check_Mission_Completion},
	{WMission_History,
		check_Mission_History},
	{WMission_Information,
		check_Mission_Information},
	{WMission_Significant_Event,
		check_Mission_Significant_Event},
	{WMission_Start_Date,
		check_Mission_Start_Date},
	{WMultiple_Image_Alignment,
		check_Multiple_Image_Alignment},
	{WNadir,
		check_Nadir},
	{WNominal_Geostationary_Position,
		check_Nominal_Geostationary_Position},
	{WNominal_Spatial_Resolution,
		check_Nominal_Spatial_Resolution},
	{WNumber_of_Wavelength_Bands,
		check_Number_of_Wavelength_Bands},
	{WOrbit_Period,
		check_Orbit_Period},
	{WPerigee_Passage_Time,
		check_Perigee_Passage_Time},
	{WPhotographic_Resolving_Power,
		check_Photographic_Resolving_Power},
	{WPixel_Description,
		check_Pixel_Description},
	{WPixel_Resolution,
		check_Pixel_Resolution},
	{WPlatform_and_Instrument_Identification,
		check_Platform_and_Instrument_Identification},
	{WPlatform_and_Mission_Information,
		check_Platform_and_Mission_Information},
	{WPlatform_Information,
		check_Platform_Information},
	{WPlatform_Nominal_Altitude,
		check_Platform_Nominal_Altitude},
	{WPlatform_Nominal_Altitude_Units,
		check_Platform_Nominal_Altitude_Units},
	{WPlatform_Orbit,
		check_Platform_Orbit},
	{WPlatform_Start_Date,
		check_Platform_Start_Date},
	{WPolarization_Characteristics,
		check_Polarization_Characteristics},
	{WPolynomial_Denominator,
		check_Polynomial_Denominator},
	{WPolynomial_Function,
		check_Polynomial_Function},
	{WPolynomial_Numerator,
		check_Polynomial_Numerator},
	{WPositional_Information,
		check_Positional_Information},
	{WPrincipal_Point_of_Autocollimation,
		check_Principal_Point_of_Autocollimation},
	{WPrincipal_Point_of_Symmetry,
		check_Principal_Point_of_Symmetry},
	{WProcessing_Change_History,
		check_Processing_Change_History},
	{WProcessing_Documentation,
		check_Processing_Documentation},
	{WProcessing_Environment,
		check_Processing_Environment},
	{WProcessing_Identifiers,
		check_Processing_Identifiers},
	{WProcessing_Information,
		check_Processing_Information},
	{WProcessing_Input_Dataset,
		check_Processing_Input_Dataset},
	{WProcessing_Level,
		check_Processing_Level},
	{WProcessing_Level_Authority,
		check_Processing_Level_Authority},
	{WProcessing_Procedure,
		check_Processing_Procedure},
	{WProcessing_Run_History,
		check_Processing_Run_History},
	{WProcessing_Software,
		check_Processing_Software},
	{WProcessing_Software_Reference,
		check_Processing_Software_Reference},
	{WProfile_Properties,
		check_Profile_Properties},
	{WProfile_Sounding,
		check_Profile_Sounding},
	{WQuality_of_Principal_Point_of_Autocollimation,
		check_Quality_of_Principal_Point_of_Autocollimation},
	{WQuality_of_Principal_Point_of_Symmetry,
		check_Quality_of_Principal_Point_of_Symmetry},
	{WRadial_Symmetrical_Distortion_Polynomial,
		check_Radial_Symmetrical_Distortion_Polynomial},
	{WReferenced_Coordinate_System,
		check_Referenced_Coordinate_System},
	{WReferencing_Polynomial,
		check_Referencing_Polynomial},
	{WReseau,
		check_Reseau},
	{WResolution_Value_Set,
		check_Resolution_Value_Set},
	{WSample_Description_Units,
		check_Sample_Description_Units},
	{WSample_Profile_Units,
		check_Sample_Profile_Units},
	{WSample_Properties,
		check_Sample_Properties},
	{WScan,
		check_Scan},
	{WScan_Cross_Track_Properties,
		check_Scan_Cross_Track_Properties},
	{WScan_Elevation_Properties,
		check_Scan_Elevation_Properties},
	{WScan_Geometric_Properties,
		check_Scan_Geometric_Properties},
	{WScan_Radiometric_Properties,
		check_Scan_Radiometric_Properties},
	{WScan_Spectral_Properties,
		check_Scan_Spectral_Properties},
	{WScan_Start_Time,
		check_Scan_Start_Time},
	{WScan_Timing,
		check_Scan_Timing},
	{WScience_Paper,
		check_Science_Paper},
	{WSensor_Element_Location,
		check_Sensor_Element_Location},
	{WSensor_Grid,
		check_Sensor_Grid},
	{WSensor_Orientation,
		check_Sensor_Orientation},
	{WSensor_System,
		check_Sensor_System},
	{WSource_of_Element_Locations,
		check_Source_of_Element_Locations},
	{WSpectral_Information,
		check_Spectral_Information},
	{WSwath_Track_Information,
		check_Swath_Track_Information},
	{WThematic_Layer_Identification,
		check_Thematic_Layer_Identification},
	{WUsers_Guide,
		check_Users_Guide},
	{WWavelength_Band_Properties,
		check_Wavelength_Band_Properties},
	{WWorldwide_Reference_System,
		check_Worldwide_Reference_System},
	{Wunknown,check_unknown}
	};
static int rule_table_length = 0;
static int compare (const void *e1, const void *e2) {
	struct rule *p = (struct rule *) e1;
	struct rule *q = (struct rule *) e2;
	return (p->key - q->key);
	}
static void init_rule_table (void) {
	if (rule_table_length == 0) {
		int i;
		for (i=0; rule_table[i].key != Wunknown; i++);
		rule_table_length = i;
		qsort (rule_table,rule_table_length,sizeof(struct rule),compare);
		}
	}
/*----------------------------------------------------------------------*/
static int check_item (struct item *p) {
	struct rule r,*pr;
	if (rule_table_length == 0) init_rule_table();
	r.key = p->key;
	pr = (struct rule *) bsearch (&r,rule_table,rule_table_length,sizeof(struct rule),compare);
	if (pr) return (pr->check(p));
	else
		if (p->key == Wblank) return (0);
		else
			if (p->key == Wunknown) return (check_unknown (p));
			else
				if (is_extension (p->key)) return (check_extension (p));
				else
					return (check_scalar_children (p));
	}
void check_syntax (struct item *p) {
	if (bio_profile == -1)
		if (profile_name)
			if (memicmp (profile_name,"bio",3) == 0) bio_profile = 1;
			else bio_profile = 0;
		else bio_profile = 0;
	if (rs_profile == -1)
		if (profile_name)
			if (memicmp (profile_name,"rs",2) == 0) rs_profile = 1;
			else rs_profile = 0;
		else rs_profile = 0;
	if (sh_profile == -1)
		if (profile_name)
			if (memicmp (profile_name,"sh",2) == 0) sh_profile = 1;
			else sh_profile = 0;
		else sh_profile = 0;
	while (p) {
		check_item (p);
		if (p->child) check_syntax (p->child);
		p = p->next;
		}
	}
void summarize_errors (FILE *fp) {
	int total = errors.unrecognized +
				errors.misplaced +
				errors.too_many +
				errors.missing +
				errors.empty +
				errors.bad_value;
	if (!fp) return;
	if (total == 0) fprintf (fp,"No errors\n");
	else {
		int q = 0;
		fprintf (fp,"%d errors: ",total);
		if (errors.unrecognized) {
			fprintf (fp,"%d unrecognized",errors.unrecognized);
			q = 1;
			}
		if (errors.misplaced) {
			if (q) fprintf (fp,", ");
			fprintf (fp,"%d misplaced",errors.misplaced);
			q = 1;
			}
		if (errors.too_many) {
			if (q) fprintf (fp,", ");
			fprintf (fp,"%d too_many",errors.too_many);
			q = 1;
			}
		if (errors.missing) {
			if (q) fprintf (fp,", ");
			fprintf (fp,"%d missing",errors.missing);
			q = 1;
			}
		if (errors.empty) {
			if (q) fprintf (fp,", ");
			fprintf (fp,"%d empty",errors.empty);
			q = 1;
			}
		if (errors.bad_value) {
			if (q) fprintf (fp,", ");
			fprintf (fp,"%d bad_value",errors.bad_value);
			q = 1;
			}
		fprintf (fp,"\n");
		}
	}
/*----------------------------------------------------------------------*\
\*----------------------------------------------------------------------*/