cdo.c 45.1 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
/*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
2
  This file is part of CDO. CDO is a collection of Operators to
Uwe Schulzweida's avatar
Uwe Schulzweida committed
3
4
  manipulate and analyse Climate model Data.

5
  Copyright (C) 2003-2016 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
7
8
9
10
11
12
13
14
15
16
17
  See COPYING file for copying and redistribution conditions.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
*/

Uwe Schulzweida's avatar
Uwe Schulzweida committed
18
#if defined(HAVE_CONFIG_H)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
19
20
21
#  include "config.h"
#endif

22
#ifndef _XOPEN_SOURCE
Uwe Schulzweida's avatar
Uwe Schulzweida committed
23
//#define _XOPEN_SOURCE 600 /* gethostname */
24
25
#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
26
27
28
29
#if defined (HAVE_EXECINFO_H)
#include <execinfo.h>
#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
30
31
#include <signal.h>
#include <fenv.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
32
#include <ctype.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
33
/*#include <malloc.h>*/ /* mallopt and malloc_stats */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
34
#include <sys/stat.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35
36
#if defined(HAVE_GETRLIMIT)
#if defined(HAVE_SYS_RESOURCE_H)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
37
38
#include <sys/time.h>       /* getrlimit */
#include <sys/resource.h>   /* getrlimit */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
40
#endif
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
41
#include <unistd.h>         /* sysconf, gethostname */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
42

Uwe Schulzweida's avatar
Uwe Schulzweida committed
43
#if defined(SX)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
44
45
46
47
48
#define RLIM_T  long long
#else
#define RLIM_T  rlim_t
#endif

Ralf Mueller's avatar
Ralf Mueller committed
49
#include <cdi.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
50
51
52
#include "cdo.h"
#include "cdo_int.h"

Uwe Schulzweida's avatar
Uwe Schulzweida committed
53
#include "cdo_getopt.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
54

Uwe Schulzweida's avatar
Uwe Schulzweida committed
55
#if defined(HAVE_LIBPTHREAD)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
56
57
58
59
60
61
#include "pstream_int.h"
#include "pthread_debug.h"
#endif

#include "modules.h"
#include "util.h"
62
#include "error.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
63

Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
#if defined(_OPENMP)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65
66
67
#  include <omp.h>
#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
68
#if ! defined(VERSION)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
69
70
71
#  define  VERSION  "0.0.1"
#endif

72
#define MAX_NUM_VARNAMES 256
73

74
75
76
77
78
static int Debug = 0;
static int Version = 0;
static int Help = 0;
static int DebugLevel = 0;
static int numThreads = 0;
79
static int timer_total;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
80
81
static int CDO_netcdf_hdr_pad = 0;
static int CDO_Rusage = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
82
static const char *username;
83

84
void gridsearch_set_method(const char *methodstr);
85

