~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/libs/uti/sge_parse_num_par.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 * 
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 * 
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 * 
 
9
 * 
 
10
 *  Sun Industry Standards Source License Version 1.2
 
11
 *  =================================================
 
12
 *  The contents of this file are subject to the Sun Industry Standards
 
13
 *  Source License Version 1.2 (the "License"); You may not use this file
 
14
 *  except in compliance with the License. You may obtain a copy of the
 
15
 *  License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
 
16
 * 
 
17
 *  Software provided under this License is provided on an "AS IS" basis,
 
18
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 
19
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 
20
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 
21
 *  See the License for the specific provisions governing your rights and
 
22
 *  obligations concerning the Software.
 
23
 * 
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 * 
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 * 
 
28
 *   All Rights Reserved.
 
29
 * 
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
 
 
33
#include <stdio.h>
 
34
#include <string.h>
 
35
#include <stdlib.h>
 
36
#include <ctype.h>
 
37
#include <math.h>
 
38
#include <float.h>
 
39
 
 
40
#include "sgermon.h"
 
41
#include "sge_answer.h"
 
42
#include "sge_log.h"
 
43
#include "sge_string.h"
 
44
#include "sge_parse_num_par.h"
 
45
#include "symbols.h"
 
46
 
 
47
#include "msg_utilib.h"
 
48
 
 
49
 
 
50
#if defined(IRIX)
 
51
   /* to be independent from irix' compiler options */
 
52
#  undef RLIM_INFINITY
 
53
#  define  RLIM_INFINITY  0x7fffffffffffffffLL
 
54
#elif defined(CRAY)
 
55
#  define  RLIM_INFINITY  0
 
56
#elif defined(WIN32NATIVE)
 
57
#       define RLIM_INFINITY 0
 
58
#endif
 
59
 
 
60
#if !defined(CRAY) && !defined(SOLARIS64) && !defined(SOLARISAMD64)
 
61
#  define RLIM_MAX RLIM_INFINITY
 
62
#else
 
63
#  define RLIM_MAX 0x7fffffffffffffff
 
64
#endif
 
65
 
 
66
#ifdef WIN32NATIVE
 
67
#       define strcasecmp( a, b) stricmp( a, b)
 
68
#       define strncasecmp( a, b, n) strnicmp( a, b, n)
 
69
#endif
 
70
 
 
71
u_long32 sge_parse_num_val(sge_rlim_t *rlimp, double *dvalp, 
 
72
                           const char *str, const char *where, 
 
73
                           char *err_str, int err_len);
 
74
 
 
75
static double get_multiplier(sge_rlim_t *rlimp, char **dptr,
 
76
                             const char *where, char *err_str, int err_len);
 
77
 
 
78
static sge_rlim_t add_infinity(sge_rlim_t rlim, sge_rlim_t offset);
 
79
 
 
80
 
 
81
/* -----------------------------------------
 
82
 
 
83
NAME
 
84
   parse_ulong_val()
 
85
 
 
86
DESCR
 
87
   is a wrapper around sge_parse_num_val()
 
88
   for migration to code that returns an
 
89
   error and does not exit() 
 
90
 
 
91
   parse_ulong_val() should be used instead 
 
92
   of sge_parse_num_val()
 
93
 
 
94
PARAM
 
95
   uvalp - where to write the parsed value
 
96
   type  - one of :
 
97
            TYPE_INT   any number
 
98
            TYPE_TIM   h:m:s
 
99
            TYPE_MEM   [mMkK] postfix
 
100
            TYPE_BOO   true or false
 
101
            TYPE_ACC   user access to queue
 
102
           if type == 0 all above types will get accepted
 
103
 
 
104
   s     - string to parse
 
105
 
 
106
RETURN
 
107
      1 - ok, value in *uvalp is valid
 
108
      0 - parsing error
 
109
 
 
110
NOTES
 
111
   MT-NOTE: parse_ulong_val() is MT safe
 
112
*/
 
113
int parse_ulong_val(double *dvalp, u_long32 *uvalp, u_long32 type, 
 
114
                    const char *s, char *error_str, int error_len) 
 
