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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
5
  Copyright (C) 2003-2014 Uwe Schulzweida, Uwe.Schulzweida@zmaw.de
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  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.
*/

/*
   This module contains the following operators:
*/

#include <ctype.h>  /* isspace */

Ralf Mueller's avatar
Ralf Mueller committed
24
#include <cdi.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25
26
#include "cdo.h"
#include "cdo_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
27
#include "counter.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28

Uwe Schulzweida's avatar
Uwe Schulzweida committed
29
30
31
32

typedef struct
{
  int   param;
33
34
35
  char  name[CDI_MAX_NAME];
  char  longname[CDI_MAX_NAME];
  char  units[CDI_MAX_NAME];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
36
37
38
39
40
41
42
43
} vars_t;

vars_t *all_vars = NULL;

int gl_streamID = 0;
int gl_vlistID = 0;
int gl_varID = 0;
int gl_nvars = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
44
int levelID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
45
46
47
int gl_tsID1 = 0;
int gl_tsID2 = 0;
double *gl_data = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
48
49
50
51
52
53
54
55
56

#define MAX_LINE 256

int Done = 0;

int com_help(char *);
int com_list(char *);
int com_quit(char *);
int com_stat(char *);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
57
int com_set(char *);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
int com_vars(char *);
//int com_stat(char *);


typedef struct {
  char  *name; /* User printable name of the function. */
  int  (*func)(char *); /* Function to call to do the job. */
  char  *doc; /* Documentation for this function. */
}
command_t;

command_t commands[] = {
  { "help", com_help, "Display this text" },
  { "?",    com_help, "Synonym for 'help'" },
  { "list", com_list, "List files in DIR" },
  { "quit", com_quit, "Quit using CDO" },
  { "stat", com_stat, "Statistic for selected field" },
Uwe Schulzweida's avatar
Uwe Schulzweida committed
75
  { "set",  com_set,  "set variables" },
Uwe Schulzweida's avatar
Uwe Schulzweida committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  { "vars", com_vars, "list variables" },
  //  { "stat", com_stat, "Print out statistics on FILE" },
  { NULL, NULL, NULL }
};


/* Return non-zero if ARG is a valid argument for CALLER, else print
an error message and return zero. */
int valid_argument (char *caller, char *arg)
{
  if (!arg || !*arg)
    {
      fprintf (stderr, "%s: Argument required.\n", caller);
      return (0);
    }
  return (1);
}

/* Print out help for ARG, or for all of the commands if ARG is not present. */
int com_help(char *arg)
{
  int i;
  int printed = 0;

  for ( i = 0; commands[i].name; i++ )
    {
      if (!*arg || (strcmp (arg, commands[i].name) == 0))
	{
	  printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
	  printed++;
	}
    }

  if ( !printed )
    {
Ralf Mueller's avatar
Ralf Mueller committed
111
      printf ("No commands match '%s'. Possibilties are:\n", arg);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
      for (i = 0; commands[i].name; i++)
	{
	  /* Print in six columns. */
	  if ( printed == 6 )
	    {
	      printed = 0;
	      printf ("\n");
	    }
	  printf("%s\t", commands[i].name);
	  printed++;
	}

      if (printed) printf ("\n");
    }

  return (0);
}


/* List the file(s) named in arg. */
int com_list(char *arg)
{
  if (!arg)
    arg = "";

  return (0);
}

/* The user wishes to quit using this program. Just set DONE non-zero. */
int com_quit(char *arg)
{
  Done = 1;

  return (0);
}


