bufr2synop 0.24.0
build_bufrdeco_tables.c
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2013-2022 by Guillermo Ballester Valor *
3 * gbv@ogimet.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20/*!
21 \file build_bufrdeco_tables.c
22 \brief This file includes the code for build_bufrdeco_tables binary
23
24 \a build_bufrdeco_tables is the tool to convert original BUFR files from ECMWF package
25 and WMO machine readable files into the format used by the decode library \a bufrdeco
26 included in this package. \a bufrdeco uses BUFR table files in csv format like WMO but supressing
27 some fields from original WMO files.
28
29 Because of WMO has not released csv table files for versions prior to 18, it is needed to build
30 them since version 13 using ECMWF table files. Version 13 is backward compatible with prior versions.
31
32 Following the ECMWF way to set the CodeFlag tables as C Tables, the original WMO CodeFlag Tables are named
33 as C tables. Original WMO C tables with descriptors operators an A tables are no needed in this package.
34*/
35
36#include "bufrdeco.h"
37
38// To use package config.h
39#ifndef CONFIG_H
40# include "config.h"
41# define CONFIG_H
42#endif
43
44const char SELF[] = "build_bufrdeco_tables";
45char INPUT_FILE[256];
46char TABLE_TYPE[8];
48int A_FIELDS[8] = {1,2,-1,-1,-1,-1,-1,-1}; // fields selected for table A type
49int B_FIELDS[8] = {3,4,5,6,7,8,9,-1}; // fields selected for table B type
50int C_FIELDS[8] = {1,3,4,5,6,7,-1,-1}; // Fields selected for CodeFlag (C) type.
51int D_FIELDS[8] = {3,6,4,7,-1,-1,-1,-1}; // Fields selected for D type (Common sequences)
52
53int B_FIELDS_2[8] = {2,3,4,5,6,7,8,-1}; // fields selected for table B type for 38 > version >= 35
54int C_FIELDS_2[8] = {0,2,3,4,5,6,-1,-1}; // Fields selected for CodeFlag (C) type for 38 > version >= 35.
55int D_FIELDS_2[8] = {2,5,3,6,-1,-1,-1,-1}; // Fields selected for D type (Common sequences) for 38 > version >= 35
56
57int B_FIELDS_3[8] = {2,3,11,4,5,6,7,-1}; // fields selected for table B type for version >= 38
58int C_FIELDS_3[8] = {0,2,3,4,5,6,-1,-1}; // Fields selected for CodeFlag (C) type for version >= 38.
59int D_FIELDS_3[8] = {2,5,3,6,-1,-1,-1,-1}; // Fields selected for D type (Common sequences) for version >= 38
60
61
62
63
64void print_usage ( void )
65{
66 printf ( "%s %s\n", SELF, PACKAGE_VERSION );
67 printf ( "Usage: \n" );
68 printf ( "%s -i input_file -t table_type [-e[-h]\n" , SELF );
69 printf ( " -h Print this help\n" );
70 printf ( " -e Source ECMWF, default WMO\n" );
71 printf ( " -t table_type. (A = TableA, B = TableB, C = CodeFlag, D = TableD)\n" );
72 printf ( " -2 Version 35, 36 or 37\n");
73 printf ( " -3 Version 38 or newest\n");
74}
75
76
77int main ( int argc, char *argv[] )
78{
79 int iopt, i, *fs;
80 FILE *f;
81 char lin[CSV_MAXL], caux[CSV_MAXL], caux2[32];
82 char *tk[16], *c;
83 int nt;
84 uint32_t ix = 0;
85 long int il;
86 struct bufr_descriptor desc;
87
88 // Read args
89 TABLE_TYPE[0] = 0;
90 INPUT_FILE[0] = 0;
91 IS_WMO = 1;
92 while ( ( iopt = getopt ( argc, argv, "hei:t:23" ) ) !=-1 )
93 switch ( iopt )
94 {
95 case 'i':
96 if ( strlen ( optarg ) < 256 )
97 strcpy ( INPUT_FILE, optarg );
98 break;
99 case 't':
100 if ( strlen ( optarg ) < 8 )
101 strcpy ( TABLE_TYPE, optarg );
102 break;
103 case '2':
104 IS_WMO = 2;
105 break;
106 case '3':
107 IS_WMO = 3;
108 break;
109 case 'e':
110 case 'E':
111 IS_WMO = 0;
112 break;
113 case 'h':
114 default:
115 print_usage();
116 exit ( EXIT_SUCCESS );
117 }
118
119 if ( TABLE_TYPE[0] == 0 )
120 {
121 fprintf ( stderr, "%s: Error. Need to provide Table Type with arg -t\n", SELF );
122 exit ( EXIT_FAILURE );
123 }
124
125 if ( INPUT_FILE[0] == 0 )
126 {
127 f = stdin;
128 }
129 else if ( ( f = fopen ( INPUT_FILE, "r" ) ) == NULL )
130 {
131 fprintf ( stderr, "%s: Error. Cannot open file '%s'\n", SELF, INPUT_FILE );
132 exit ( EXIT_FAILURE );
133 }
134
135 if ( IS_WMO )
136 {
137 switch ( TABLE_TYPE[0] )
138 {
139 case 'A':
140 case 'a':
141 fs = & ( A_FIELDS[0] );
142 break;
143 case 'B':
144 case 'b':
145 if (IS_WMO == 1)
146 fs = & ( B_FIELDS[0] );
147 else if (IS_WMO == 2)
148 fs = & ( B_FIELDS_2[0] );
149 else
150 fs = & ( B_FIELDS_3[0] );
151 break;
152 case 'C':
153 case 'c':
154 if (IS_WMO == 1)
155 fs = & ( C_FIELDS[0] );
156 else if (IS_WMO == 2)
157 fs = & ( C_FIELDS_2[0] );
158 else
159 fs = & ( C_FIELDS_3[0] );
160 break;
161 case 'D':
162 case 'd':
163 if (IS_WMO == 1)
164 fs = & ( D_FIELDS[0] );
165 else if (IS_WMO == 2)
166 fs = & ( D_FIELDS_2[0] );
167 else
168 fs = & ( D_FIELDS_3[0] );
169 break;
170 default:
171 fprintf ( stderr, "%s: Error, bad '%s' table type\n", SELF, TABLE_TYPE );
172 fclose ( f );
173 exit ( EXIT_FAILURE );
174 }
175
176 while ( fgets ( lin, CSV_MAXL, f ) != NULL )
177 {
178 // Parse line
179 if ( parse_csv_line ( &nt, tk, lin ) < 0 )
180 {
181 fprintf ( stderr, "%s: Error parsing csv line '%s' from file '%s'\n", SELF, lin, INPUT_FILE );
182 fclose ( f );
183 exit ( EXIT_FAILURE );
184 }
185
186 i = 0;
187 while ( fs[i] >= 0 )
188 {
189 if ( i > 0 )
190 printf ( "," );
191 if ( strlen ( tk[fs[i]] ) )
192 printf ( "%s", csv_quoted_string ( caux, tk[fs[i]] ) );
193 i++;
194 }
195 printf ( "\n" );
196 }
197 }
198 else
199 {
200 // Decode ECMWF tables
201 // first line with the name of fields
202 switch ( TABLE_TYPE[0] )
203 {
204 case 'B':
205 case 'b':
206 printf ( "\"FXY\",\"ElementName_en\",\"Note_en\",\"BUFR_Unit\",\"BUFR_Scale\",\"BUFR_ReferenceValue\",\"BUFR_DataWidth_Bits\"\n" );
207 break;
208 case 'C':
209 case 'c':
210 printf ( "\"FXY\",\"CodeFigure\",\"EntryName_en\",\"EntryName_sub1_en\",\"EntryName_sub2_en\",\"Note_en\"\n" );
211 break;
212 case 'D':
213 case 'd':
214 printf ( "\"FXY1\",\"FXY2\",\"Title_en\",\"ElementName_en\"\n" );
215 break;
216 }
217
218 caux[0] = 0;
219 while ( fgets ( lin, CSV_MAXL, f ) != NULL )
220 {
221 // supress the newline
222 if ( ( c = strrchr ( lin,'\n' ) ) != NULL )
223 {
224 *c = '\0';
225 }
226
227 switch ( TABLE_TYPE[0] )
228 {
229 case 'B':
230 case 'b':
231 // Descriptor
232 ix = strtoul ( &lin[0], &c, 10 );
233 uint32_t_to_descriptor ( &desc, ix );
234 printf ( "\"%s\",", desc.c );
235
236 // detailed name and a void note
237 bufr_charray_to_string ( caux, &lin[8], 64 );
238 bufr_adjust_string ( caux ); // supress trailing blanks
239 printf ( "\"%s\",,", caux );
240
241 // type
242 bufr_charray_to_string ( caux ,&lin[73], 24 );
243 bufr_adjust_string ( caux );
244 printf ( "\"%s\",", caux );
245
246 // escale
247 il = strtol ( &lin[97], &c, 10 );
248 printf ( "\"%ld\",", il );
249
250 // reference
251 il = strtol ( &lin[102], &c, 10 );
252 printf ( "\"%ld\",", il );
253
254 // bits
255 il = strtol ( &lin[115], &c, 10 );
256 printf ( "\"%ld\"\n", il );
257 break;
258
259 case 'C':
260 case 'c':
261
262 // write csv line with stored data if finished
263 if ( lin[12] != ' ' && caux[0] )
264 {
265 printf ( "\"%s\",\"%u\",\"%s\",,,\n", caux2, ix, caux );
266 caux[0] = 0;
267 }
268
269 if ( lin[0] != ' ' )
270 {
271 memcpy ( caux2, lin, 6 );
272 caux2[6] = '\0';
273 }
274
275 if ( lin[12] != ' ' )
276 {
277 ix = strtol ( lin + 12, &c, 10 );
278 strcpy ( caux, lin + 24 );
279 }
280 else
281 {
282 if ( lin[22] != ' ' )
283 {
284 if ( strlen ( caux ) + strlen ( lin + 22 ) < BUFR_EXPLAINED_LENGTH )
285 strcat ( caux, lin + 22 );
286 else
287 {
288 // cut the explanation
289 * ( lin + 22 + BUFR_EXPLAINED_LENGTH - strlen ( caux ) - 1 ) = '\0';
290 strcat ( caux, lin + 22 );
291 }
292 }
293 else
294 {
295 // this is valid for versions < 15
296 if ( strlen ( caux ) + strlen ( lin + 24 ) < BUFR_EXPLAINED_LENGTH )
297 strcat ( caux, lin + 24 );
298 else
299 {
300 // cut the explanation
301 * ( lin + 24 + BUFR_EXPLAINED_LENGTH - strlen ( caux ) - 1 ) = '\0';
302 strcat ( caux, lin + 24 );
303 }
304 }
305 }
306
307 break;
308
309 case 'D':
310 case 'd':
311
312 if ( lin[1] != ' ' )
313 {
314 memcpy ( caux2, lin + 1, 6 );
315 caux2[6] = '\0';
316 }
317
318 memcpy ( caux, lin + 11, 6 );
319 caux[6] = '\0';
320 printf ( "\"%s\",\"%s\",,\n", caux2, caux );
321 break;
322
323 default:
324 fprintf ( stderr, "%s: Error, bad '%s' table type\n", SELF, TABLE_TYPE );
325 fclose ( f );
326 exit ( EXIT_FAILURE );
327 }
328 }
329
330 // In case of table C (codeFlag) we still have to write last line
331 if ( TABLE_TYPE[0] == 'C' || TABLE_TYPE[0] == 'c' )
332 {
333 printf ( "\"%s\",\"%u\",\"%s\",,,\n", caux2, ix, caux );
334 }
335 }
336 if (INPUT_FILE[0])
337 fclose ( f );
338
339 exit ( EXIT_SUCCESS );
340}
Include header file for bufrdeco library.
#define BUFR_EXPLAINED_LENGTH
Maximum length for a explained descriptor string.
Definition: bufrdeco.h:122
int uint32_t_to_descriptor(struct bufr_descriptor *d, uint32_t id)
parse an integer with a descriptor fom bufr ECWMF libary
#define CSV_MAXL
Maximum length in a string to be parsed as csv.
Definition: bufrdeco.h:128
char * bufr_charray_to_string(char *s, char *buf, size_t size)
get a null termitated c-string from an array of unsigned chars
int parse_csv_line(int *nt, char *tk[], char *lin)
Parse a csv line.
Definition: bufrdeco_csv.c:258
char * csv_quoted_string(char *out, char *in)
Transform a string to a quoted string to be inserted in a csv file.
Definition: bufrdeco_csv.c:48
char * bufr_adjust_string(char *s)
Supress trailing blanks of a string.
#define PACKAGE_VERSION
Definition: config.h:4
int C_FIELDS_2[8]
char INPUT_FILE[256]
int main(int argc, char *argv[])
int IS_WMO
int C_FIELDS[8]
const char SELF[]
char TABLE_TYPE[8]
int B_FIELDS[8]
int A_FIELDS[8]
int D_FIELDS_2[8]
void print_usage(void)
int B_FIELDS_3[8]
int D_FIELDS_3[8]
int D_FIELDS[8]
int B_FIELDS_2[8]
int C_FIELDS_3[8]
BUFR descriptor.
Definition: bufrdeco.h:409
char c[12]
Definition: bufrdeco.h:414