115
{
 
116
   return extended_parse_ulong_val(dvalp, uvalp, type, s, error_str, error_len, 1, false);
 
117
}
 
118
 
 
119
/* enable_infinity enhancement: if 0 no infinity value is allowed */
 
120
/*    MT-NOTE: extended_parse_ulong_val() is MT safe */
 
121
int extended_parse_ulong_val(double *dvalp, u_long32 *uvalp, u_long32 type,
 
122
                             const char *s, char *error_str, int error_len,
 
123
                             int enable_infinity, bool only_positive) 
 
124
{
 
125
   int retval = 0; /* error */
 
126
   char dummy[10];
 
127
   u_long32 dummy_uval;
 
128
 
 
129
   if (s == NULL) {
 
130
      return 0;
 
131
   }
 
132
 
 
133
   if (only_positive && (strchr(s, '-') != NULL)) {
 
134
      if (error_str) {
 
135
         sge_strlcpy(error_str, MSG_GDI_NUMERICALVALUENOTPOSITIVE, error_len); 
 
136
      } 
 
137
      return 0;
 
138
   }   
 
139
 
 
140
   if ((enable_infinity == 0) && (strcasecmp(s,"infinity") == 0)) {
 
141
      if (error_str) {
 
142
         sge_strlcpy(error_str, MSG_GDI_VALUETHATCANBESETTOINF, error_len); 
 
143
      } 
 
144
      return 0;
 
145
   }
 
146
 
 
147
   if (uvalp == NULL) {
 
148
      uvalp = &dummy_uval;
 
149
   }   
 
150
 
 
151
   /*
 
152
      here we have to convert from string
 
153
      representation of the request value
 
154
      into an ulong value
 
155
   */
 
156
   switch (type) {
 
157
   case TYPE_LOG:
 
158
      retval = sge_parse_loglevel_val(uvalp, s);
 
159
      if (retval != 1) {
 
160
         if (error_str != NULL) {
 
161
            sge_strlcpy(error_str, "loglevel value", error_len); 
 
162
         }
 
163
      } 
 
164
      break;
 
165
 
 
166
   case TYPE_INT:
 
167
   case TYPE_TIM:
 
168
   case TYPE_MEM:
 
169
   case TYPE_BOO:
 
170
   case TYPE_DOUBLE:
 
171
      /* dirty but isolated .. */
 
172
      if (error_str != NULL) {
 
173
         *uvalp = sge_parse_num_val(NULL, dvalp, s, s, error_str, error_len);
 
174
         if (!error_str[0]) /* err msg written ? */
 
175
            retval = 1; /* no error */
 
176
         else {
 
177
            if (type==TYPE_INT)
 
178
               sge_strlcpy(error_str, "integer value", error_len); 
 
179
            else if (type==TYPE_TIM)
 
180
               sge_strlcpy(error_str, "time value", error_len); 
 
181
            else if (type==TYPE_BOO)
 
182
               sge_strlcpy(error_str, "boolean value", error_len); 
 
183
            else if (type==TYPE_DOUBLE)
 
184
               sge_strlcpy(error_str, "double value", error_len); 
 
185
            else
 
186
               sge_strlcpy(error_str, "memory value", error_len); 
 
187
         }
 
188
      } else {
 
189
         dummy[0] = '\0';
 
190
         *uvalp = sge_parse_num_val(NULL, dvalp, s, s, dummy, sizeof(dummy));
 
191
         if (!dummy[0]) { /* err msg written ? */
 
192
            retval = 1; /* no error */
 
193
         }        
 
194
      }
 
195
      break;
 
196
 
 
197
   default:
 
198
      break;
 
199
   }
 
200
   return retval;
 
201
}
 
202
 
 
203
/*----------------------------------------------------------------------*/
 
204
/*    MT-NOTE: sge_parse_loglevel_val() is MT safe */
 
205
bool sge_parse_loglevel_val(u_long32 *uval, const char *s) 
 