int com_stat(char *arg)
{
  int nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
152
  int tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
153

Uwe Schulzweida's avatar
Uwe Schulzweida committed
154
155
156
  fprintf(stdout, "name=%s\n", all_vars[gl_varID].name);

  for ( tsID = gl_tsID1; tsID <= gl_tsID2; ++tsID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
158
      nrecs = streamInqTimestep(gl_streamID, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
159
      if ( nrecs == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
161
162
163
164
165
166
167
168
169
170
171
172
	  fprintf(stderr, "Timestep %d out of range!\n", tsID+1);
	  break;
	}
      else
	{
	  int i;
	  int nmiss;
	  int gridsize;
	  double fmin = 1.e50 , fmax = -1.e50, fmean = 0;
	  counter_t counter;
	  
	  counter_start(&counter);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
174
	  streamReadVarSlice(gl_streamID, gl_varID, levelID, gl_data, &nmiss);
	  gridsize = gridInqSize(vlistInqVarGrid(gl_vlistID, gl_varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
175
176
	  for ( i = 0; i < gridsize; ++i )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
177
178
179
	      if ( gl_data[i] < fmin ) fmin = gl_data[i];
	      if ( gl_data[i] > fmax ) fmax = gl_data[i];
	      fmean += gl_data[i];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
180
181
182
183
	    }
	  fmean /= gridsize;
	  counter_stop(&counter);
	  
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184
185
	  fprintf(stdout, "timestep=%d %g %g %g (%gs)\n",
		  tsID+1, fmin, fmean, fmax,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
186
		  counter_cputime(counter));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
188
	}
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
189
190
191
192
193
194
195
196
197

  return (0);
}


int com_set(char *arg)
{
  printf("com_set: %s\n", arg);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
198
199
200
201
202
203
204
  return (0);
}


int com_vars(char *arg)
{
  int varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
  char paramstr[32];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
206

Uwe Schulzweida's avatar
Uwe Schulzweida committed
207
208
  if ( !arg ) arg = "";
  printf("com_vars: %s %d\n", arg, gl_nvars);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
209

Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
  for ( varID = 0; varID < gl_nvars; ++varID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
211
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
212
213
214
215
      cdiParamToString(all_vars[varID].param, paramstr, sizeof(paramstr));

      fprintf(stdout,"varID=%3d, param=%s, name=%s %s %s\n",
	      varID+1, paramstr, all_vars[varID].name, all_vars[varID].longname, all_vars[varID].units);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216
217
218
219
220
221
    }

  return (0);
}

/* Look up NAME as the name of a command, and return a pointer to that
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222
   command. Return a NULL pointer if NAME isn't a command name. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
command_t *find_command(char *name)
{
  int i;

  for ( i = 0; commands[i].name; i++ )
    if ( strcmp(name, commands[i].name) == 0)
      return (&commands[i]);

  return ((command_t *)NULL);
}

/* Execute a command line. */
int execute_line(char *line)
{
  int i;
  command_t *command;
  char *word;

  /* Isolate the command word. */
  i = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
243
  while ( line[i] && isspace(line[i]) )  i++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
  word = line + i;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
245
  while ( line[i] && !isspace(line[i]) ) i++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294

  if ( line[i] ) line[i++] = '\0';

  command = find_command(word);
  if ( !command )
    {
      fprintf (stderr, "%s: No such command!\n", word);
      return (-1);
    }
  /* Get argument to command, if any. */
  while ( isspace(line[i]) ) i++;

  word = line + i;
  /* Call the function. */
  return ((*(command->func)) (word));
}

/* Strip isspace from the start and end of STRING. Return a pointer into STRING. */
char *stripwhite(char *string)
{
  char *s, *t;
  for (s = string; isspace(*s); s++)
    ;
  if (*s == 0)
    return (s);
  t = s + strlen (s) - 1;
  while (t > s && isspace(*t))
    t--;
  *++t = '\0';

  return s;
}


void readcmd(const char *prompt, char *line, int size)
{
  fputs(prompt, stdout);
  fflush(stdout);

  *line = '\0';
  if ( fgets(line, size, stdin) )
    {
      char *newline = strchr(line, '\n'); /* check for trailing '\n' */
      if ( newline )
	*newline = '\0'; /* overwrite the '\n' with a terminating null */
    }
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
void command_init()
{
  int gridsize;
  int taxisID;
  int varID;

  gl_vlistID = streamInqVlist(gl_streamID);
  taxisID = vlistInqTaxis(gl_vlistID);

  gridsize = vlistGridsizeMax(gl_vlistID);
  gl_data = (double *) malloc(gridsize*sizeof(double));

  gl_nvars = vlistNvars(gl_vlistID);
  all_vars = (vars_t *) malloc(gl_nvars*sizeof(vars_t));

  for ( varID = 0; varID < gl_nvars; ++varID )
    {
      all_vars[varID].param   = vlistInqVarParam(gl_vlistID, varID);
      vlistInqVarName(gl_vlistID, varID, all_vars[varID].name);
      vlistInqVarLongname(gl_vlistID, varID, all_vars[varID].longname);
      vlistInqVarUnits(gl_vlistID, varID, all_vars[varID].units);
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
320
321
322

void *Command(void *argument)
{
  int nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
323
  int recID, varID, levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324
325
326
327
328
329
330
331
332
333
334
  int nmiss;
  double s_utime, s_stime;
  double e_utime, e_stime;
  double c_cputime = 0, c_usertime = 0, c_systime = 0;
  char line[MAX_LINE];
  char *s;
 
  cdoInitialize(argument);

  processStartTime(&s_utime, &s_stime);

335
  gl_streamID = streamOpenRead(cdoStreamName(0)->args);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
336

Uwe Schulzweida's avatar
Uwe Schulzweida committed
337
338
  command_init();
  
Uwe Schulzweida's avatar
Uwe Schulzweida committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  /* Loop reading and executing lines until the user quits. */
  while ( !Done )
    {
      readcmd("cdo cmd> ", line, MAX_LINE);

      /* Remove leading and trailing whitespace from the line.
	 Then, if there is anything left, add it to the history list
	 and execute it. */
      s = stripwhite(line);
      if ( *s ) execute_line(s);
    }


/*
  while ( readline(stdin, line, MAX_LINE) )
    {
      linep = line;
      
      if      ( strcmp(linep, "exit") == 0 ) break;
      else if ( strcmp(linep, "vars") == 0 )
	{
	  int varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361
	  int nvars = vlistNvars(gl_vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
362
363
364
365
366
367
368
369
	  for ( varID = 0; varID < nvars; ++nvars )
	    {
	      fprintf(stdout,"varID %d\n", varID);
	    }
	}
    }
*/
  
Uwe Schulzweida's avatar
Uwe Schulzweida committed
370
  streamClose(gl_streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371

Uwe Schulzweida's avatar
Uwe Schulzweida committed
372
373
  if ( gl_data ) free(gl_data);
  if ( all_vars ) free(all_vars);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  
  cdoProcessTime(&e_utime, &e_stime);

  c_usertime = e_utime - s_utime;
  c_systime  = e_stime - s_stime;
  c_cputime  = c_usertime + c_systime;

  s_utime = e_utime;
  s_stime = e_stime;

  cdoPrint("%.2fs %.2fs %.2fs", c_usertime, c_systime, c_cputime);

  cdoFinish();

  return (0);
}