/****************************************************************************/ /* */ /* IAGA_merge.c */ /* */ /****************************************************************************/ /****************************************************************************/ /* This program merges two IAGA-format files into a single IAGA file. */ /* The ordering of stations in the resulting file is controlled by an */ /* optional parameter. */ /* */ /* Usage: */ /* IAGA_merge [-o] IAGAFile1 ... IAGAFileN > NewIAGAFile */ /* [-o StationList] Defines how the stations are ordered in the */ /* final data file. e.g. 'SOR MAS KEV'. */ /* Don't include stations which are not mentioned. */ /* If missing then stations from IAGAFile1 are */ /* written first, stations from IAGAFileN last */ /* If data for some station appears in more than */ /* one file then data from the first encountered */ /* file will be written, the rest are neglected. */ /* IAGAFile1 Name of first IAGA-format file. */ /* IAGAFileN Name of last IAGA-format file. */ /* NewIAGAFile Name of new IAGA-format file. */ /* */ /* Here the files IAGAFile1 ... IAGAFileN must contain data for exactly the */ /* same times. */ /****************************************************************************/ /****************************************************************************/ /* Lasse Hakkinen */ /* Finnish Meteorological Institute */ /* Geophysical Research Division */ /* P.O.Box 503 */ /* FIN-00101, Helsinki, Finland */ /* e-mail: Lasse.Hakkinen@fmi.fi */ /* phone : (+358)-9-19294634 */ /* fax : (+358)-9-19294603 */ /* */ /* version 1.06 11.01.2020 */ /****************************************************************************/ /****************************************************************************/ /* Version history: */ /* */ /* 1.06 11.01.2020 Date strings must be YYYYMMDD (four digits for year) */ /* Replaced StrToSecs -> StrToSecsC and */ /* SecsToStr -> SecsToStrC. */ /* 1.05 08.09.2000 Modified the program so that also the case where only */ /* one input file is given is legal. In this case the data */ /* is simply copied. */ /* 1.04 09.09.1999 Fixed a Y2K bug in NewTime.h file which resulted in */ /* incorrect year in date strings if year >= 2000. */ /* 1.03 28.5.1999 */ /* - Allowed the possibility that data for some station exists in more */ /* than one file. */ /* 1.02 26.5.1999 */ /* - Increased the length of StationStr to 255 in order to eliminate */ /* possible overflows if full pathnames are used. */ /* 1.01 26.2.1996 */ /* - Added the possibility to merge more than two files. */ /* - Cosmetic change in handling the usage text. */ /* */ /* 1.0 10.10.1995 First official release */ /****************************************************************************/ #include #include #include #include "Usage.h" #include "NewTime.h" #define OK 0 /* Return value for successfull completion */ #define FAIL 1 /* Return value for failed operation */ #define MaxFileCount 32 /* Maximum number of IAGA files to be merged */ #define MaxStationCount 1000 /* Maximum total count of stations in IAGA files*/ #define IAGA_DateCentury 48 #define IAGA_DateYear 50 #define IAGA_SampleStep 60 char *version = "1.06"; char *date = "11.01.2020"; #define HeaderLineCount 6 #define UsageLineCount 9 long IAGABlockSize; /* Size of IAGA block = 1440, 1441 or 1442 */ char *HeaderText[HeaderLineCount] = { "**************************************************************************", "This program merges two or more IAGA format files into a single IAGA file.", "All files must contain data for the same time interval. If data for some ", "station exists in more than one file then data from the first encountered ", "file will be written. ", "**************************************************************************", }; char *UsageText[UsageLineCount] = { " [-o] IAGAFile1 ... IAGAFileN > NewIAGAFile", " [-o StationList] Defines how the stations are ordered in the ", " final data file. e.g. 'SOR MAS KEV'. ", " Don't include stations which are not mentioned.", " If missing then stations from IAGAFile1 are ", " written first, stations from IAGAFileN last. ", " IAGAFile1 Name of first IAGA-format file. ", " IAGAFileN Name of last IAGA-format file. ", " NewIAGAFile Name of new IAGA-format file. ", }; /*--------------------------------------------------------------------------*/ /* Check if the IAGA block contains newlines or carriage returns. */ /*--------------------------------------------------------------------------*/ long GetIAGABlockSize(FILE *FilePtr) { long Size = 1440; char Buffer[1442]; /* Buffer for reading one IAGA block */ fread(Buffer,1442,1,FilePtr); /* Read the first block and little more */ if (Buffer[1441] < '0') Size = 1442; else if (Buffer[1440] < '0') Size = 1441; rewind(FilePtr); return (Size); } /*--------------------------------------------------------------------------*/ /* Get the starting time of the 1440 character IAGA block */ /*--------------------------------------------------------------------------*/ long GetIAGABlockTime(char *Buffer) { // return (StrToSecs(Buffer+IAGA_DateYear,10)); return (StrToSecsC(Buffer+IAGA_DateCentury,12)); } /*--------------------------------------------------------------------------*/ /* Get the sampling rate of the 1440 character IAGA block */ /*--------------------------------------------------------------------------*/ long GetIAGABlockSampleRate(char *Buffer) { char Step_str[3] = "??"; strncpy(Step_str,Buffer+IAGA_SampleStep,2); return (atol(Step_str)); } /*--------------------------------------------------------------------------*/ /* Count the number of stations in the file FilePtr. */ /*--------------------------------------------------------------------------*/ long GetStationCount(FILE *FilePtr) { long Count; char Station[4]; /* Name of the first station */ char Buffer[1442]; /* Buffer for reading one IAGA block */ fread(Buffer,IAGABlockSize,1,FilePtr); /* Read the first block */ strncpy(Station,Buffer+12,3); /* Set the station ID */ Station[3] = '\0'; Count = 0; do { Count++; fread(Buffer,IAGABlockSize,1,FilePtr); } while (strncmp(Station,Buffer+12,3)); rewind(FilePtr); return (Count); } /*--------------------------------------------------------------------------*/ /* Read one IAGA block from given file. */ /*--------------------------------------------------------------------------*/ long ReadBlock(FILE *FilePtr,char *Buffer) { long count; count = fread(Buffer,IAGABlockSize,1,FilePtr); if (count == 0) return (0); else return (1); } /*--------------------------------------------------------------------------*/ /* Write one IAGA block into stdout. */ /*--------------------------------------------------------------------------*/ long WriteBlock(char *Buffer) { return(fwrite(Buffer,IAGABlockSize,1,stdout)); } /*--------------------------------------------------------------------------*/ /* The main procedure */ /*--------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { long i,j; /* Dummy indices */ long params; long BlockNbr; long status; long FileCount = 0; /* Number of IAGA files */ long StationCount[MaxFileCount]; /* Number of stations in IAGA files */ long TotalStationCount; /* Total number of stations */ long written; /* Flag to indicate multiple */ /* occurrences of the same station */ char StationStr[255] = ""; /* List of stations */ char *Block[MaxStationCount]; /* Pointers to IAGA data blocks */ char *FileName[MaxFileCount]; /* Names of the data files */ FILE *IAGAFile[MaxFileCount]; /* File pointers to IAGA files */ Time_sec BlockTime; long SampleRate; /*==========================*/ /* Analyse the command line */ /*==========================*/ if (argc == 1) { /* No arguments, show the usage text */ PrintUsage(argv[0],0,HeaderLineCount,UsageLineCount); return OK; } for (params = 1; params < argc; params++) { if (*argv[params] != '-') { FileName[FileCount++] = argv[params]; } else { switch (*(argv[params]+1)) { case 'o' : strcpy(StationStr,argv[++params]); break; default : fprintf(stderr,"\n### %s: \"%s\" is not an option.\n\n", argv[0], argv[params]); PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount); return FAIL; break; } } } /*====================================*/ /* Check the values of the parameters */ /*====================================*/ if (FileCount < 1) { PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount); return FAIL; } if (FileCount > MaxFileCount) { fprintf(stderr,"### Too many files : %d\n",FileCount); fprintf(stderr,"### Maximum allowed: %d\n",MaxFileCount); return FAIL; } /*============================*/ /* Try to open all the files. */ /*============================*/ for (i=0;i MaxStationCount) { fprintf(stderr,"### Too many stations : %d\n",TotalStationCount); fprintf(stderr,"### Maximum allowed : %d\n",MaxStationCount); return FAIL; } /*==========================================*/ /* Allocate one IAGA block for each station */ /*==========================================*/ for (i=0;i 0) { for (i=0;i