206
{
 
207
   bool ret = true;
 
208
 
 
209
   if (s == NULL) {
 
210
      ret = false;
 
211
   } else {
 
212
      if (!strcasecmp("log_crit", s)) {
 
213
         *uval = LOG_CRIT;
 
214
      } else if (!strcasecmp("log_err", s)) {
 
215
         *uval = LOG_ERR;
 
216
      } else if (!strcasecmp("log_warning", s)) {
 
217
         *uval = LOG_WARNING;
 
218
      } else if (!strcasecmp("log_notice", s)) {
 
219
         *uval = LOG_NOTICE;
 
220
      } else if (!strcasecmp("log_info", s)) {
 
221
         *uval = LOG_INFO;
 
222
      } else if (!strcasecmp("log_debug", s)) {
 
223
         *uval = LOG_DEBUG;
 
224
      } else {
 
225
         ret = false;
 
226
      }
 
227
   }
 
228
   return ret;
 
229
}
 
230
 
 
231
/* 
 
232
 * return rlim multiplied with muli 
 
233
 * 
 
234
 * if the result would exceed sge_rlim_t
 
235
 * the result is set to RLIM_INFINITY
 
236
 *
 
237
 * NOTES
 
238
 *     MT-NOTE: mul_infinity() is MT safe
 
239
 */
 
240
sge_rlim_t mul_infinity(sge_rlim_t rlim, sge_rlim_t muli) 
 
241
{
 
242
   if (rlim == RLIM_INFINITY ||
 
243
       muli == RLIM_INFINITY )
 
244
      return RLIM_INFINITY;
 
245
 
 
246
   if ((sge_rlim_t)(RLIM_MAX/muli)<rlim)
 
247
      rlim = RLIM_INFINITY;
 
248
   else
 
249
      rlim *= muli;
 
250
   return rlim;
 
251
}
 
252
 
 
253
/* 
 
254
 * return rlim added to offset 
 
255
 * 
 
256
 * if the result would exceed sge_rlim_t
 
257
 * the result is set to RLIM_INFINITY
 
258
 *
 
259
 * NOTES
 
260
 *     MT-NOTE: add_infinity() is MT safe
 
261
 */
 
262
static sge_rlim_t add_infinity(sge_rlim_t rlim, sge_rlim_t offset) 
 
263
{
 
264
   if (rlim == RLIM_INFINITY || offset == RLIM_INFINITY) {
 
265
      return RLIM_INFINITY;
 
266
   }
 
267
 
 
268
   if ((sge_rlim_t)(RLIM_MAX-offset) < rlim) {
 
269
      rlim = RLIM_INFINITY;
 
270
   } else {
 
271
      rlim += offset;
 
272
   }
 
273
 
 
274
   return rlim;
 
275
}
 
276
 
 
277
/***********************************************************************
 
278
 * get_multiplier -
 
279
 *       get a multiplier for number value attribute requests
 
280
 *
 
281
 *       Attribute requests may look like -l sc=123x,...
 
282
 *       with x being one of
 
283
 *
 
284
 *                k : Multiplier = 1000
 
285
 *                K : Multiplier = 1024
 
286
 *                m : Multiplier = 1000*1000
 
287
 *                M : Multiplier = 1024*1024
 
288
 *                g : Multiplier = 1000*1000*1000
 
289
 *                G : Multiplier = 1024*1024*1024
 
290
 *
 
291
 * NOTES
 
292
 *     MT-NOTE: get_multiplier() is MT safe
 
293
 **********************************************************************/
 
294
 
 
295
static double get_multiplier(sge_rlim_t *rlimp, char **dptr, 
 
296
                             const char *where, char *err_str, int err_len)
 
