File c2rfx241.c of Package rnxcmp
/***********************************************************************/
/* program name : C2RFX241 */
/* */
/* recover the RINEX file from buggy Compact RINEX file created by */
/* RNX2CRX ver 2.4.1 or 2.4.1a which contain bugs */
/* Created by HATANAKA, Yuki / Geographical Survey Institute, Japan*/
/* */
/* ver. */
/* 0.1.1 2004.7.16 created by HATANAKA, Y. */
/* based on CRX2RNX ver. 2.4.2 */
/* */
/***********************************************************************/
#undef UNIX
#undef DOS
#undef VMS
#undef SUN41
/*** Choose the system by defining one of UNIX/DOS/VMS. ***/
#define UNIX
/*** Uncomment next line, in the case of SunOS4.1.x. ***/
/*** #define SUN41 ***/
/* Maybe, you don't have to change the lines from here. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#ifdef UNIX
#define VERSION "ver.u.0.1"
#define SEPARATOR '/'
#define CR_CHECK(p,q) if( (p = strrchr(q,'\r')) != NULL && *(p+1) == '\0' ) *p = '\0'
#else
#ifdef DOS
#define VERSION "ver.d.0.1"
#define SEPARATOR '\\'
#define CR_CHECK(p,q) /*** define to NULL ***/
#else
#define VERSION "ver.v.0.1"
#define SEPARATOR ']'
#define CR_CHECK(p,q) if( (p = strrchr(q,'\r')) != NULL && *(p+1) == '\0' ) *p = '\0'
#endif
#endif
#define CHOP_BLANK(q,p) while(*--p == ' ' && p>q);*++p = '\0'
/*** "sprintf" on SunOS4.1.x does not follow the ANSI standard (returned value is ***/
/*** not the number of output characters). For these OS, "my_sprintf" defined below ***/
/*** is used instead of sprintf. ***/
#ifdef SUN41
#include <stdarg.h>
#define SPRINTF my_sprintf
int my_sprintf(char *p, char *format, ...){
va_list ap;
va_start(ap,format);
vsprintf(p,format,ap);
va_end(ap);
return strlen(p);
}
#else
#define SPRINTF sprintf
#endif
#define CRX_VERSION "1.0"
#define PROGNAME "C2RFX241"
#define MAXSAT 100 /* Maximum number of satellites */
#define MAXTYPE 20 /* Maximum number of data types */
#define MAX_DIFF_ORDER 5 /* Muximum order of difference to be dealt with */
#define MAXSAT3 MAXSAT*3 /* MAXSAT*3 */
#define MAXTYPE2 MAXTYPE*2+2 /* MAXTYPE2 = MAXTYPE * 2 + 2 */
#define MAXLEN 512 /* Muximum length of one line */
#define MAXBUF MAXLEN*MAXSAT /* Muximum size of output buffer */
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#ifdef VMS
#define EXIT_FAILURE 3
#else
#define EXIT_FAILURE 1
#endif
#endif
typedef struct clock_format{
int i[MAX_DIFF_ORDER+1];
long f[MAX_DIFF_ORDER+1];
} clock_format;
typedef struct data_format{
double r[MAX_DIFF_ORDER+1];
int order;
int arc_order;
} data_format;
FILE *ifp;
clock_format clk1,clk0;
data_format y1[MAXSAT][MAXTYPE],y0[MAXSAT][MAXTYPE];
char flag1[MAXSAT][MAXTYPE2],flag[MAXSAT][MAXTYPE2];
int nsat,ntype,clk_order = 0, clk_arc_order = 0;
long nl_count=0;
char out_buff[MAXBUF],*p_buff;
void fileopen(int argc, char *argv[]);
void header();
void put_event_data(char *dline);
void process_clock(char *dline);
void set_sat_table(char *p_new, char *p_old, int nsat1, int *sattbl);
void data(int *sattbl);
void repair(char *s, char *ds);
void getdiff(data_format *y, data_format *y0, int i0, char *dflag);
void putfield(data_format *y, char *flag);
void read_clock(char *p ,int *yi, long *yf);
void print_clock(int yi, long yf);
char *read_chk_line(char *line);
void error_exit(int error_no, char *string);
/*---------------------------------------------------------------------*/
main(int argc, char *argv[]){
/********************************************************************/
/* sattbl : previous column on which the satellites are set */
/* new satellites are set to -1 */
/* date of previous epoch are set to line1, nsat1, */
/********************************************************************/
static char line[MAXLEN]="", sat_lst_old[MAXSAT3];
static int nsat1 = 0, n;
char dline[MAXLEN],*p;
int event,sattbl[MAXSAT],i,j;
if ( DBL_EPSILON > 1.e-15 ) error_exit(17,line);
fileopen(argc,argv);
header();
while( fgets(dline,MAXLEN,stdin) != NULL){
nl_count++;
p = strchr(dline,'\n'); if( *(p-1) == '\r' )p--; *p = '\0';
if(dline[0] == '&'){
dline[0] = ' ';
while(atoi(&dline[26]) > 0){
put_event_data(dline);
nl_count++;
if(fgets(dline,MAXLEN,stdin) == NULL) return EXIT_SUCCESS; /*** exit program successfully ***/
p = strchr(dline,'\n'); if( *(p-1) == '\r' )p--; *p = '\0';
if(dline[0] != '&') error_exit(9,dline);
dline[0] = ' ';
}
line[0] = '\0'; /**** initialize arc for epoch data ***/
nsat1 = 0; /**** initialize the all satellite arcs ****/
}else if( dline[0] == '\032' ){
return EXIT_SUCCESS; /** DOS EOF **/
}
/**** read, repair the line ****/
repair(line,dline);
p = strchr(line,'\0');
CHOP_BLANK(line,p);
CR_CHECK(p,line);
set_sat_table(&line[29],sat_lst_old,nsat1,sattbl); /**** set satellite table ****/
process_clock(dline);
/*************************************/
/**** print the recovered line(s) ****/
/*************************************/
p_buff = out_buff;
if(clk_order >= 0){
p_buff += SPRINTF(p_buff,"%-68.68s",line);
print_clock(clk1.i[clk_order],clk1.f[clk_order]);
}else{
p_buff += SPRINTF(p_buff,"%.68s\n",line);
}
for(p = &line[68],n=nsat-12; n>0; n-=12,p+=36) p_buff += SPRINTF(p_buff,"%32.32s%.36s\n"," ",p);
data(sattbl);
*p_buff = '\0'; printf("%s",out_buff);
/*********************************************************/
/**** save current epoch for processing of next epoch ****/
/*********************************************************/
nsat1 = nsat;
clk0 = clk1;
strncpy(sat_lst_old,&line[32],nsat*3);
for(i=0;i<nsat;i++){
strncpy(flag1[i],flag[i],ntype*2);
for(j=0;j<ntype;j++) y0[i][j] = y1[i][j];
}
}
return EXIT_SUCCESS;
}
/*---------------------------------------------------------------------*/
void fileopen(int argc, char *argv[]){
char *p,*basename,*infile,outfile[MAXLEN],*progname;
int nfile=0, force=0, help=0;
int nfout = 0; /*** =0 default output file name ***/
/*** =1 specified name (VAX) or standaed output (UNIX,DOS) ***/
progname = argv[0];
argc--;argv++;
for(;argc>0;argc--,argv++){
if((*argv)[0] != '-'){
infile = *argv;
nfile++;
#ifdef VMS
}else if((*argv)[1] == 'o'){
argc--;argv++;
if(argc==0) help = 1;
nfout++;
strcpy(outfile,*argv);
#else
}else if((*argv)[1] == '\0'){
nfout = 1;
#endif
}else if((*argv)[1] == 'f'){
force = 1;
}else if((*argv)[1] == 'h'){
help = 1;
}else{
help = 1;
}
}
#ifdef VMS
if(help == 1 || nfile != 1 || nfout > 1) error_exit(1,progname);
#else
if(help == 1 || nfile > 1 || nfile < 0) error_exit(2,progname);
if(nfile == 0) return; /*** stdin & stdout will be used ***/
#endif
/***********************/
/*** open input file ***/
/***********************/
basename = infile;
if( (p=strrchr(infile,SEPARATOR)) != NULL ) basename = p+1;
#ifdef VMS
if( (p=strchr(basename,';')) != NULL ) *p = '\0';
#endif
p=strstr(basename,".");
if(p == NULL || (*(p+3) != 'D' && *(p+3) != 'd') || *(p+4) != '\0') error_exit(3,p);
if((ifp = fopen(infile,"r")) == NULL) error_exit(4,infile);
/************************/
/*** open output file ***/
/************************/
if(nfout == 0) {
strcpy(outfile,basename);
p=strstr(outfile,".");
*(p+3) = 'o';
#ifdef VMS
}
{
#endif
if((freopen(outfile,"r",stdout)) != NULL && force == 0){
fprintf(stderr,"The file %s already exists. Overwrite?(n)",outfile);
if(getchar() != 'y') exit(EXIT_SUCCESS);
}
#ifdef VMS
freopen(outfile,"w",stdout,"rfm=var","rat=cr");
#else
freopen(outfile,"w",stdout);
#endif
}
fclose(ifp);
freopen(infile,"r",stdin);
}
/*---------------------------------------------------------------------*/
void header(){
int end = 1;
char line[MAXLEN],*p,crx_ver;
nl_count++;
if( fgets(line,MAXLEN,stdin) == NULL ) error_exit(5,CRX_VERSION);
if( strncmp(&line[0],CRX_VERSION,3) != 0 ||
strncmp(&line[60],"CRINEX VERS / TYPE",19) != 0 ) error_exit(5,CRX_VERSION);
nl_count++;
if( fgets(line,MAXLEN,stdin) == NULL ) error_exit(8,line);
if(strncmp(&line[0],"RNX2CRX ver.",12) != 0 ||
strncmp(&line[13],".2.4.1",6) != 0)error_exit(18,line);
while(end != 0){
p=read_chk_line(line);
while(*--p == ' ' && p>line);*++p = '\0';
printf("%s\n",line);
if(strncmp(&line[60],"# / TYPES OF OBSERV",19) == 0){
ntype=atoi(line);
if(ntype > MAXTYPE) error_exit(16,line);
}
end = strncmp(&line[60],"END OF HEADER",13);
}
}
/*---------------------------------------------------------------------*/
void process_clock(char *dline){
/********************************/
/**** process clock offset ****/
/********************************/
int i,j;
char *p,*ps;
read_chk_line(dline);
p = dline;
if(*p == '\0'){
clk_order = -1;
}else{
/****************************/
/**** arc initialization ****/
/****************************/
if(*(p+1) == '&') {
/* sscanf(p,"%d&",&clk_arc_order); */
clk_arc_order=atoi(p);
if(clk_arc_order > MAX_DIFF_ORDER) error_exit(7,dline);
clk_order = -1;
p += 2;
}
/****************************************/
/**** recover the clock offset value ****/
/****************************************/
read_clock(p,clk1.i,clk1.f);
if(clk_order < clk_arc_order){
clk_order++;
for(i=0,j=1 ; i<clk_order ; i++,j++){
clk1.i[j] = clk1.i[i]+clk0.i[i];
clk1.f[j] = clk1.f[i]+clk0.f[i];
clk1.i[j] += clk1.f[j]/100000000; /*** avoid overflow of y1.f ***/
clk1.f[j] %= 100000000;
}
}else{
for(i=0,j=1 ; i<clk_order ; i++,j++){
clk1.i[j] = clk1.i[i]+clk0.i[j];
clk1.f[j] = clk1.f[i]+clk0.f[j];
clk1.i[j] += clk1.f[j]/100000000;
clk1.f[j] %= 100000000;
}
}
}
}
/*---------------------------------------------------------------------*/
void put_event_data(char *dline){
/***********************************************************************/
/* - Put event data for one event. */
/* - This function is called when the event flag > 1. */
/***********************************************************************/
int i,n;
char *p;
printf("%s\n",dline);
if( strlen(dline) > 29 ){
if(*(dline+28) == '6'){ /*** for cycle slip records ***/
nsat=atoi(&dline[29]);
n=nsat*((ntype+4)/5)+((nsat-1)/12);
}else{
n=atoi(&dline[29]);
}
for(i=0;i<n;i++){
p=read_chk_line(dline);
CHOP_BLANK(dline,p);
printf("%s\n",dline);
if(strncmp(&dline[60],"# / TYPES OF OBSERV",19) == 0) {
ntype=atoi(&dline[0]);
if(ntype > MAXTYPE) error_exit(16,dline);
}
}
}
}
/*---------------------------------------------------------------------*/
void set_sat_table(char *p_new, char *p_old, int nsat1, int *sattbl){
/***********************************************************************/
/* - Read number of satellites (nsat) */
/* - Compare the satellite list at the epoch (*p_new) and that at the */
/* previous epoch(*p_old), and make index (*sattbl) for the */
/* corresponding order of the satellites. */
/* *sattbl is set to -1 for new satellites. */
/***********************************************************************/
int i,j;
char *ps;
nsat=atoi(p_new);
if(nsat > MAXSAT) error_exit(6,p_new);
for (i=0,p_new+=3 ; i<nsat ; i++,p_new+=3){
*sattbl = -1;
for(j=0,ps=p_old ; j<nsat1 ; j++,ps+=3){
if(strncmp(p_new,ps,3) == 0){
*sattbl = j;
break;
}
}
sattbl++;
}
}
/*---------------------------------------------------------------------*/
void data(int *sattbl){
/********************************************************************/
/* Functions */
/* (1) compose the original data from 3rd order difference */
/* (2) repair the flags */
/* sattbl : previous column on which the satellites are set */
/* new satellites are set to -1 */
/* i : integer part of the data */
/* f : fractioal part of the data */
/* ( y = i*1000 + f ) */
/* date of previous epoch are set to y0 */
/********************************************************************/
data_format *py1,*py0;
int i,j,k,k1,*i0;
char dflag[MAXTYPE2];
for(i=0,i0=sattbl ; i<nsat ; i++,i0++){
getdiff(y1[i],y0[*i0],*i0,dflag); /**** read data ****/
/*********************************/
/**** repair the data frags ****/
/*********************************/
if(*i0 < 0){
sprintf(flag[i],"%-*s",ntype*2,dflag);
}else{
strncpy(flag[i],flag1[*i0],ntype*2);
repair(flag[i],dflag);
}
/****************************************/
/**** recover the date, and output ****/
/****************************************/
for(j=0,py1=y1[i] ; j<ntype ; j++,py1++){
if(py1->arc_order >= 0){
py0 = &(y0[*i0][j]);
if(py1->order < py1->arc_order){
(py1->order)++;
for(k=0,k1=1; k<py1->order; k++,k1++){
py1->r[k1] = py1->r[k] + py0->r[k];
}
}else{
for(k=0,k1=1; k<py1->order; k++,k1++){
py1->r[k1] = py1->r[k] + py0->r[k1];
}
}
putfield(py1,&flag[i][j*2]);
}else{
p_buff += SPRINTF(p_buff," ");
flag[i][j*2] = flag[i][j*2+1] = ' ';
}
if((j+1)%5 == 0 || (j+1) == ntype){
while(*--p_buff == ' '); p_buff++; /*** cut spaces ***/
*p_buff++ = '\n';
}
}
}
}
/*---------------------------------------------------------------------*/
void repair(char *s, char *ds){
for(; *s != '\0' && *ds != '\0' ; ds++,s++){
if(*ds != ' '){
if(*ds == '&')
*s = ' ';
else
*s = *ds;
}
}
if(*ds != '\0') {
sprintf(s,"%s",ds);
for(; *s != '\0' ;s++) {
if(*s == '&') *s = ' ';
}
}
}
/*---------------------------------------------------------------------*/
void getdiff(data_format *y, data_format *y0, int i0, char *dflag){
int j,lmax;
char *s,*s1,*s2,line[MAXLEN];
/******************************************/
/**** separate the fields with "\0" ****/
/******************************************/
read_chk_line(line);
for(j=0,s=line; j<ntype; s++){
if(*s == '\0') {
j++;
*(s+1) = '\0';
}else if(*s == ' '){
j++;
*s = '\0';
}
}
strcpy(dflag,s);
/************************************/
/* read the differenced data */
/************************************/
s1=line;
for(j=0;j<ntype;j++){
if(*s1 == '\0'){
y->arc_order = -1; /**** arc_order < 0 means that the feild if blank ****/
y->order = -1;
s1++;
}else{
if(*(s1+1) == '&'){ /**** arc initialization ****/
y->order = -1;
/* sscanf(s1,"%d&",&(y->arc_order)); */
y->arc_order = atoi(s1);
s1 += 2;
if(y->arc_order > MAX_DIFF_ORDER) error_exit(7,line);
}else if(i0 < 0){
error_exit(11,line);
}else if(y0->arc_order < 0){
error_exit(12,line);
}else{
y->order = y0->order;
y->arc_order = y0->arc_order;
}
y->r[0] = atof(s1);
s1=strchr(s1,'\0')+1;
}
y++;
y0++;
}
}
/*---------------------------------------------------------------------*/
void putfield(data_format *y, char *flag){
int i;
char *si;
si=p_buff;
i=y->order;
SPRINTF(p_buff,"%13.0f ",y->r[i]);
/*** devision by 1000 ***/
si[13]=si[12];
si[12]=si[11];
si[11]=si[10];
si[10]='.';
/*** relocation of sign and padding 0 ***/
if(si[11]=='-'){
si[9]='-';
si[11]='0';
}else if(si[11]==' '){
si[11]='0';
if(si[12]=='-'){
si[9]='-';
si[12]='0';
}else if(si[12]==' '){
si[12]='0';
}
}
si[14]=*flag;si[15]=*(flag+1);
p_buff+=16;
}
/*---------------------------------------------------------------------*/
void print_clock(int yi, long yf){
char buff[5];
if(yi<0 && yf>0){
yi++ ; yf -= 100000000;
}else if(yi>0 && yf<0){
yi-- ; yf += 100000000;
}
sprintf(buff,"%3d.",yi);
buff[3]=buff[2];
buff[2]='.';
if(yi==0){
if(yf <0)
buff[1]='-';
else
buff[1]=' ';
}
p_buff += SPRINTF(p_buff,"%4s%08.8ld\n",buff,labs(yf));
}
/*---------------------------------------------------------------------*/
void read_clock(char *p ,int *yi, long *yf){
/**************************/
/**** read clock diffs ****/
/**************************/
char *s=p,*p1=p;
if(*s == '-') p1++;
while(*s != '\0') s++;
if((s-p1) < 9 ){ /** s-p1 == strlen(p1) ***/
*yi = 0;
*yf = atol(p);
}else{
s -= 8;
*yf = atol(s);
*s = '\0';
*yi = atol(p);
if(*yi < 0) *yf = -*yf;
}
}
/*---------------------------------------------------------------------*/
char *read_chk_line(char *line){
char *p;
nl_count++;
if( fgets(line,MAXLEN,stdin) == NULL ) error_exit(8,line);
if( (p = strchr(line,'\n')) == NULL) {
if( fgetc(stdin) == EOF ) { /** check if EOF is there **/
error_exit(8,line);
}else{
error_exit(13,line);
}
}
if( *(p-1) == '\r' )p--; /*** check DOS CR/LF ***/
*p = '\0';
return p;
}
/*---------------------------------------------------------------------*/
void error_exit(int error_no, char *string){
if(error_no == 1 ){
fprintf(stderr,"Usage: %s input file [-o output file] [-f] [-h]\n",string);
fprintf(stderr," output file name can be omitted if input file name is *.[yy]d\n");
}else if(error_no == 2 ){
fprintf(stderr,"Usage: %s [file] [-] [-f] [-h]\n",string);
fprintf(stderr," stdin and stdout are used if input file name is not given.\n");
}
if(error_no == 1 || error_no == 2){
fprintf(stderr," - : output to stdout\n");
fprintf(stderr," -f : force overwrite of output file\n");
fprintf(stderr," -h : display help message\n");
fprintf(stderr," exit code = %d (success)\n",EXIT_SUCCESS);
fprintf(stderr," = %d (error)\n",EXIT_FAILURE);
fprintf(stderr," [version : %s]\n",VERSION);
exit(EXIT_FAILURE);
}
if(error_no == 3 ){
fprintf(stderr,"ERROR : invalid file name %s\n",string);
fprintf(stderr,"The file name should be such as [xxxxxxxx.xxd].\n");
#ifdef VMS
fprintf(stderr," if you don't specify output file name\n");
#else
fprintf(stderr,"If the file name doesn't obey this naming convention, use this program as a filter. \n");
fprintf(stderr," for example) cat file.in | %s - > file.out\n",PROGNAME);
#endif
exit(EXIT_FAILURE);
}
if(error_no == 4 ){
fprintf(stderr,"ERROR : can't open %s\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 5 ){
fprintf(stderr,"ERROR : version of the format is not valid.\n");
fprintf(stderr," This software can deal with only ver.%s.\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 6 ){
fprintf(stderr,"ERROR at line %ld : exceed maximum number of satellites(%d)\n",MAXSAT,nl_count);
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 7 ){
fprintf(stderr,"ERROR at line %ld : exceed maximum order of difference (%d)\n",MAX_DIFF_ORDER,nl_count);
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 8 ){
fprintf(stderr,"ERROR : The file seems to be trancated in the middle.\n");
fprintf(stderr," The conversion is interrupted after reading the line %ld :\n",nl_count);
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 9 ){
fprintf(stderr,"ERROR at line %ld : The arc should be initialized, but not.\n",nl_count);
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 11){
fprintf(stderr,"ERROR at line %ld : New satellite, but data arc is not initialized.\n",nl_count);
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 12){
fprintf(stderr,"ERROR at line %ld : The data feild in previous epoch is blank, but the arc is not initialized.\n",nl_count);
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 13){
fprintf(stderr,"ERROR at line %ld : null character is found in the line or the line is too long (>%d) at line.\n",nl_count,MAXLEN);
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
if(error_no == 16 ){
fprintf(stderr,"Number of datea type exceeds limitation (%d):\n%s\n",MAXTYPE,string);
exit(EXIT_FAILURE);
}
if(error_no == 17 ){
fprintf(stderr,"ERROR: DBL_EPSILON = %e on this machine architecture.\n",DBL_EPSILON);
fprintf(stderr," (DBL_EPSILON should be smaller than 1.0e-15)\n");
exit(EXIT_FAILURE);
}
if(error_no == 18 ){
fprintf(stderr,"ERROR: CRINEX PROG must be RNX2CRX ver.?.2.4.1(a).\n");
fprintf(stderr," start>%s<end\n",string);
exit(EXIT_FAILURE);
}
}