Uwe Schulzweida's avatar
Uwe Schulzweida committed
86
87
#define PRINT_RLIMIT(resource) \
      { \
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
        int status; \
        struct rlimit rlim; \
        status = getrlimit(resource, &rlim); \
        if ( status == 0 ) \
          { \
            if ( sizeof(RLIM_T) > sizeof(long) ) \
              { \
                fprintf(stderr, "CUR %-15s = %llu\n", #resource, (long long) rlim.rlim_cur); \
                fprintf(stderr, "MAX %-15s = %llu\n", #resource, (long long) rlim.rlim_max); \
              } \
            else \
              { \
                fprintf(stderr, "CUR %-15s = %lu\n", #resource, (long) rlim.rlim_cur); \
                fprintf(stderr, "MAX %-15s = %lu\n", #resource, (long) rlim.rlim_max); \
              } \
          } \
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104
105
      }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
106
#define ISME  (strcmp(username, "\x6d\x32\x31\x34\x30\x30\x33") == 0)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
107

Uwe Schulzweida's avatar
Uwe Schulzweida committed
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
static
void cdo_stackframe(void)
{
#if defined HAVE_EXECINFO_H && defined HAVE_BACKTRACE
  void *callstack[32];
  int frames = backtrace(callstack, 32);
  char **messages = backtrace_symbols(callstack, frames);

  fprintf(stderr, "[bt] Execution path:\n");
  if ( messages ) {
    for ( int i = 0; i < frames; ++i )
      fprintf(stderr, "[bt] %s\n", messages[i]);
    free(messages);
  }
#endif
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
125
static
126
int cdo_feenableexcept(int excepts)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
127
{
128
#if defined HAVE_FEENABLEEXCEPT
129
130
  int feenableexcept(int);
  int old_excepts = feenableexcept(excepts);
131
132
  return old_excepts;
#else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
133
  static fenv_t fenv;
134
135
  unsigned new_excepts = ((unsigned)excepts) & FE_ALL_EXCEPT;
  int old_excepts = -1;  // previous masks
Uwe Schulzweida's avatar
Uwe Schulzweida committed
136
137

  if ( fegetenv(&fenv) ) return -1;
138
139
#if defined(HAVE_FENV_T___CONTROL) && defined(HAVE_FENV_T___MXCSR)
  old_excepts = (int) (fenv.__control & FE_ALL_EXCEPT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
140

141
142
143
  // unmask
  fenv.__control &= ~new_excepts;
  fenv.__mxcsr   &= ~(new_excepts << 7);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
144
145
146
#endif

  return ( fesetenv(&fenv) ? -1 : (int)old_excepts );
147
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148
149
150
151
152
153
154
155
156
157
158
159
}

static
void cdo_sig_handler(int signo)
{
  if ( signo == SIGFPE )
    {
      cdo_stackframe();
      cdoAbort("floating-point exception!");
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
161
162
static
void cdo_version(void)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
163
164
  const int   filetypes[] = {FILETYPE_SRV, FILETYPE_EXT, FILETYPE_IEG, FILETYPE_GRB, FILETYPE_GRB2, FILETYPE_NC, FILETYPE_NC2, FILETYPE_NC4, FILETYPE_NC4C};
  const char* typenames[] = {        "srv",        "ext",        "ieg",        "grb",        "grb2",        "nc",        "nc2",        "nc4",        "nc4c"};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
165
166

  fprintf(stderr, "%s\n", CDO_Version);
167
#if defined(USER_NAME) && defined(HOST_NAME) && defined(SYSTEM_TYPE)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
168
  fprintf(stderr, "Compiled: by %s on %s (%s) %s %s\n", USER_NAME, HOST_NAME, SYSTEM_TYPE, __DATE__, __TIME__);
169
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
170
#if defined(COMPILER)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
171
172
  fprintf(stderr, "Compiler: %s\n", COMPILER);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
#if defined(COMP_VERSION)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
175
176
177
178
  fprintf(stderr, " version: %s\n", COMP_VERSION);
#endif

  printFeatures();
  printLibraries();
179

Uwe Schulzweida's avatar
Uwe Schulzweida committed
180
  fprintf(stderr, "Filetypes: ");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
181
  set_text_color(stderr, BRIGHT, GREEN);
182
183
  for ( size_t i = 0; i < sizeof(filetypes)/sizeof(int); ++i )
    if ( cdiHaveFiletype(filetypes[i]) ) fprintf(stderr, "%s ", typenames[i]);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184
  reset_text_color(stderr);
185
186
  fprintf(stderr, "\n");

Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
188
189
190
  cdiPrintVersion();
  fprintf(stderr, "\n");
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
191
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
192
void cdo_usage(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
193
{
194
  const char *name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
195
196
197

  /*  fprintf(stderr, "%s\n", CDO_Version);*/
  /*  fprintf(stderr, "\n");*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198
  fprintf(stderr, "usage : cdo  [Options]  Operator1  [-Operator2  [-OperatorN]]\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
199
200
  fprintf(stderr, "\n");
  fprintf(stderr, "  Options:\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
201
  set_text_color(stderr, RESET, BLUE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
202
  fprintf(stderr, "    -a             Generate an absolute time axis\n");
203
  fprintf(stderr, "    -b <nbits>     Set the number of bits for the output precision\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
204
  fprintf(stderr, "                   (I8/I16/I32/F32/F64 for nc/nc2/nc4/nc4c; F32/F64 for grb2/srv/ext/ieg; P1 - P24 for grb/grb2)\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
  fprintf(stderr, "                   Add L or B to set the byteorder to Little or Big endian\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
206
207
208
209
210
  if ( ISME )
    {
      fprintf(stderr, "    --enableexcept <except>\n");
      fprintf(stderr, "                   Set individual floating-point traps (DIVBYZERO, INEXACT, INVALID, OVERFLOW, UNDERFLOW, ALL_EXCEPT)\n");
    }
211
212
  fprintf(stderr, "    -f, --format <format>\n");
  fprintf(stderr, "                   Format of the output file. (grb/grb2/nc/nc2/nc4/nc4c/srv/ext/ieg)\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
  fprintf(stderr, "    -g <grid>      Set default grid name or file. Available grids: \n");
214
  fprintf(stderr, "                   n<N>, t<RES>, tl<RES>, global_<DXY>, r<NX>x<NY>, g<NX>x<NY>, gme<NI>, lon=<LON>/lat=<LAT>\n");
215
  fprintf(stderr, "    -h, --help     Help information for the operators\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216
  fprintf(stderr, "    --history      Do not append to NetCDF \"history\" global attribute\n");
217
  fprintf(stderr, "    --netcdf_hdr_pad, --hdr_pad, --header_pad <nbr>\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
218
  fprintf(stderr, "                   Pad NetCDF output header with nbr bytes\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
220
221
  /*
  fprintf(stderr, "    -i <inst>      Institution name/file\n");
  fprintf(stderr, "                   Predefined instituts: ");
222
  for ( int id = 0; id < institutInqNumber; id++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
224
225
226
227
    if ( (name = institutInqNamePtr(id)) )
      fprintf(stderr, " %s", name);
  fprintf(stderr, "\n");
  */
  /* fprintf(stderr, "    -l <level>     Level file\n"); */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
228
229
  fprintf(stderr, "    -k <chunktype> NetCDF4 chunk type: auto, grid or lines\n");
  fprintf(stderr, "    -L             Lock IO (sequential access)\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
  fprintf(stderr, "    -M             Switch to indicate that the I/O streams have missing values\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
231
  fprintf(stderr, "    -m <missval>   Set the missing value of non NetCDF files (default: %g)\n", cdiInqMissval());
232
  fprintf(stderr, "    --no_warnings  Inhibit warning messages\n");
233
  fprintf(stderr, "    -O             Overwrite existing output file, if checked\n");
234
  fprintf(stderr, "    --operators    List of all operators\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
235
#if defined(_OPENMP)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
237
  fprintf(stderr, "    -P <nthreads>  Set number of OpenMP threads\n");
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
238
239
  fprintf(stderr, "    --percentile <method>\n");
  fprintf(stderr, "                   Percentile method: nrank, nist, numpy, numpy_lower, numpy_higher, numpy_nearest\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
240
241
  fprintf(stderr, "    -Q             Alphanumeric sorting of NetCDF parameter names\n");
  fprintf(stderr, "    --reduce_dim   Reduce NetCDF dimensions (module: TIMSTAT, FLDSTAT)\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
  fprintf(stderr, "    -R, --regular  Convert GRIB1 data from reduced to regular grid (cgribex only)\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
243
  fprintf(stderr, "    -r             Generate a relative time axis\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
245
  fprintf(stderr, "    -S             Create an extra output stream for the module TIMSTAT. This stream\n");
  fprintf(stderr, "                   contains the number of non missing values for each output period.\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
246
  fprintf(stderr, "    -s, --silent   Silent mode\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
247
  fprintf(stderr, "    -t <partab>    Set GRIB1 default parameter table name or file (cgribex only)\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
248
  fprintf(stderr, "                   Predefined tables: ");
249
  for ( int id = 0; id < tableInqNumber(); id++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
250
251
252
253
    if ( (name = tableInqNamePtr(id)) )
      fprintf(stderr, " %s", name);
  fprintf(stderr, "\n");

254
255
  fprintf(stderr, "    -V, --version  Print the version number\n");
  fprintf(stderr, "    -v, --verbose  Print extra details for some operators\n");
256
  fprintf(stderr, "    -W             Print extra warning messages\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
257
258
  fprintf(stderr, "    -z szip        SZIP compression of GRIB1 records\n");
  fprintf(stderr, "       jpeg        JPEG compression of GRIB2 records\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
259
  fprintf(stderr, "        zip[_1-9]  Deflate compression of NetCDF4 variables\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
260
  reset_text_color(stderr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
261
262
263
  fprintf(stderr, "\n");

  fprintf(stderr, "  Operators:\n");
264
265
  fprintf(stderr, "    Use option --operators for a list of all operators.\n");
  /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
266
  set_text_color(stderr, RESET, GREEN);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
267
  operatorPrintAll();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
268
  reset_text_color(stderr);
269
  */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
270
271

  fprintf(stderr, "\n");
272
  fprintf(stderr, "  CDO version %s, Copyright (C) 2003-2016 Uwe Schulzweida\n", VERSION);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
273
  //  fprintf(stderr, "  Available from <http://mpimet.mpg.de/cdo>\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
274
  fprintf(stderr, "  This is free software and comes with ABSOLUTELY NO WARRANTY\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275
  fprintf(stderr, "  Report bugs to <http://mpimet.mpg.de/cdo>\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
276
277
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
278
279
280
281
282
static
void cdo_init_is_tty(void)
{
  struct stat statbuf;
  fstat(0, &statbuf);
283
  if ( S_ISCHR(statbuf.st_mode) ) stdin_is_tty = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
284
  fstat(1, &statbuf);
285
  if ( S_ISCHR(statbuf.st_mode) ) stdout_is_tty = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
286
  fstat(2, &statbuf);
287
  if ( S_ISCHR(statbuf.st_mode) ) stderr_is_tty = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
288
289
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
290
static
291
void cdoPrintHelp(const char *phelp[]/*, char *xoperator*/)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
292
293
{
  if ( phelp == NULL )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
294
    fprintf(stderr, "No help available for this operator!\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
296
  else
    {
297
298
      int lprint;
      while ( *phelp )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
        {
          lprint = TRUE;
          if ( *phelp[0] == '\0' )
            if ( *(phelp+1) )
              if ( *(phelp+1)[0] == ' ' ) lprint = FALSE;
          
          if ( lprint )
            {
              if ( COLOR_STDOUT )
                {
                  if ( (strcmp(*phelp, "NAME")        == 0) ||
                       (strcmp(*phelp, "SYNOPSIS")    == 0) ||
                       (strcmp(*phelp, "DESCRIPTION") == 0) ||
                       (strcmp(*phelp, "OPERATORS")   == 0) ||
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313
                       (strcmp(*phelp, "NAMELIST")    == 0) ||
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
314
                       (strcmp(*phelp, "PARAMETER")   == 0) ||
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
                       (strcmp(*phelp, "ENVIRONMENT") == 0) ||
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
                       (strcmp(*phelp, "NOTE")        == 0) ||
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
                       (strcmp(*phelp, "EXAMPLES")    == 0) )
                    {
                      set_text_color(stdout, BRIGHT, BLACK);
                      fprintf(stdout, "%s", *phelp);
                      reset_text_color(stdout);
                      fprintf(stdout, "\n");
                    }
                  else
                    fprintf(stdout, "%s\n", *phelp);
                }
              else
                {
                  fprintf(stdout, "%s\n", *phelp);
                }
            }

          phelp++;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
335
336
337
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
338
339
static
void cdoSetDebug(int level)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
{
  /*
    level   0: off
    level   1: on
    level   2: cdi
    level   4: memory
    level   8: file
    level  16: format
    level  32: cdo
    level  64: stream
    level 128: pipe
    level 256: pthread
   */
  cdiDebug(level);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
356
  if ( level == 1 || (level &  32) ) cdoDebug = 1;
  if ( level == 1 || (level &  64) ) pstreamDebug(1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
357
#if defined(HAVE_LIBPTHREAD)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
358
359
  if ( level == 1 || (level & 128) ) pipeDebug(1);
  if ( level == 1 || (level & 256) ) Pthread_debug(1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
360
361
362
363
364
365
#endif
}

#undef  IsBigendian
#define IsBigendian()  ( u_byteorder.c[sizeof(long) - 1] )

Uwe Schulzweida's avatar
Uwe Schulzweida committed
366
static
367
void setDefaultDataType(const char *datatypestr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368
369
{
  static union {unsigned long l; unsigned char c[sizeof(long)];} u_byteorder = {1};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
370
  int nbits = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371
  enum {D_UINT, D_INT, D_FLT, D_CPX};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
  int dtype = -1;

  if      ( *datatypestr == 'i' || *datatypestr == 'I' )
    {
      dtype = D_INT;
      datatypestr++;
    }
  else if ( *datatypestr == 'u' || *datatypestr == 'U' )
    {
      dtype = D_UINT;
      datatypestr++;
    }
  else if ( *datatypestr == 'f' || *datatypestr == 'F' )
    {
      dtype = D_FLT;
      datatypestr++;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
390
391
392
393
  else if ( *datatypestr == 'c' || *datatypestr == 'C' )
    {
      dtype = D_CPX;
      datatypestr++;
    }
394
395
396
397
  else if ( *datatypestr == 'p' || *datatypestr == 'P' )
    {
      datatypestr++;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
398

399
400
  if ( isdigit((int) *datatypestr) )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
402
      nbits = atoi(datatypestr);
      if ( nbits < 10 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
403
        datatypestr += 1;
404
      else
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
405
        datatypestr += 2;
406

Uwe Schulzweida's avatar
Uwe Schulzweida committed
407
      if ( dtype == -1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
        {
          if      ( nbits > 0 && nbits < 32 ) cdoDefaultDataType = nbits;
          else if ( nbits == 32 )
            {
              if ( cdoDefaultFileType == FILETYPE_GRB )
                cdoDefaultDataType = DATATYPE_PACK32;
              else
                cdoDefaultDataType = DATATYPE_FLT32;
            }
          else if ( nbits == 64 ) cdoDefaultDataType = DATATYPE_FLT64;
          else
            {
              fprintf(stderr, "Unsupported number of bits %d!\n", nbits);
              fprintf(stderr, "Use I8/I16/I32/F32/F64 for nc/nc2/nc4/nc4c; F32/F64 for grb2/srv/ext/ieg; P1 - P24 for grb/grb2.\n");
              exit(EXIT_FAILURE);
            }
        }
425
      else
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
        {
          if ( dtype == D_INT )
            {
              if      ( nbits ==  8 ) cdoDefaultDataType = DATATYPE_INT8;
              else if ( nbits == 16 ) cdoDefaultDataType = DATATYPE_INT16;
              else if ( nbits == 32 ) cdoDefaultDataType = DATATYPE_INT32;
              else
                {
                  fprintf(stderr, "Unsupported number of bits = %d for datatype INT!\n", nbits);
                  exit(EXIT_FAILURE);
                }
            }
          else if ( dtype == D_UINT )
            {
              if      ( nbits ==  8 ) cdoDefaultDataType = DATATYPE_UINT8;
              else if ( nbits == 16 ) cdoDefaultDataType = DATATYPE_UINT16;
              else if ( nbits == 32 ) cdoDefaultDataType = DATATYPE_UINT32;
              else
                {
                  fprintf(stderr, "Unsupported number of bits = %d for datatype UINT!\n", nbits);
                  exit(EXIT_FAILURE);
                }
            }
          else if ( dtype == D_FLT )
            {
              if      ( nbits == 32 ) cdoDefaultDataType = DATATYPE_FLT32;
              else if ( nbits == 64 ) cdoDefaultDataType = DATATYPE_FLT64;
              else
                {
                  fprintf(stderr, "Unsupported number of bits = %d for datatype FLT!\n", nbits);
                  exit(EXIT_FAILURE);
                }
            }
          else if ( dtype == D_CPX )
            {
              if      ( nbits == 32 ) cdoDefaultDataType = DATATYPE_CPX32;
              else if ( nbits == 64 ) cdoDefaultDataType = DATATYPE_CPX64;
              else
                {
                  fprintf(stderr, "Unsupported number of bits = %d for datatype CPX!\n", nbits);
                  exit(EXIT_FAILURE);
                }
            }
        }
470
471
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
472
  if ( *datatypestr != 0 )
473
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474
      if ( *datatypestr == 'l' || *datatypestr == 'L' )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
475
476
477
478
        {
          if ( IsBigendian() ) cdoDefaultByteorder = CDI_LITTLEENDIAN;
          datatypestr++;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
479
      else if ( *datatypestr == 'b' || *datatypestr == 'B' )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
480
481
482
483
        {
          if ( ! IsBigendian() ) cdoDefaultByteorder = CDI_BIGENDIAN;
          datatypestr++;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
      else
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
485
486
487
488
        {
          fprintf(stderr, "Unsupported character in number of bytes: >%s< !\n", datatypestr);
          exit(EXIT_FAILURE);
        }
489
490
    }
}
491
/*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
static
void setDefaultDataTypeByte(char *datatypestr)
494
495
496
497
{
  static union {unsigned long l; unsigned char c[sizeof(long)];} u_byteorder = {1};
  int datatype = -1;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
498
499
500
501
502
  if ( isdigit((int) *datatypestr) )
    {
      datatype = atoi(datatypestr);
      datatypestr++;

503
504
505
506
507
      if      ( datatype == 1 ) cdoDefaultDataType = DATATYPE_PACK8;
      else if ( datatype == 2 ) cdoDefaultDataType = DATATYPE_PACK16;
      else if ( datatype == 3 ) cdoDefaultDataType = DATATYPE_PACK24;
      else if ( datatype == 4 ) cdoDefaultDataType = DATATYPE_FLT32;
      else if ( datatype == 8 ) cdoDefaultDataType = DATATYPE_FLT64;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
      else
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
509
510
511
512
513
        {
          fprintf(stderr, "Unsupported datatype %d!\n", datatype);
          fprintf(stderr, "Use 4/8 for filetype nc/srv/ext/ieg and 1/2/3 for grb/grb2.\n");
          exit(EXIT_FAILURE);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
515
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
  if ( *datatypestr != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
      if ( *datatypestr == 'l' || *datatypestr == 'L' )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
519
520
        {
          if ( IsBigendian() ) cdoDefaultByteorder = CDI_LITTLEENDIAN;
521
          datatypestr++;setDefaultDataTypeByte
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
522
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
523
      else if ( *datatypestr == 'b' || *datatypestr == 'B' )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
524
525
526
527
        {
          if ( ! IsBigendian() ) cdoDefaultByteorder = CDI_BIGENDIAN;
          datatypestr++;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528
      else
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
529
530
531
532
        {
          fprintf(stderr, "Unsupported character in number of bytes: %s!\n", datatypestr);
          exit(EXIT_FAILURE);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
533
534
    }
}
535
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
static
537
void setDefaultFileType(const char *filetypestr, int labort)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
538
539
540
{
  if ( filetypestr )
    {
541
      const char *ftstr = filetypestr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
543
544
545
546
547
548
549
550
551
552
553
      size_t len;

      if      ( cmpstrlen(filetypestr, "grb2", len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_GRB2;}
      else if ( cmpstrlen(filetypestr, "grb1", len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_GRB; }
      else if ( cmpstrlen(filetypestr, "grb",  len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_GRB; }
      else if ( cmpstrlen(filetypestr, "nc2",  len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_NC2; }
      else if ( cmpstrlen(filetypestr, "nc4c", len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_NC4C;}
      else if ( cmpstrlen(filetypestr, "nc4",  len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_NC4; }
      else if ( cmpstrlen(filetypestr, "nc",   len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_NC;  }
      else if ( cmpstrlen(filetypestr, "srv",  len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_SRV; }
      else if ( cmpstrlen(filetypestr, "ext",  len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_EXT; }
      else if ( cmpstrlen(filetypestr, "ieg",  len)  == 0 ) { ftstr += len; cdoDefaultFileType = FILETYPE_IEG; }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
554
      else
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
555
556
557
558
559
560
561
562
563
564
565
566
        {
          if ( labort )
            {
              fprintf(stderr, "Unsupported filetype %s!\n", filetypestr);
              fprintf(stderr, "Available filetypes: grb/grb2/nc/nc2/nc4/nc4c/srv/ext/ieg\n");
              exit(EXIT_FAILURE);
            }
          else
            {
              return;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567

568
      if ( cdoDefaultFileType != CDI_UNDEFID && *ftstr != 0 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
        {
          if ( *ftstr == '_' )
            {
              ftstr++;

              setDefaultDataType(ftstr);
            }
          else
            {
              fprintf(stderr, "Unexpected character >%c< in file type >%s<!\n", *ftstr, filetypestr);
              fprintf(stderr, "Use format[_nbits] with:\n");
              fprintf(stderr, "    format = grb, grb2, nc, nc2, nc4, nc4c, srv, ext or ieg\n");
              fprintf(stderr, "    nbits  = 32/64 for grb2/nc/nc2/nc4/nc4c/srv/ext/ieg; 1 - 24 for grb/grb2\n");
              exit(EXIT_FAILURE);
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
586
587
    }
}

588
#define NTESTS 11
589
#include <inttypes.h>
590
591
592
593
594
595
596
597
598
599
static
int getMemAlignment(void)
{
  int ma = -1;
  double *ptr[NTESTS];
  int64_t iptr;
  size_t tsize[NTESTS] = {1, 3, 5, 9, 17, 33, 69, 121, 251, 510, 1025};
  size_t ma_check[4] = {8, 16, 32, 64};
  int ma_result[4] = {1, 1, 1, 1};

Uwe Schulzweida's avatar
Uwe Schulzweida committed
600
  for ( int i = 0; i < NTESTS; ++i )
601
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
602
      ptr[i] = (double*) malloc(tsize[i]);
603
      iptr = (int64_t) ptr[i];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
604
      for ( int k = 0; k < 4; ++k ) if ( iptr%ma_check[k] ) ma_result[k] = 0; 
605
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
606
  for ( int i = 0; i < NTESTS; ++i ) free(ptr[i]);
607

Uwe Schulzweida's avatar
Uwe Schulzweida committed
608
  for ( int i = NTESTS-1; i >= 0; i-- )
609
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
610
      ptr[i] = (double*) malloc(tsize[i]+5);
611
      iptr = (int64_t) ptr[i];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
      for ( int k = 0; k < 4; ++k ) if ( iptr%ma_check[k] ) ma_result[k] = 0; 
613
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
614
  for ( int i = 0; i < NTESTS; ++i ) free(ptr[i]);
615

Uwe Schulzweida's avatar
Uwe Schulzweida committed
616
  for ( int k = 0; k < 4; ++k ) if ( ma_result[k] ) ma = ma_check[k];
617

Uwe Schulzweida's avatar
Uwe Schulzweida committed
618
  return ma;
619
620
}

621

Uwe Schulzweida's avatar
Uwe Schulzweida committed
622
static
623
624
625
626
void defineCompress(const char *arg)
{
  size_t len = strlen(arg);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
  if      ( strncmp(arg, "szip", len) == 0 )
628
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
629
630
      cdoCompType  = COMPRESS_SZIP;
      cdoCompLevel = 0;
631
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
632
  else if ( strncmp(arg, "jpeg", len) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
633
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
635
      cdoCompType = COMPRESS_JPEG;
      cdoCompLevel = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
637
  else if ( strncmp(arg, "gzip", len) == 0 )
638
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
639
640
      cdoCompType  = COMPRESS_GZIP;
      cdoCompLevel = 6;
641
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
642
  else if ( strncmp(arg, "zip", 3) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
643
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
644
      cdoCompType  = COMPRESS_ZIP;
645
      if ( len == 5 && arg[3] == '_' && isdigit(arg[4]) )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
646
        cdoCompLevel = atoi(&arg[4]);
647
      else
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
648
        cdoCompLevel = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
649
    }
650
  else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
    {
      fprintf(stderr, "Compression type '%s' unsupported!\n", arg);
      exit(EXIT_FAILURE);
    }
}

static
void defineChunktype(const char *arg)
{
  if      ( strcmp("auto",  arg)   == 0 ) cdoChunkType = CHUNK_AUTO;
  else if ( strcmp("grid",  arg)   == 0 ) cdoChunkType = CHUNK_GRID;
  else if ( strcmp("lines", arg)   == 0 ) cdoChunkType = CHUNK_LINES;
  else
    {
      fprintf(stderr, "Chunk type '%s' unsupported!\n", arg);
      exit(EXIT_FAILURE);
    }
668
669
}

670
671
672
673
674
675
676
677
678
679
static
void defineVarnames(const char *arg)
{
  size_t len = strlen(arg);
  size_t istart = 0;
  while ( istart < len && (arg[istart] == ' ' || arg[istart] == ',') ) istart++;

  len -= istart;

  if ( len )
680
    {      
681
      cdoVarnames = (char **) Malloc(MAX_NUM_VARNAMES*sizeof(char *));
682

683
      char *pbuf = strdup(arg+istart);
684
685
      cdoVarnames[cdoNumVarnames++] = pbuf;    

686
      char *commapos = pbuf;
687
      while ( (commapos = strchr(commapos, ',')) != NULL )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
688
689
690
691
692
693
694
695
696
697
        {
          *commapos++ = '\0';
          if ( strlen(commapos) )
            {
              if ( cdoNumVarnames >= MAX_NUM_VARNAMES )
                cdoAbort("Too many variable names (limit=%d)!", MAX_NUM_VARNAMES);

              cdoVarnames[cdoNumVarnames++] = commapos;
            }
        }
698
699
      /*
      for ( int i = 0; i < cdoNumVarnames; ++i )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
700
        printf("varname %d: %s\n", i+1, cdoVarnames[i]);
701
702
703
704
      */
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
705
706
707
708
709
static
void get_env_vars(void)
{
  char *envstr;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
710
711
712
713
714
715
716
  username = getenv("LOGNAME");
  if ( username == NULL )
    {
      username = getenv("USER");
      if ( username == NULL ) username = "unknown";
    }

717
718
719
720
721
  envstr = getenv("CDO_GRID_SEARCH_DIR");
  if ( envstr )
    {
      size_t len = strlen(envstr);
      if ( len > 0 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
722
723
        {
          len += 2;
724
          cdoGridSearchDir = (char*) Malloc(len);
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
725
726
727
728
729
730
731
          memcpy(cdoGridSearchDir, envstr, len-1);
          if ( cdoGridSearchDir[len-3] != '/' )
            {
              cdoGridSearchDir[len-2] = '/';
              cdoGridSearchDir[len-1] = 0;
            }
        }
732
733
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
734
735
736
737
  envstr = getenv("CDO_LOG_OFF");
  if ( envstr )
    {
      if ( atoi(envstr) == 1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
738
739
740
741
742
        {
          cdoLogOff = TRUE;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_LOG_OFF         = %s\n", envstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
743
744
745
746
747
748
    }

  envstr = getenv("CDO_DISABLE_HISTORY");
  if ( envstr )
    {
      if ( atoi(envstr) == 1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
749
750
751
752
753
        {
          CDO_Reset_History = TRUE;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_DISABLE_HISTORY = %s\n", envstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
755
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
756
757
758
759
  envstr = getenv("CDO_RESET_HISTORY");
  if ( envstr )
    {
      if ( atoi(envstr) == 1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
760
761
762
763
764
        {
          CDO_Reset_History = TRUE;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_RESET_HISTORY = %s\n", envstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
765
766
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
767
768
769
770
771
772
773
774
775
776
777
778
  envstr = getenv("CDO_HISTORY_INFO");
  if ( envstr )
    {
      int ival = atoi(envstr);
      if ( ival == 0 || ival == 1 )
        {
          CDO_Append_History = ival;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_HISTORY_INFO = %s\n", envstr);
        }
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
779
  CDO_File_Suffix[0] = 0;
780
781
782
783
784

  envstr = getenv("CDO_FILE_SUFFIX");
  if ( envstr )
    {
      if ( envstr[0] )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
785
786
787
788
789
        {
          strncat(CDO_File_Suffix, envstr, sizeof(CDO_File_Suffix)-1);
          if ( cdoVerbose )
            fprintf(stderr, "CDO_FILE_SUFFIX = %s\n", envstr);
        }
790
791
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
792
793
794
795
  envstr = getenv("CDO_DISABLE_FILESUFFIX");
  if ( envstr )
    {
      if ( atoi(envstr) == 1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
796
797
798
799
800
        {
          strcat(CDO_File_Suffix, "NULL");
          if ( cdoVerbose )
            fprintf(stderr, "CDO_DISABLE_FILESUFFIX = %s\n", envstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
801
802
803
804
805
806
    }

  envstr = getenv("CDO_DIAG");
  if ( envstr )
    {
      if ( atoi(envstr) == 1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
807
808
809
810
811
        {
          cdoDiag = TRUE;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_DIAG = %s\n", envstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
813

814
815
816
817
818
  envstr = getenv("CDO_USE_FFTW");
  if ( envstr )
    {
      int ival = atoi(envstr);
      if ( ival == 0 || ival == 1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
819
820
821
822
823
        {
          CDO_Use_FFTW = ival;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_Use_FFTW = %s\n", envstr);
        }
824
825
    }

826
827
828
829
830
831
832
833
834
835
836
837
  envstr = getenv("CDO_VERSION_INFO");
  if ( envstr )
    {
      int ival = atoi(envstr);
      if ( ival == 0 || ival == 1 )
        {
          CDO_Version_Info = ival;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_Version_Info = %s\n", envstr);
        }
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
838
839
840
  envstr = getenv("CDO_COLOR");
  if ( envstr )
    {
841
842
      int ival = atoi(envstr);
      if ( ival == 0 || ival == 1 )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
843
844
845
846
847
        {
          CDO_Color = ival;
          if ( cdoVerbose )
            fprintf(stderr, "CDO_COLOR = %s\n", envstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849
  else if ( CDO_Color == FALSE && ISME ) CDO_Color = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
850
851
}

852
853
static
void print_system_info()
Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
{
855
  fprintf(stderr, "\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
856
857
858
  fprintf(stderr, "CDO_Color           = %d\n", CDO_Color);
  fprintf(stderr, "CDO_Reset_History   = %d\n", CDO_Reset_History);
  fprintf(stderr, "CDO_File_Suffix     = %s\n", CDO_File_Suffix);
859
860
861
862
863
  fprintf(stderr, "cdoDefaultFileType  = %d\n", cdoDefaultFileType);
  fprintf(stderr, "cdoDefaultDataType  = %d\n", cdoDefaultDataType);
  fprintf(stderr, "cdoDefaultByteorder = %d\n", cdoDefaultByteorder);
  fprintf(stderr, "cdoDefaultTableID   = %d\n", cdoDefaultTableID);
  fprintf(stderr, "\n");
864

865
  const char *envstr;
866
867
868
869
870
871
872
873
874
  envstr = getenv("HOSTTYPE");
  if ( envstr ) fprintf(stderr, "HOSTTYPE            = %s\n", envstr);
  envstr = getenv("VENDOR");
  if ( envstr ) fprintf(stderr, "VENDOR              = %s\n", envstr);
  envstr = getenv("OSTYPE");
  if ( envstr ) fprintf(stderr, "OSTYPE              = %s\n", envstr);
  envstr = getenv("MACHTYPE");
  if ( envstr ) fprintf(stderr, "MACHTYPE            = %s\n", envstr);
  fprintf(stderr, "\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
875

876
877
#if defined(_ARCH_PWR6)
  fprintf(stderr, "Predefined: _ARCH_PWR6\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878
#elif defined(_ARCH_PWR7)
879
  fprintf(stderr, "Predefined: _ARCH_PWR7\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
880
881
882
883
884
#endif

#if defined(__AVX2__)
  fprintf(stderr, "Predefined: __AVX2__\n");
#elif defined(__AVX__)
885
  fprintf(stderr, "Predefined: __AVX__\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
886
887
888
889
890
891
892
893
#elif defined(__SSE4_2__)
  fprintf(stderr, "Predefined: __SSE4_2__\n");
#elif defined(__SSE4_1__)
  fprintf(stderr, "Predefined: __SSE4_1__\n");
#elif defined(__SSE3__)
  fprintf(stderr, "Predefined: __SSE3__\n");
#elif defined(__SSE2__)
  fprintf(stderr, "Predefined: __SSE2__\n");
894
895
#endif 
  fprintf(stderr, "\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
896

897
  fprintf(stderr, "mem alignment       = %d\n\n", getMemAlignment());
Uwe Schulzweida's avatar
Uwe Schulzweida committed
898

Uwe Schulzweida's avatar
Uwe Schulzweida committed
899
#if defined(HAVE_MMAP)
900
901
  fprintf(stderr, "HAVE_MMAP\n");
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
902
#if defined(HAVE_MEMORY_H)
903
904
905
  fprintf(stderr, "HAVE_MEMORY_H\n");
#endif
  fprintf(stderr, "\n");
906

Uwe Schulzweida's avatar
Uwe Schulzweida committed
907
#if defined(_OPENACC)
908
909
  fprintf(stderr, "OPENACC VERSION     = %d\n", _OPENACC);
#endif
910
911
  /* OPENMP 3:  201107 */
  /* OPENMP 4:  201307 gcc 4.9 */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
912
#if defined(_OPENMP)
913
914
  fprintf(stderr, "OPENMP VERSION      = %d\n", _OPENMP);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
915
#if defined(__GNUC__)
916
917
  fprintf(stderr, "GNUC VERSION        = %d\n", __GNUC__);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
918
#if defined(__GNUC_MINOR__)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
919
920
  fprintf(stderr, "GNUC MINOR          = %d\n", __GNUC_MINOR__);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
921
#if defined(__ICC)
922
923
  fprintf(stderr, "ICC VERSION         = %d\n", __ICC);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
924
#if defined(__STDC__)
925
926
  fprintf(stderr, "STD ANSI C          = %d\n", __STDC__);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
927
#if defined(__STD_VERSION__)
928
929
  fprintf(stderr, "STD VERSION         = %ld\n", __STD_VERSION__);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
930
#if defined(__STDC_VERSION__)
931
932
  fprintf(stderr, "STDC VERSION        = %ld\n", __STDC_VERSION__);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
933
#if defined(__STD_HOSTED__)
934
935
  fprintf(stderr, "STD HOSTED          = %d\n", __STD_HOSTED__);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
936
#if defined(FLT_EVAL_METHOD)
937
938
  fprintf(stderr, "FLT_EVAL_METHOD     = %d\n", FLT_EVAL_METHOD);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
939
#if defined(FP_FAST_FMA)
940
  fprintf(stderr, "FP_FAST_FMA         = defined\n");
941
942
943
#endif
#if defined(__FAST_MATH__)
  fprintf(stderr, "__FAST_MATH__       = defined\n");
944
945
946
#endif
  fprintf(stderr, "\n");

Uwe Schulzweida's avatar
Uwe Schulzweida committed
947
#if defined(_SC_VERSION)
948
949
  fprintf(stderr, "POSIX.1 VERSION     = %ld\n", sysconf(_SC_VERSION));
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
950
#if defined(_SC_ARG_MAX)
951
952
  fprintf(stderr, "POSIX.1 ARG_MAX     = %ld\n", sysconf(_SC_ARG_MAX));
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
953
#if defined(_SC_CHILD_MAX)
954
955
  fprintf(stderr, "POSIX.1 CHILD_MAX   = %ld\n", sysconf(_SC_CHILD_MAX));
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
956
#if defined(_SC_STREAM_MAX)
957
958
  fprintf(stderr, "POSIX.1 STREAM_MAX  = %ld\n", sysconf(_SC_STREAM_MAX));
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
959
#if defined(_SC_OPEN_MAX)
960
961
  fprintf(stderr, "POSIX.1 OPEN_MAX    = %ld\n", sysconf(_SC_OPEN_MAX));
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
962
#if defined(_SC_PAGESIZE)
963
964
  fprintf(stderr, "POSIX.1 PAGESIZE    = %ld\n", sysconf(_SC_PAGESIZE));
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
965

966
  fprintf(stderr, "\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
967

Uwe Schulzweida's avatar
Uwe Schulzweida committed
968
969
#if defined(HAVE_GETRLIMIT)
#if defined(RLIMIT_FSIZE)
970
971
  PRINT_RLIMIT(RLIMIT_FSIZE);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
972
#if defined(RLIMIT_NOFILE)
973
974
  PRINT_RLIMIT(RLIMIT_NOFILE);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
975
#if defined(RLIMIT_STACK)
976
977
978
979
980
981
  PRINT_RLIMIT(RLIMIT_STACK);
#endif
#endif
  fprintf(stderr, "\n");
}

982

983
984
985
static
void check_stacksize()
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
986
987
#if defined(HAVE_GETRLIMIT)
#if defined(RLIMIT_STACK)
988
989
990
991
992
993
994
995
996
997
  {
#define  MIN_STACK_SIZE  67108864L  /* 64MB */
    int status;
    struct rlimit rlim;
    RLIM_T min_stack_size = MIN_STACK_SIZE;

    status = getrlimit(RLIMIT_STACK, &rlim);

    if ( status == 0 )
      {
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
        if ( min_stack_size > rlim.rlim_max ) min_stack_size = rlim.rlim_max;
        if ( rlim.rlim_cur < min_stack_size )
          {
            rlim.rlim_cur = min_stack_size;

            status = setrlimit(RLIMIT_STACK, &rlim);
            if ( Debug )
              {
                if ( status == 0 )
                  {
                    fprintf(stderr, "Set stack size to %ld\n", (long) min_stack_size);
                    PRINT_RLIMIT(RLIMIT_STACK);
                  }
                else
                  fprintf(stderr, "Set stack size to %ld failed!\n", (long) min_stack_size);
              }
          }
1015
1016
1017
1018
1019
      }
  }
#endif
#endif
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1020

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1021
1022
1023
1024
1025
static
void cdo_set_options(void)
{
  if ( Debug )
    {
1026
      fprintf(stderr, "CDO_CMOR_Mode       = %d\n", CDO_CMOR_Mode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1027
1028
1029
1030
      fprintf(stderr, "CDO_netcdf_hdr_pad  = %d\n", CDO_netcdf_hdr_pad);
      fprintf(stderr, "\n");
    }
  
1031
  if ( CDO_CMOR_Mode )          cdiDefGlobal("CMOR_MODE", CDO_CMOR_Mode);
1032
  if ( CDO_netcdf_hdr_pad > 0 ) cdiDefGlobal("NETCDF_HDR_PAD", CDO_netcdf_hdr_pad);  
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1033
1034
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1035

1036
static
1037
long str_to_int(const char *intstring)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
{
  long intval = -1;
  long fact = 1;

  if ( intstring )
    {
      int loop, len;

      len = (int) strlen(intstring);
      for ( loop = 0; loop < len; loop++ )
Yvonne Kuestermann's avatar
Yvonne Kuestermann committed
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
        {
          if ( ! isdigit((int) intstring[loop]) )
            {
              switch ( tolower((int) intstring[loop]) )
                {
                case 'k':  fact = 1024;        break;
                case 'm':  fact = 1048576;     break;
                case 'g':  fact = 1073741824;  break;
                default:   fact = 0;           break;
                }
              break;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1061
1062
1063
1064

      if ( fact ) intval = fact*atol(intstring);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1065
  return intval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1066
1067
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1068
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1069
int parse_options_long(int argc, char *argv[])
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1070
1071
{
  int c;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1072
  int lnetcdf_hdr_pad;
1073
  int luse_fftw;
1074
  int lgridsearchnn;
1075
  int lgridsearchradius;
1076
  int lremap_genweights;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1077
  int lpercentile;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1078
  int lprintoperators = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1079
  int lenableexcept;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1080
1081

  struct cdo_option opt_long[] =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1082
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1083
      { "percentile",        required_argument,        &lpercentile,  1  },
1084
1085
1086
1087
      { "netcdf_hdr_pad",    required_argument,    &lnetcdf_hdr_pad,  1  },
      { "header_pad",        required_argument,    &lnetcdf_hdr_pad,  1  },
      { "hdr_pad",           required_argument,    &lnetcdf_hdr_pad,  1  },
      { "use_fftw",          required_argument,          &luse_fftw,  1  },
1088
      { "gridsearchnn",      required_argument,      &lgridsearchnn,  1  },
1089
      { "gridsearchradius",  required_argument,  &lgridsearchradius,  1  },
1090
      { "remap_genweights",  required_argument,  &lremap_genweights,  1  },