297
{
 
298
   double mul = 1;
 
299
   *rlimp = 1;
 
300
 
 
301
   /* parse for k,K,m,M multipliers at the end of the value
 
302
    * string; strtod returns dptr to point to this location
 
303
    */
 
304
   switch (**dptr) {
 
305
   case 'k':
 
306
      mul = 1000;
 
307
      *rlimp = 1000;
 
308
      (*dptr)++;
 
309
      break;
 
310
   case 'K':
 
311
      mul = 1024;
 
312
      *rlimp = 1024;
 
313
      (*dptr)++;
 
314
      break;
 
315
   case 'm':
 
316
      mul = 1000 * 1000;
 
317
      *rlimp = 1000 * 1000;
 
318
      (*dptr)++;
 
319
      break;
 
320
   case 'M':
 
321
      mul = 1024 * 1024;
 
322
      *rlimp = 1024 * 1024;
 
323
      (*dptr)++;
 
324
      break;
 
325
   case 'g':
 
326
      mul = 1000 * 1000 * 1000;
 
327
      *rlimp = mul_infinity(mul_infinity(1000, 1000), 1000);
 
328
      (*dptr)++;
 
329
      break;
 
330
   case 'G':
 
331
      mul = 1024 * 1024 * 1024;
 
332
      *rlimp = mul_infinity(mul_infinity(1024, 1024), 1024);
 
333
      (*dptr)++;
 
334
      break;
 
335
   case ',':                    /* no multiplier */
 
336
   case '\0':                   /* no multiplier */
 
337
   case '/':                    /* no multiplier */
 
338
   case ' ':                    /* no multiplier */
 
339
      break;
 
340
   default:
 
341
      snprintf(err_str, err_len, MSG_GDI_UNRECOGNIZEDVALUETRAILER_SS , *dptr, where);
 
342
      return 0;
 
343
   }
 
344
 
 
345
   if ((**dptr != ',') && (**dptr != '\0') && (**dptr != '/')) {
 
346
      snprintf(err_str, err_len, MSG_GDI_UNEXPECTEDENDOFNUMERICALVALUE_SC , where, **dptr);
 
347
      return 0;
 
348
   }
 
349
 
 
350
   return mul;
 
351
}
 
352
 
 
353
/***********************************************************************
 
354
 * sge_parse_num_val -
 
355
 *    parse numeric attribute values from command-line
 
356
 *
 
357
 *    Numeric attribute values may look like -l <attr>=<num><m>,...
 
358
 *    with <num> being a decimal (both integer and fixed float),
 
359
 *    hex and octal constant. <m> is a multiplier (see get_multiplier
 
360
 *    above).
 
361
 *
 
362
 * !new feature!
 
363
 *    
 
364
 *    call the good old parse_num_val() with a non null argument for err_str
 
365
 *    and it will ++NOT++ abort your daemon.
 
366
 *
 
367
 *    in case of a parsing error the err_str gets filled with an error
 
368
 *    message
 
369
 *
 
370
 * NOTES
 
371
 *     MT-NOTE: sge_parse_num_val() is MT safe
 
372
 **********************************************************************/
 
373
 
 
374
u_long32 
 
375
sge_parse_num_val(sge_rlim_t *rlimp, double *dvalp, 
 
376
                  const char *str, const char *where, 
 
377
                  char *err_str, int err_len)
 
378
{
 
379
   double dummy;
 
380
   sge_rlim_t rlim, rlmuli;
 
381
   double dval;
 
382
   u_long32 ldummy;
 
383
   char *dptr;
 
384
   double muli;
 
385
 
 
386
   if (!rlimp)
 
387
      rlimp = &rlim;
 
388
   if (!dvalp)
 
389
      dvalp = &dval;
 
390
 
 
391
   if (err_str)
 
392
      err_str[0] = '\0';
 
393
 
 
394
   if (!strcasecmp(str, "true")) {
 
395
      /* C-language says bool is a numeric. For reasons of simplicity we 
 
396
         agree. */
 
397
      *dvalp = 1;
 
398
      *rlimp = 1;
 
399
      return 1;
 
400
   }
 
401
   else if (!strcasecmp(str, "false")) {
 
402
      *dvalp = 0;
 
403
      *rlimp = 0;
 
404
      return 0;
 
405
   }
 
406
   else if (!strcasecmp(str, "infinity")) {
 
407
      *dvalp = DBL_MAX;       /* use this for comparing limits */
 
408
      *rlimp = RLIM_INFINITY; /* use this for limit setting */
 
409
#ifndef CRAY      
 
410
      return 0xFFFFFFFF;      /* return max ulong in 32 bit */
 
411
#else
 
412
      return RLIM_MAX;
 
413
#endif            
 
414
   }
 
415
   else if (strchr(str, ':')) {
 
416
      /* This is a time value in the format hr:min:sec */
 
417
 
 
418
      /* find the hours first */
 
419
      double t = strtod(str, &dptr);
 
420
      if (t > 0x7fffffff) {
 
421
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEFORHOUREXCEEDED_SS , where, str);
 
422
         return 0;
 
423
      }
 
424
      ldummy = (u_long32)(3600 * t);
 
425
      *rlimp = (sge_rlim_t)(long)mul_infinity(t, 3600.0);
 
426
      *dvalp = 3600 * t;
 
427
 
 
428
      if ((*dptr) != ':') {  
 
429
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
 
430
         return 0;
 
431
      }
 
432
      /* now go for the minutes */
 
433
      dptr++;
 
434
      t = strtod(dptr, &dptr);
 
435
      if (t > 0x7fffffff) {
 
436
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEFORMINUTEEXCEEDED_SS , where, str);
 
437
         return 0;
 
438
      }
 
