Exemplo n.º 1
0
int EXP_LVL9 CSdtcomp (	Const char *inpt,
						Const char *outp,
						int flags,
						Const char *elipsoid,
						int (*err_func)(char *mesg)
					  )
{
	int st;
	int test;
	int demo;
	int warn;
	int dummy;
	int cancel;
	int err_cnt;
	int crypt;

	size_t rdCnt;
	size_t wrCnt;

	char *cp;
	csFILE *inStrm;
	csFILE *elStrm;
	csFILE *outStrm;
	struct cs_DtcmpT_ *tp;
	struct cs_DtTypeT_ *typPtr;

	cs_magic_t magic;

	char err_seg [18];
	char buff [128];
	char err_msg [128];
	char last_name [48];

	__ALIGNMENT__2		/* For some versions of Sun compiler. */
	struct cs_Dtdef_ dtdef;

	crypt = ((flags & cs_CMPLR_CRYPT) != 0);
	demo  = ((flags & cs_CMPLR_DEMO) != 0);
	test  = ((flags & cs_CMPLR_TEST) != 0);
	warn  = ((flags & cs_CMPLR_WARN) != 0);

	/* Open the source file. */
	inStrm = CS_fopen (inpt,_STRM_TXTRD);
	if (inStrm == NULL)
	{
		sprintf (err_msg,"Couldn't open %s for input.",inpt);
		cancel = (*err_func)(err_msg);
		return (1);
	}

	/* Open the output file and write the magic number.  BINRW mode
	   creates a new file with read and write access. */
	outStrm = CS_fopen (outp,_STRM_BINRW);
	if (outStrm == NULL)
	{
		sprintf (err_msg,"Couldn't open %s for output.",outp);
		cancel = (*err_func)(err_msg);
		CS_fclose (inStrm);
		return (1);
	}
	if (demo) magic = cs_DTDEF_MAGIC;
	else      magic = cs_DTDEF_MAGIC;
	CS_bswap (&magic,"l");
	wrCnt = CS_fwrite ((char *)&magic,1,sizeof (magic),outStrm);
	if (wrCnt != sizeof (magic))
	{
		sprintf (err_msg,"Failure detected during write to %s.",outp);
		cancel = (*err_func)(err_msg);  
		CS_fclose (outStrm);
		CS_remove (outp);										/*lint !e534 */
		CS_fclose (inStrm);
		return (1);
	}

	/* If we have been given an ellipsoid file name, we open it now. */
	if (elipsoid != NULL && *elipsoid != '\0')
	{
		elStrm = CS_fopen (elipsoid,_STRM_BINRD);
		if (elStrm == NULL)
		{
			sprintf (err_msg,"Couldn't open %s as an Ellipsoid Dictionary.",elipsoid);
			cancel = (*err_func)(err_msg);
			CS_fclose (inStrm);
			return (1);
		}
		rdCnt = CS_fread (&magic,1,sizeof (magic),elStrm);
		CS_bswap (&magic,"l");
		if (rdCnt != sizeof (magic) ||
			(demo && magic != cs_ELDEF_MAGIC) ||
			(!demo && magic != cs_ELDEF_MAGIC))
		{
			sprintf (err_msg,"%s is not an Elipsoid Dictionary file.",elipsoid);
			cancel = (*err_func)(err_msg);
			CS_fclose (inStrm);
			CS_fclose (elStrm);
			return (1);
		}
	}
	else
	{
		elStrm = NULL;
	}

	/* Process each line in the source file. */
	line_nbr = 0;
	err_cnt = 0;
	cancel = FALSE;
	memset (&dtdef,'\0',sizeof (dtdef));
	dtdef.delta_X = no_value;
	dtdef.delta_Y = no_value;
	dtdef.delta_Z = no_value;
	dtdef.rot_X = no_value;
	dtdef.rot_Y = no_value;
	dtdef.rot_Z = no_value;
	dtdef.bwscale = no_value;
	dtdef.to84_via = cs_DTCTYP_NONE;
	while (CS_fgets (buff,sizeof (buff),inStrm) != NULL)
	{
		if (cancel)
		{
			CS_fclose (inStrm);
			CS_fclose (outStrm);
			if (elStrm != NULL) CS_fclose (elStrm);
			CS_remove (outp);										/*lint !e534 */
			return (err_cnt);
		}
		line_nbr += 1;

		/* Ignore comments and blank lines. */
		CS_trim (buff);
		if (buff [0] == '#' || buff [0] == '\0')
		{
			continue;
		}
		cp = buff;
		while ((cp = strchr (cp,'#')) != NULL)
		{
			if (*(cp + 1) != '#' &&
			    *(cp - 1) != '\\')
			{
				*cp = '\0';
				break;
			}
		}

		/* Run the line through the table parser.  We
		   see what type of line we have. */
		cp = buff;
		tp = (struct cs_DtcmpT_ *)CS_tpars (&cp,cs_DtcmpT,sizeof (struct cs_DtcmpT_));

		if (tp == NULL)
		{
			CS_stncp (err_seg,buff,sizeof (err_seg));
			sprintf (err_msg,"Invalid keyword (%s) on line %d.",err_seg,line_nbr);
			cancel = (*err_func)(err_msg);
			err_cnt += 1;
			dtdef.key_nm [0] = '\0';
			continue;
		}

		/* Here when we have a valid line. Cp points to the first
		   character after the colon. */
		CS_trim (cp);
		switch (tp->type) {
		case DT_NAME:

			/* Here each time we encounter a new datum
			   name.  We see if there is an existing
			   datum which must be written. */
			if (dtdef.key_nm [0] != '\0' &&		/* Skip 1st one. */
				(test || CS_stricmp (dtdef.group,"TEST")))
			{
				st = CSdtdefwr (outStrm,&dtdef,crypt,warn,elStrm,err_func);
				if (st >= 0) err_cnt += st;
				else
				{
					cancel = TRUE;
					err_cnt += -st;
				}
				
			}

			/* Prepare for the next coordinate system. */
			memset (&dtdef,'\0',sizeof (dtdef));
			dtdef.delta_X = no_value;
			dtdef.delta_Y = no_value;
			dtdef.delta_Z = no_value;
			dtdef.rot_X = no_value;
			dtdef.rot_Y = no_value;
			dtdef.rot_Z = no_value;
			dtdef.bwscale = no_value;
			dtdef.protect = FALSE;
			dtdef.to84_via = cs_DTCTYP_NONE;

			CS_stncp (dtdef.key_nm,cp,sizeof (dtdef.key_nm));
			st = CS_nampp (dtdef.key_nm);
			if (st != 0)
			{
				sprintf (err_msg,"%s is not a valid datum key name; line %d.",cp,line_nbr);
				cancel = (*err_func)(err_msg);
				err_cnt += 1;
			}
			break;

		case DESC_NM:
			if (strlen (cp) >= sizeof (dtdef.name) && warn)
			{
				sprintf (err_msg,"Warning: Description for %s on line %d is too long.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			CS_stncp (dtdef.name,cp,sizeof (dtdef.name));
			break;

		case ELLP_NM:
			CS_stncp (dtdef.ell_knm,cp,sizeof (dtdef.ell_knm));
			break;

		case LOCATION:
			if (strlen (cp) >= sizeof (dtdef.locatn) && warn)
			{
				sprintf (err_msg,"Warning: Country list for %s on line %d is too long.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			CS_stncp (dtdef.locatn,cp,sizeof (dtdef.locatn));
			break;

		case COUNTRY:
			if (strlen (cp) >= sizeof (dtdef.cntry_st) && warn)
			{
				sprintf (err_msg,"Warning: Country list for %s on line %d is too long.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			CS_stncp (dtdef.cntry_st,cp,sizeof (dtdef.cntry_st));
			break;

		case SOURCE:
			if (strlen (cp) >= sizeof (dtdef.source) && warn)
			{
				sprintf (err_msg,"Warning: Source for %s on line %d is too long.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			CS_stncp (dtdef.source,cp,sizeof (dtdef.source));
			break;

		case DELTA_X:
			dtdef.delta_X = atof (cp);
			if (warn && (fabs (dtdef.delta_X) > 2000.0))
			{
				sprintf (err_msg,"Warning: Delta X value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			break;

		case DELTA_Y:
			dtdef.delta_Y = atof (cp);
			if (warn && (fabs (dtdef.delta_Y) > 2000.0))
			{
				sprintf (err_msg,"Warning: Delta Y value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			break;

		case DELTA_Z:
			dtdef.delta_Z = atof (cp);
			if (warn && (fabs (dtdef.delta_Z) > 2000.0))
			{
				sprintf (err_msg,"Warning: Delta Z value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			break;

		case ROT_X:
			dtdef.rot_X = atof (cp);
			if (warn && (fabs (dtdef.rot_X) >= 60.0))
			{
				sprintf (err_msg,"Warning: X Rotation value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}		
			break;

		case ROT_Y:
			dtdef.rot_Y = atof (cp);
			if (warn && (fabs (dtdef.rot_Y) >= 60.0))
			{
				sprintf (err_msg,"Warning: Y Rotation value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}		
			break;

		case ROT_Z:
			dtdef.rot_Z = atof (cp);
			if (warn	 && (fabs (dtdef.rot_Z) >= 60.0))
			{
				sprintf (err_msg,"Warning: Y Rotation value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}		
			break;

		case BWSCALE:
			dtdef.bwscale = atof (cp);
			if (warn && (fabs (dtdef.bwscale) >= 25.0))
			{
				sprintf (err_msg,"Warning: Bursa Wolfe scale value for %s on line %d is suspicious.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}		
			break;

		case USE:
			dtdef.to84_via = cs_DTCTYP_NONE;
			for (typPtr = cs_DtTypeT;typPtr->type != cs_DTCTYP_NONE;typPtr += 1)
			{
				if (!CS_stricmp (cp,typPtr->label))
				{
					dtdef.to84_via = typPtr->type;
					break;
				}
			}
			if (dtdef.to84_via == cs_DTCTYP_NONE)
			{
				sprintf (err_msg,"Invalid 'USE' specification detected on line %d.",line_nbr);
				cancel = (*err_func)(err_msg);
				err_cnt += 1;
			}
			break;

		case GROUP:
			if (strlen (cp) >= sizeof (dtdef.group) && warn)
			{
				sprintf (err_msg,"Warning: Group for %s on line %d is too long.",dtdef.key_nm,line_nbr);
				cancel = (*err_func)(err_msg);
			}
			CS_stncp (dtdef.group,cp,sizeof (dtdef.group));
			break;

		case EPSG_NBR:
			dtdef.epsgNbr = atoi (cp);
			break;

		default:
			sprintf (err_msg,"Software problem detected at line %d in module %s.",__LINE__,__FILE__);
			(void)(*err_func)(err_msg);
			cancel = TRUE;
			break;
		}

		/* On to the next input line. */
	}
	CS_fclose (inStrm);

	/* Write out the last coordinate system if not in error. */
	if (dtdef.key_nm [0] != '\0' && (test || CS_stricmp (dtdef.group,"TEST")))
	{
		st = CSdtdefwr (outStrm,&dtdef,crypt,warn,elStrm,err_func);
		if (st >= 0) err_cnt += st;
		else
		{
			cancel = TRUE;
			err_cnt += -st;
		}
	}
	if (elStrm != NULL) CS_fclose (elStrm);
	if (cancel)
	{
		CS_fclose (outStrm);
		CS_remove (outp);										/*lint !e534 */
		return (err_cnt);
	}

	/* Sort the output file. */
	CS_fseek (outStrm,(long)sizeof (magic),SEEK_SET);
	CS_ips (outStrm,sizeof (dtdef),0L,(CMPFUNC_CAST)CS_dtcmp);		/*lint !e534 */

	/* Verify that there are no duplicates. */
	CS_fseek (outStrm,(long)sizeof (magic),0);
	CS_dtrd (outStrm,&dtdef,&dummy);								/*lint !e534 */
	CS_stncp (last_name,dtdef.key_nm,sizeof (last_name));
	while (!cancel && CS_dtrd (outStrm,&dtdef,&dummy) != 0)
	{
		if (!CS_stricmp (dtdef.key_nm,last_name))
		{
			sprintf (err_msg,"Datum key name %s appears more than once.",last_name);
			cancel = (*err_func)(err_msg);
			err_cnt += 1;
		}
		CS_stncp (last_name,dtdef.key_nm,sizeof (last_name));
	}
	CS_fclose (outStrm);

	/* Remove the output file if there were errors. */
	if (err_cnt != 0)
	{
		CS_remove (outp);										/*lint !e534 */
	}
	return (err_cnt);
}
Exemplo n.º 2
0
/* This function creates a binary version of the Jgd2k file if it doesn't
   exist, or if the date on the binary file is older than or equal to
   that of the primary text file.  Note, that this function uses the path name
   in the provided object, and modifies it to point to the binary file which
   is then created if necessary.

   This function is implemented as records in the ASCII text file may not be
   of fixed length, there can be a million of them, and there is no guarantee
   that the records in the text file will be properly sorted.  The binary
   file enables random access to the data file for decent performance without
   eating up 12MB of RAM. */
int CSmakeBinaryJgd2kFile (struct cs_Japan_* thisPtr)
{
	extern char cs_ExtsepC;
	extern char csErrnam [];
	extern double cs_Zero;

	int st;
	cs_Time_ aTime, bTime;

	size_t wrCnt;

	char *cp1, *cp2;
	csFILE *aStrm, *bStrm;

	long32_t tempL;
	long32_t dblFrmt;
	ulong32_t meshCode;

	double lngTmp, latTmp;
	double mesh_ll [2];

	char lineBufr [128];
	char binaryPath [MAXPATH];

	struct csJgd2kGridRecord_ gridRec;
	struct csJgd2kGridRecord_ minRec;
	struct csJgd2kGridRecord_ maxRec;

	/* We will write two records to the file with bogus mesh codes.  These
	   records will carry the minimum (i.e. southwest) longitude and latitude
	   and the maximum (i.e. northeast) longitude and latitude of the data in
	   the file.  This is an attempt to make the file format something which
	   does not inherently imply applicability to Japanese geography.
	   
	   The bogus mesh codes were devised such that the min/max will be the
	   first two records in the file, thus easily accessible.  For these two
	   special records, the deltaLng and DeltaLat fields carry absolute 
	   longitude and latitude in seconds. */
	minRec.meshCode = 1UL;
	minRec.deltaLat = (long32_t)( 90 * 3600);
	minRec.deltaLng = (long32_t)(180 * 3600);
	maxRec.meshCode = 2UL;
	maxRec.deltaLat = (long32_t)( -90 * 3600);
	maxRec.deltaLng = (long32_t)(-180 * 3600);

	/* Prepare for an error of some sort. */
	aStrm = bStrm = NULL;
	lngTmp = latTmp = cs_Zero;

	/* Manufacture the name of the binary file. */
	CS_stncp (binaryPath,thisPtr->filePath,sizeof (binaryPath));
	cp1 = strrchr (binaryPath,cs_ExtsepC);
	if (cp1 == NULL) 
	{
		CS_stncp (csErrnam,thisPtr->filePath,MAXPATH);
		CS_erpt (cs_DTC_FILE);
		goto error;
	}
	CS_stcpy ((cp1 + 1),"_par");

	bTime = CS_fileModTime (binaryPath);
	/* Build a new binary file only if it doesn't exist yet. */
	if (0 == bTime)
	{
		/* Determine the last modification time for the two files.  Zero time value
		   means the file does not exist. */
		aTime = CS_fileModTime (thisPtr->filePath);
		if (aTime == 0)
		{
			/* The indicated source file does not exist, not uncommon among the
			   error conditions possible. */
			CS_stncp (csErrnam,thisPtr->filePath,MAXPATH);
			CS_erpt (cs_DTC_FILE);
			goto error;
		}

		/* Here to create a, possibly new, binary version of the Jgd2k file,
		   typically named "TKY2JGD.par".  To follow the general design
		   theme, we assume there can be several files, and there is no fixed
		   name for any of the files.  At this particular point, of course,
		   we're only dealing with one file, the file whose name was provided.
		   
		   We write one csJgd2kGridRecord structure	for each line of text that
		   we read.   Of course, we need to skip the first two lines (usually)
		   in the file as they are of the mets-data variety. */
		aStrm = CS_fopen (thisPtr->filePath,_STRM_TXTRD);
		if (aStrm == NULL)
		{
			/* This could happen if the file exists, but for some reason we
			   are denied permission to read the file.*/
			CS_stncp (csErrnam,thisPtr->filePath,MAXPATH);
			CS_erpt (cs_DTC_FILE);
			goto error;
		}

		/* The mode of the following open will truncate any existing file, and
		   create a new binary file if necessary. */
		bStrm = CS_fopen (binaryPath,_STRM_BINWR);
		if (bStrm == NULL)
		{
			CS_stncp (csErrnam,thisPtr->filePath,MAXPATH);
			CS_erpt (cs_FL_OPEN);
			goto error;
		}

		/* If we're still here, we can copy the file, converting it to binary
		   form as we do.  While doing so, we'll convert each mesh code to
		   latitude and longitude form and accumulate an estimate of the
		   coverage of the file. */
		while (CS_fgets (lineBufr,sizeof (lineBufr),aStrm) != NULL)
		{
			/* Parse the information is in a record. */
			meshCode = CS_strtoul (lineBufr,&cp1,10);
			
			/* The first two lines of the files we've seen contain labels and
			   other data.  We use the following to filter these out.  This may
			   need to be improved should new versions of the file include some
			   other form of header. */
			if (meshCode == 0 || meshCode == 0xffffffffUL) continue;
			
			/* Accumulate a bounding box (or minimum and maximum as us old
			   farts used to call it) so we have a rough estimate of the
			   coverage of the file. */
			CSjpnMeshCodeToLl (mesh_ll,meshCode);			
			if (mesh_ll [LNG] < -180.0 || mesh_ll [LNG] > 180.0 ||
				mesh_ll [LAT] <  -90.0 || mesh_ll [LAT] > 90.0)
			{
				/* Bogus mesh code.  We could consider this to be meta-data
				   that slipped through the code immediately above, or that
				   the file is invalid.  For now, we consider it to be the
				   latter:  The file is not a validly formatted data file. */
				CS_erpt (cs_INV_FILE);
				goto error;
			}
			tempL = (long32_t)(mesh_ll [LNG] * 3600 + 0.01);
			if (tempL < minRec.deltaLng) minRec.deltaLng = tempL; 
			if (tempL > maxRec.deltaLng) maxRec.deltaLng = tempL; 
			tempL = (long32_t)(mesh_ll [LAT] * 3600 + 0.01);
			if (tempL < minRec.deltaLat) minRec.deltaLat = tempL; 
			if (tempL > maxRec.deltaLat) maxRec.deltaLat = tempL; 

			/* Separate the two data values.  We avoid strtod as it is
			   locale dependent and the data file is not. */			
			while (*cp1 == ' ') cp1++;
			cp2 = strchr (cp1,' ');
			*cp2++ = '\0';
			while (*cp2 == ' ') cp2++;

			dblFrmt = CSatof (&latTmp,cp1,'.',',',':');
			if (dblFrmt >= 0)
			{
				dblFrmt = CSatof (&lngTmp,cp2,'.',',',':');
			}
			if (dblFrmt < 0)
			{
				CS_erpt (cs_INV_FILE);
				goto error;
			}

			/* Build a new record in the array. */
			gridRec.meshCode = meshCode;
			
			/* NTO 30 Oct 2008, Trac # 13
			   The following was necessiatated by Linux.  It appears that on the
			   Linux platform (or some of them, anyway), the rounding of doubles
			   (especially negative ones) is different than what you will see on
			   WIN32 platforms.  Which one is correct is of no concern to me,
			   only that they are different. */
			latTmp *= 100000.0;
			latTmp += (latTmp >= 0.0) ? 0.1 : -0.1;
			lngTmp *= 100000.0;
			lngTmp += (lngTmp >= 0.0) ? 0.1 : -0.1;
			/* End Linux fix, Trac #13 */

			gridRec.deltaLat = (long32_t)(latTmp);
			gridRec.deltaLng = (long32_t)(lngTmp);
			wrCnt = CS_fwrite (&gridRec,sizeof (gridRec),1,bStrm);
			if (wrCnt != 1)
			{
				CS_erpt (cs_IOERR);
				goto error;
			}
		}

		/* If we're still here, we write minRec and maxRec to the file so we
		   have a record of the coverage of the file. */
		wrCnt =	CS_fwrite (&minRec,sizeof (minRec),1,bStrm);
		if (wrCnt != 1)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}
		wrCnt = CS_fwrite (&maxRec,sizeof (maxRec),1,bStrm);
		if (wrCnt != 1)
		{
			CS_erpt (cs_IOERR);
			goto error;
		}

		/* Close the file streams.  We're going to open the binary file back
		   up immediately, but have found this redundant close and open to
		   produce more reliable operation cross platforms. */
		CS_fclose (aStrm);
		aStrm = NULL;
		st = CS_fclose (bStrm);
		bStrm = NULL;

		/* OK, we need to sort the file by mesh codes so we can use a binary
		   search algorithm on it.  This should also cause the min/max records
		   to end up being the first two records in the file. This is very
		   convenient.

		   Note that the position of any one record in the file with respect
		   to any other record in the file is immaterial in this file format.
		   Thus, we can reorder the file any way we want to.  The original
		   code was written in the Windows 95 era, so the current scheme may
		   look rather dumb.  Nevertheless, it works and I have no motivation
		   to fix it. */
		bStrm = CS_fopen (binaryPath,_STRM_BINUP);
		if (bStrm == NULL)
		{
			CS_stncp (csErrnam,binaryPath,MAXPATH);
			CS_erpt (cs_FL_OPEN);
			goto error;
		}
		st = CS_ips (bStrm,sizeof (gridRec),0L,(CMPFUNC_CAST)CScompareJgd2kGridRecord);
		CS_fclose (bStrm);
		bStrm = NULL;
		if (st < 0) goto error;
		if (st == 1) st = csGRIDI_ST_OK;	/* CS_ips returns 1 for success, for historical reasons. */

		/* OK, now we're really done. */
	}

	/* If all that was done successfully, we change the name of
	   the file and return success. */
	CS_stncp (thisPtr->filePath,binaryPath,sizeof (thisPtr->filePath));
	return csGRIDI_ST_OK;
error:
	if (aStrm != NULL)
	{
		CS_fclose (aStrm);
		aStrm = NULL;
	}
	if (bStrm != NULL)
	{
		CS_fclose (bStrm);
		bStrm = NULL;
	}
	return csGRIDI_ST_SYSTEM;
}
Exemplo n.º 3
0
Arquivo: CStest6.c Projeto: asir6/Colt
int CStest6 (int verbose,int crypt)
{
	int st;
	int cnt;
	int flag;
	int my_crypt;

	csFILE *csStrm;
	struct tst_lst_ *tp;

	char last_name [48];

	__ALIGNMENT__1			/* Required by some Sun compilers. */
	struct cs_Csdef_ cs_def;

	printf ("Testing sort and binary search functions.\n");

	/* This test sorts the Coordinate System Dictionary, the
	   largest of the three dictionaries, into reverse order.
	   Then does some CS_bins calls.  Then resorts back into
	   normal order.  This is a resaonable good exercise of
	   the sort function which normally sorts files with a
	   single entry out of order. */

	if (verbose)
	{
		printf ("Sorting Coordinate System Dictionary into reverse order.\n");
	}
	csStrm = CS_csopn (_STRM_BINUP);
	if (csStrm == NULL)
	{
		printf ("Coordinate System Dictionary open failed.  Is it write protected?.\n");
		return 1;
	}

	/* NOTE: CS_csopn leaves the file positioned after
	   the magic number.  CS_ips always starts sorting
	   at the current file position. */

	CS_ips (csStrm,sizeof (struct cs_Csdef_),-1L,(CMPFUNC_CAST)CStest6cmp);

	/* The dictionary should now be in reverse order.  We
	   check the order now.  CS_ips is supposed to return
	   with the file position where it was when we started. */

	if (verbose)
	{
		printf ("Checking reverse order of Coordinate System Dictionary.\n");
	}
	cnt = 0;
	st = CS_csrd (csStrm,&cs_def,&my_crypt);
	if (st == 0)
	{
		printf ("CS_ips hosed the Coordinate System Dictionary.\n");
		CS_fclose (csStrm);
		return (1);
	}
	CS_stncp (last_name,cs_def.key_nm,sizeof (last_name));
	while (CS_csrd (csStrm,&cs_def,&my_crypt))
	{
		cnt += 1;
		if (verbose && (cnt % 10) == 0) putchar ('.');
		st = CS_stricmp (last_name,cs_def.key_nm);
		if (st < 0)
		{
			printf ("\nSort did not sort entire file correctly!!!\n");
			CS_fclose (csStrm);
			return (1);
		}
		else if (st == 0)
		{
			printf ("\nSort left duplicate entries when sorting entire file!!!\n");
			CS_fclose (csStrm);
			return (1);
		}
	}
	if (verbose) printf (" OK.\n");

	/* If we are still here, the sort worked correctly.
	   Use the sort_tst list as a list of names to binary
	   search on.  It includes the normal first and last;
	   which should now be the last and the first. */

	tp = sort_tst;
	while (tp->name [0] != '\0')
	{
		if (verbose)
		{
			printf ("Searching for %s in reversed CS Dictionary.",tp->name);
		}
		CS_stncp (cs_def.key_nm,tp->name,sizeof (cs_def.key_nm));
		flag = CS_bins (csStrm,(long32_t)sizeof (cs_magic_t),(long32_t)0,sizeof (cs_def),
				(char *)&cs_def,(CMPFUNC_CAST)CStest6cmp);
		if (flag <= 0)
		{
			printf ("CS_bins failed on file in reverse order!!!\n");
			CS_fclose (csStrm);
			return (1);
		}
		if (verbose) printf (" OK.\n");
		tp += 1;
	}

	/* OK, return the file back to normal sorted order. */

	if (verbose)
	{
		printf ("Sorting Coordinate System Dictionary back to normal order.\n");
	}
	CS_fseek (csStrm,(long)sizeof (cs_magic_t),SEEK_SET);
	CS_ips (csStrm,sizeof (struct cs_Csdef_),-1L,(CMPFUNC_CAST)CS_cscmp);

	/* One more time, check that the order is correct. */

	if (verbose)
	{
		printf ("Checking Coordinate System Dictionary normal sorted order.\n");
	}
	cnt = 0;
	st = CS_csrd (csStrm,&cs_def,&my_crypt);
	if (st == 0)
	{
		printf ("CS_ips hosed the Coordinate System Dictionary.\n");
		CS_fclose (csStrm);
		return (1);
	}
	CS_stncp (last_name,cs_def.key_nm,sizeof (last_name));
	while (CS_csrd (csStrm,&cs_def,&my_crypt))
	{
		cnt += 1;
		if (verbose && (cnt % 10) == 0) putchar ('.');
		st = CS_stricmp (last_name,cs_def.key_nm);
		if (st > 0)
		{
			printf ("Sort did not sort entire file correctly!!!\n");
			CS_fclose (csStrm);
			return (1);
		}
		else if (st == 0)
		{
			printf ("Sort left duplicate entries when sorting entire file!!!\n");
			CS_fclose (csStrm);
			return (1);
		}
	}
	if (verbose) printf (" OK.\n");

	/* OK, if we are still here, we passed the test. */

	CS_csDictCls (csStrm);
	return (0);
}
Exemplo n.º 4
0
int EXP_LVL3 CS_dtupd (struct cs_Dtdef_ *dtdef,int crypt)
{
    extern char csErrnam [];
    extern short cs_Protect;
    extern char cs_Unique;

    short cs_time;

    int st;
    int flag;
    int dummy;

    csFILE *strm;

    long fpos;

    char *cp;

    __ALIGNMENT__1		/* For some versions of Sun compiler. */

    struct cs_Dtdef_ my_dtdef;

    /* Capture the current time. For our purposes here, time is
       the number of days since (approx) January 1, 1990. If this
       record does get written, the protect field will indicate
       that it has changed. */

    cs_time = (short)((CS_time ((cs_Time_ *)0) - 630720000L) / 86400L);
    if (dtdef->protect >= 0)
    {
        dtdef->protect = cs_time;
    }

    /* Prepare for a possible error. */
    strm = NULL;

    /* Adjust the name and make sure it is all upper
       case.  By convention, datum names are case
       insensitive. */
    st = CS_nampp (dtdef->key_nm);
    if (st != 0) goto error;

    /* Open up the Datum Dictionary and verify its magic number. */
    strm = CS_dtopn (_STRM_BINUP);
    if (strm == NULL)
    {
        goto error;
    }

    /* See if we have a datum with this name already. */
    flag = CS_bins (strm,(long)sizeof (cs_magic_t),0L,sizeof (*dtdef),
                    (char *)dtdef,(CMPFUNC_CAST)CS_dtcmp);
    if (flag < 0) goto error;
    if (flag)
    {
        /* Here when the datum already exists. See if we are
           allowed to change this definition. */
        if (cs_Protect >= 0)
        {
            /* Distribution protection is enabled. */
            fpos = CS_ftell (strm);
            if (fpos < 0L)
            {
                CS_erpt (cs_IOERR);
                goto error;
            }
            st = CS_dtrd (strm,&my_dtdef,&dummy);
            if (st == 0) CS_erpt (cs_INV_FILE);
            if (st <= 0)
            {
                goto error;
            }

            if (my_dtdef.protect == 1)
            {
                CS_stncp (csErrnam,dtdef->key_nm,MAXPATH);
                CS_erpt (cs_DT_PROT);
                goto error;
            }
            if (cs_Protect > 0 && my_dtdef.protect > 0)
            {
                if (my_dtdef.protect < (cs_time - cs_Protect))		/*lint !e644 */
                {
                    CS_stncp (csErrnam,dtdef->key_nm,MAXPATH);
                    CS_erpt (cs_DT_UPROT);
                    goto error;
                }
            }
            st  = CS_fseek (strm,fpos,SEEK_SET);
            if (st < 0L)
            {
                CS_erpt (cs_IOERR);
                goto error;
            }
        }

        /* If we're still here, it's OK to update this definition. */
        if (CS_dtwr (strm,dtdef,crypt))
        {
            goto error;
        }
    }
    else
    {
        /* Here if the datum definition doesn't exist.  We
           have to add it. If cs_Unique is not zero, we
           require that a cs_Unique character be present
           in the key name before we'll allow it to be
           written. */
        if (cs_Unique != '\0')
        {
            cp = strchr (dtdef->key_nm,cs_Unique);
            if (cp == NULL)
            {
                csErrnam [0] = cs_Unique;
                csErrnam [1] = '\0';
                CS_erpt (cs_UNIQUE);
                goto error;
            }
        }

        /* Now we can add it. Write to the end of the file, and then
           sort the file. */
        st = CS_fseek (strm,0L,SEEK_END);
        if (st != 0)
        {
            CS_erpt (cs_IOERR);
            goto error;
        }
        if (CS_dtwr (strm,dtdef,crypt))
        {
            goto error;
        }

        /* Sort the file into proper order, thereby
           moving the new datum to its proper place
           in the dictionary. */
        st = CS_fseek (strm,(long)sizeof (cs_magic_t),SEEK_SET);
        if (st != 0)
        {
            CS_erpt (cs_IOERR);
            goto error;
        }
        st = CS_ips (strm,sizeof (*dtdef),0L,(CMPFUNC_CAST)CS_dtcmp);
        if (st < 0) goto error;
    }

    /* The Datum Dictionary has been updated. */
    CS_dtDictCls (strm);
    return (flag);

error:
    if (strm != NULL) CS_dtDictCls (strm);
    return (-1);
}