439
      ldummy += (u_long32)(60 * t);
 
440
      *rlimp = add_infinity(*rlimp, (sge_rlim_t)(60*t));
 
441
      *dvalp += 60 * t;
 
442
 
 
443
      if ((*dptr) != ':') {
 
444
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
 
445
         return 0;
 
446
      }
 
447
      /* the seconds finally */
 
448
      dptr++;
 
449
 
 
450
      t = strtod(dptr, &dptr);
 
451
      ldummy += (u_long32)t;
 
452
      *rlimp = (sge_rlim_t)(long)add_infinity(*rlimp, t);
 
453
      *dvalp += t;
 
454
 
 
455
      while(*dptr) {
 
456
         if (!isspace((int) *dptr)) {
 
457
            snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALID_SS , where, str);
 
458
            return 0;
 
459
         }
 
460
         dptr++;
 
461
      }
 
462
 
 
463
      return (ldummy);
 
464
 
 
465
   }
 
466
   else if (strchr(str, '.') || *str != '0') {
 
467
      /* obviously this is no hex and no oct
 
468
       * ==> allow for both decimal and fixed float
 
469
       */
 
470
       
 
471
      double t = strtod(str, &dptr);
 
472
      
 
473
      if (t > 0x7fffffff)
 
474
         dummy = 0x7fffffff;
 
475
      else
 
476
         dummy = t;
 
477
   
 
478
      if ((dummy == 0.0) && (dptr == str)) {    /* no valid number ==> bail */
 
479
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALIDNONUMBER_SS , where, str);
 
480
         return 0;
 
481
      }
 
482
 
 
483
      /* OK, we got it */
 
484
      if (!(muli = get_multiplier(&rlmuli, &dptr, where, err_str, err_len)))
 
485
         return 0;
 
486
      dummy =    (u_long32) (dummy * muli);
 
487
      *dvalp =              t * muli;
 
488
 
 
489
      if (t > RLIM_MAX || rlmuli>= RLIM_MAX || (double)(RLIM_MAX/muli)<t)
 
490
         *rlimp = RLIM_INFINITY;
 
491
      else 
 
492
         *rlimp = (sge_rlim_t)(t*rlmuli);
 
493
 
 
494
      return (u_long32)dummy;
 
495
 
 
496
   }
 
497
   else {                       /* if ( strchr(str,'.') || *str != '0' ) */
 
498
      /* This is either a hex or an octal ==> no fixed float allowed;
 
499
       * just use strtol
 
500
       */
 
501
      u_long32 t = strtol(str, &dptr, 0);   /* base=0 will handle both hex and oct */
 
502
      ldummy = t;
 
503
      *rlimp = t;
 
504
      *dvalp = t;
 
505
 
 
506
      if (dptr == str) {        /* no valid number ==> bail */
 
507
         snprintf(err_str, err_len, MSG_GDI_NUMERICALVALUEINVALIDNOHEXOCTNUMBER_SS , where, str);
 
508
         return 0;
 
509
      }
 
510
      /* OK, we got it */
 
511
      if (!(muli = get_multiplier(&rlmuli, &dptr, where, err_str, err_len)))
 
512
         return 0;
 
513
      ldummy *= (u_long32)muli;
 
514
      *rlimp = mul_infinity(*rlimp, rlmuli);
 
515
      *dvalp *= muli;
 
516
 
 
517
      return (u_long32)ldummy;
 
518
   }
 
519
}