~ubuntu-branches/ubuntu/precise/code-saturne/precise

« back to all changes in this revision

Viewing changes to src/mei/mei_evaluate.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2011-11-24 00:00:08 UTC
  • mfrom: (6.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20111124000008-2vo99e38267942q5
Tags: 2.1.0-3
Install a missing file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*!
 
2
 * \file mei_evaluate.c
 
3
 *
 
4
 * \brief Build an interpreter for a mathematical expression
 
5
 */
 
6
 
 
7
/*
 
8
  This file is part of Code_Saturne, a general-purpose CFD tool.
 
9
 
 
10
  Copyright (C) 1998-2011 EDF S.A.
 
11
 
 
12
  This program is free software; you can redistribute it and/or modify it under
 
13
  the terms of the GNU General Public License as published by the Free Software
 
14
  Foundation; either version 2 of the License, or (at your option) any later
 
15
  version.
 
16
 
 
17
  This program is distributed in the hope that it will be useful, but WITHOUT
 
18
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
19
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 
20
  details.
 
21
 
 
22
  You should have received a copy of the GNU General Public License along with
 
23
  this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
24
  Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
25
*/
 
26
 
 
27
/*----------------------------------------------------------------------------*/
 
28
 
 
29
/*----------------------------------------------------------------------------
 
30
 * Standard C library headers
 
31
 *----------------------------------------------------------------------------*/
 
32
 
 
33
#include <assert.h>
 
34
#include <stdarg.h>
 
35
#include <stdio.h>
 
36
#include <string.h>
 
37
#include <math.h>
 
38
 
 
39
/*----------------------------------------------------------------------------
 
40
 * BFT library headers
 
41
 *----------------------------------------------------------------------------*/
 
42
 
 
43
#include <bft_mem.h>
 
44
#include <bft_printf.h>
 
45
#include <bft_error.h>
 
46
 
 
47
/*----------------------------------------------------------------------------
 
48
 * Local headers
 
49
 *----------------------------------------------------------------------------*/
 
50
 
 
51
#include "mei_node.h"
 
52
#include "mei_parser_glob.h"
 
53
#include "mei_parser.h"
 
54
 
 
55
/*----------------------------------------------------------------------------
 
56
 * Header for the current file
 
57
 *----------------------------------------------------------------------------*/
 
58
 
 
59
#include "mei_evaluate.h"
 
60
 
 
61
/*----------------------------------------------------------------------------*/
 
62
 
 
63
#ifdef __cplusplus
 
64
extern "C" {
 
65
#endif /* __cplusplus */
 
66
 
 
67
/*----------------------------------------------------------------------------
 
68
 * Local macro definitions
 
69
 *----------------------------------------------------------------------------*/
 
70
 
 
71
/*!
 
72
 * \brief Default modulo for hash table.
 
73
 */
 
74
 
 
75
#define HASHSIZE 701
 
76
 
 
77
/*=============================================================================
 
78
 * Specific pragmas to disable some unrelevant warnings
 
79
 *============================================================================*/
 
80
 
 
81
/* Globally disable warning on float-comparisons (equality) for GCC and Intel
 
82
   compilers as we do it on purpose (infinite precision algorithm). */
 
83
 
 
84
#if defined(__GNUC__) && !defined(__ICC)
 
85
#pragma GCC diagnostic ignored "-Wfloat-equal"
 
86
#elif defined(__ICC)
 
87
#pragma warning disable 1572
 
88
#endif
 
89
 
 
90
/*============================================================================
 
91
 * Private function definitions
 
92
 *============================================================================*/
 
93
 
 
94
/*!
 
95
 * \brief Copy the symbol table pointer into the each node of the interpreter.
 
96
 *
 
97
 * \param [in] n node of the interpreter
 
98
 * \param [in] h table of symbols
 
99
 */
 
100
 
 
101
static void
 
102
_init_symbol_table(mei_node_t    *n,
 
103
                   hash_table_t  *h)
 
104
{
 
105
  int i;
 
106
 
 
107
  if (!n) return;
 
108
 
 
109
  /* Copy the symbol table pointer into the current node */
 
110
 
 
111
  n->ht = h;
 
112
 
 
113
  /* Search the next node in the interpreter */
 
114
 
 
115
  if (n->flag == FUNC1) {
 
116
    _init_symbol_table(n->type->func.op, h);
 
117
  }
 
118
  else if (n->flag == FUNC2 || n->flag == FUNC3 || n->flag == FUNC4) {
 
119
    for (i = 0; i < n->type->funcx.nops; i++)
 
120
      _init_symbol_table(n->type->funcx.op[i], h);
 
121
  }
 
122
  else if (n->flag == OPR) {
 
123
    for (i = 0; i < n->type->opr.nops; i++)
 
124
      _init_symbol_table(n->type->opr.op[i], h);
 
125
  }
 
126
}
 
127
 
 
128
/*!
 
129
 * \brief Return the number of errors related to the use of undefined symbol
 
130
 * in the expression.
 
131
 *
 
132
 * \param [in] p node of an interpreter
 
133
 * \return number of undefined symbol
 
134
 */
 
135
 
 
136
static int
 
137
_check_symbol(mei_node_t  *p)
 
138
{
 
139
  int iok = 0;
 
140
  int l;
 
141
 
 
142
  if (!p) return 0;
 
143
 
 
144
  switch(p->flag) {
 
145
 
 
146
  case CONSTANT:
 
147
    return 0;
 
148
 
 
149
  case ID:
 
150
    if (mei_hash_table_lookup(p->ht, p->type->id.i) == NULL) {
 
151
 
 
152
      /* bft_printf("Warning: identifier %s is unknown\n", p->type->id.i); */
 
153
      /* bft_printf("- line:   %i \n", p->type->id.l); */
 
154
      /* bft_printf("- column: %i \n", p->type->id.c); */
 
155
 
 
156
      BFT_REALLOC(mei_glob_label_list,  mei_glob_ierr_list+1, char*);
 
157
      BFT_REALLOC(mei_glob_line_list,   mei_glob_ierr_list+1, int);
 
158
      BFT_REALLOC(mei_glob_column_list, mei_glob_ierr_list+1, int);
 
159
 
 
160
      l = strlen("Warning, identifier ")+1;
 
161
      BFT_MALLOC(mei_glob_label_list[mei_glob_ierr_list], l, char);
 
162
      strncpy(mei_glob_label_list[mei_glob_ierr_list], "Warning: identifier ", l);
 
163
 
 
164
      l = l + strlen(p->type->id.i);
 
165
      BFT_REALLOC(mei_glob_label_list[mei_glob_ierr_list], l, char);
 
166
      strncat(mei_glob_label_list[mei_glob_ierr_list], p->type->id.i, l);
 
167
 
 
168
      l = l + strlen(" is unknown.\n");
 
169
      BFT_REALLOC(mei_glob_label_list[mei_glob_ierr_list], l, char);
 
170
      strncat(mei_glob_label_list[mei_glob_ierr_list], " is unknown.\n", l);
 
171
 
 
172
      mei_glob_line_list[mei_glob_ierr_list]   = p->type->id.l;
 
173
      mei_glob_column_list[mei_glob_ierr_list] = p->type->id.c;
 
174
 
 
175
      mei_glob_ierr_list++;
 
176
 
 
177
      return 1;
 
178
    }
 
179
    return 0;
 
180
 
 
181
  case FUNC1:
 
182
    if (mei_hash_table_lookup(p->ht, p->type->func.name) == NULL) {
 
183
 
 
184
      /* it is normally impossible to arrive here */
 
185
      /* because the parser has already checked function names */
 
186
 
 
187
      bft_error(__FILE__, __LINE__, 0, "Error: _check_symbol\n");
 
188
 
 
189
      return 1;
 
190
    }
 
191
    return _check_symbol(p->type->func.op);
 
192
 
 
193
  case FUNC2:
 
194
    if (mei_hash_table_lookup(p->ht, p->type->funcx.name) == NULL) {
 
195
 
 
196
      /* It is normally impossible to arrive here */
 
197
      /* because the parser has already checked function names */
 
198
 
 
199
      bft_error(__FILE__, __LINE__, 0, "Error: _check_symbol\n");
 
200
 
 
201
      return 1;
 
202
    }
 
203
    iok  = _check_symbol(p->type->funcx.op[0]);
 
204
    iok += _check_symbol(p->type->funcx.op[1]);
 
205
    return iok;
 
206
 
 
207
  case FUNC3:
 
208
    bft_error(__FILE__, __LINE__, 0, "not implemented yet \n");
 
209
    break;
 
210
 
 
211
  case FUNC4:
 
212
    bft_error(__FILE__, __LINE__, 0, "not implemented yet \n");
 
213
    break;
 
214
 
 
215
  case OPR:
 
216
 
 
217
    switch (p->type->opr.oper) {
 
218
 
 
219
    case IF:
 
220
      iok  = _check_symbol(p->type->opr.op[0]);
 
221
      iok += _check_symbol(p->type->opr.op[1]);
 
222
      if (p->type->opr.nops > 2)
 
223
        iok += _check_symbol(p->type->opr.op[2]);
 
224
      return iok;
 
225
 
 
226
    case PRINT:
 
227
      return _check_symbol(p->type->opr.op[0]);
 
228
 
 
229
    case '=':
 
230
      mei_hash_table_insert(p->ht,
 
231
                            p->type->opr.op[0]->type->id.i,
 
232
                            CONSTANT,
 
233
                            0,
 
234
                            NULL,
 
235
                            NULL,
 
236
                            NULL,
 
237
                            NULL);
 
238
      return _check_symbol(p->type->opr.op[1]);
 
239
 
 
240
    case UPLUS:
 
241
      return _check_symbol(p->type->opr.op[0]);
 
242
 
 
243
    case UMINUS:
 
244
      return _check_symbol(p->type->opr.op[0]);
 
245
 
 
246
    case '!':
 
247
      return _check_symbol(p->type->opr.op[0]);
 
248
 
 
249
    default:
 
250
      iok  = _check_symbol(p->type->opr.op[0]);
 
251
      iok += _check_symbol(p->type->opr.op[1]);
 
252
      return iok;
 
253
    }
 
254
  }
 
255
 
 
256
  bft_error(__FILE__, __LINE__, 0, "Error: _check_symbol\n");
 
257
 
 
258
  return iok;
 
259
}
 
260
 
 
261
/*!
 
262
 * \brief Return the evaluation of the expression.
 
263
 *
 
264
 * \param [in] p node of an interpreter
 
265
 * \return value of evaluated expression
 
266
 */
 
267
 
 
268
static double
 
269
_evaluate(mei_node_t  *p)
 
270
{
 
271
  double t1, t2;
 
272
  func1_t f1;
 
273
  func2_t f2;
 
274
 
 
275
  if (!p) return 0;
 
276
 
 
277
  switch(p->flag) {
 
278
 
 
279
  case CONSTANT:
 
280
    return p->type->con.value;
 
281
 
 
282
  case ID:
 
283
    return (mei_hash_table_lookup(p->ht, p->type->id.i))->data->value;
 
284
 
 
285
  case FUNC1:
 
286
    f1 = (mei_hash_table_lookup(p->ht, p->type->func.name))->data->func;
 
287
    return f1(_evaluate(p->type->func.op));
 
288
 
 
289
  case FUNC2:
 
290
    f2 = (mei_hash_table_lookup(p->ht, p->type->funcx.name))->data->f2;
 
291
    return f2(_evaluate(p->type->funcx.op[0]), _evaluate(p->type->funcx.op[1]));
 
292
 
 
293
  case FUNC3:
 
294
    bft_error(__FILE__, __LINE__, 0, "not implemented\n");
 
295
    break;
 
296
 
 
297
  case FUNC4:
 
298
    bft_error(__FILE__, __LINE__, 0, "not implemented\n");
 
299
    break;
 
300
 
 
301
  case OPR:
 
302
 
 
303
    switch(p->type->opr.oper) {
 
304
 
 
305
    case WHILE:
 
306
      while(_evaluate(p->type->opr.op[0])) _evaluate(p->type->opr.op[1]);
 
307
      return 0;
 
308
 
 
309
    case IF:
 
310
      if (_evaluate(p->type->opr.op[0]))
 
311
        _evaluate(p->type->opr.op[1]);
 
312
      else if (p->type->opr.nops > 2)
 
313
        _evaluate(p->type->opr.op[2]);
 
314
      return 0;
 
315
 
 
316
    case PRINT:
 
317
      bft_printf("PRINT %f\n", _evaluate(p->type->opr.op[0]));
 
318
      return 0;
 
319
 
 
320
    case ';':
 
321
      _evaluate(p->type->opr.op[0]);
 
322
      return _evaluate(p->type->opr.op[1]);
 
323
 
 
324
    case '=':
 
325
      t2 = _evaluate(p->type->opr.op[1]);
 
326
      mei_hash_table_insert(p->ht,
 
327
                            p->type->opr.op[0]->type->id.i,
 
328
                            CONSTANT,
 
329
                            t2,
 
330
                            NULL,
 
331
                            NULL,
 
332
                            NULL,
 
333
                            NULL);
 
334
      return 0;
 
335
 
 
336
    case UPLUS:
 
337
      return _evaluate(p->type->opr.op[0]);
 
338
 
 
339
    case UMINUS:
 
340
      return -_evaluate(p->type->opr.op[0]);
 
341
 
 
342
    case '+':
 
343
      return _evaluate(p->type->opr.op[0]) + _evaluate(p->type->opr.op[1]);
 
344
 
 
345
    case '-':
 
346
      return _evaluate(p->type->opr.op[0]) - _evaluate(p->type->opr.op[1]);
 
347
 
 
348
    case '*':
 
349
      return _evaluate(p->type->opr.op[0]) * _evaluate(p->type->opr.op[1]);
 
350
 
 
351
    case '/':
 
352
      t1 = _evaluate(p->type->opr.op[0]);
 
353
      t2 = _evaluate(p->type->opr.op[1]);
 
354
      if (t2)
 
355
        return t1 / t2;
 
356
      else
 
357
        bft_error(__FILE__, __LINE__, 0, "Error: floating point exception\n");
 
358
 
 
359
    case '^':
 
360
      return pow(_evaluate(p->type->opr.op[0]), _evaluate(p->type->opr.op[1]));
 
361
 
 
362
    case '<':
 
363
      return _evaluate(p->type->opr.op[0]) < _evaluate(p->type->opr.op[1]);
 
364
 
 
365
    case '>':
 
366
      return _evaluate(p->type->opr.op[0]) > _evaluate(p->type->opr.op[1]);
 
367
 
 
368
    case '!':
 
369
      return ! _evaluate(p->type->opr.op[0]);
 
370
 
 
371
    case GE:
 
372
      return _evaluate(p->type->opr.op[0]) >= _evaluate(p->type->opr.op[1]);
 
373
 
 
374
    case LE:
 
375
      return _evaluate(p->type->opr.op[0]) <= _evaluate(p->type->opr.op[1]);
 
376
 
 
377
    case NE:
 
378
      return _evaluate(p->type->opr.op[0]) != _evaluate(p->type->opr.op[1]);
 
379
 
 
380
    case EQ:
 
381
      return _evaluate(p->type->opr.op[0]) == _evaluate(p->type->opr.op[1]);
 
382
 
 
383
    case AND:
 
384
      return _evaluate(p->type->opr.op[0]) && _evaluate(p->type->opr.op[1]);
 
385
 
 
386
    case OR:
 
387
      return _evaluate(p->type->opr.op[0]) || _evaluate(p->type->opr.op[1]);
 
388
    }
 
389
  }
 
390
 
 
391
  return 0;
 
392
}
 
393
 
 
394
/*!
 
395
 * \brief Store error message.
 
396
 *
 
397
 * \param [in] ev interpreter
 
398
 */
 
399
 
 
400
static void
 
401
_manage_error(mei_tree_t  *ev)
 
402
{
 
403
  int i;
 
404
  size_t l;
 
405
 
 
406
  assert(ev != NULL);
 
407
 
 
408
  ev->errors = mei_glob_ierr_list;
 
409
 
 
410
  BFT_MALLOC(ev->labels,  mei_glob_ierr_list, char*);
 
411
  BFT_MALLOC(ev->lines,   mei_glob_ierr_list, int);
 
412
  BFT_MALLOC(ev->columns, mei_glob_ierr_list, int);
 
413
 
 
414
  for (i=0; i<ev->errors; i++) {
 
415
    ev->lines[i]   = mei_glob_line_list[i];
 
416
    ev->columns[i] = mei_glob_column_list[i];
 
417
 
 
418
    l = strlen(mei_glob_label_list[i]) + 1;
 
419
    BFT_MALLOC(ev->labels[i], l, char);
 
420
    strncpy(ev->labels[i], mei_glob_label_list[i], l);
 
421
  }
 
422
}
 
423
 
 
424
/*!
 
425
 * \brief Check if the symbol \em str exists in the expression stored
 
426
 *  in \em ev. Return 0 if the symbol exists in the symbol table, 1 if not.
 
427
 *
 
428
 * \param [in] ev  interpreter in which we want to know if \em str exists
 
429
 * \param [in] str symbol to find
 
430
 * \return 0 if the symbol exists in the symbol table, 1 if not
 
431
 */
 
432
 
 
433
static int
 
434
_find_symbol(mei_tree_t  *ev,
 
435
             const char  *str)
 
436
{
 
437
  int i, iok = 0;
 
438
  size_t l;
 
439
 
 
440
  assert(ev != NULL);
 
441
  assert(str != NULL);
 
442
 
 
443
  if (!mei_hash_table_lookup(ev->symbol, str)) {
 
444
 
 
445
    /* the symbol is not found: this information is stored */
 
446
 
 
447
    iok = 1;
 
448
 
 
449
    i = ev->errors;
 
450
    ev->errors++;
 
451
 
 
452
    if (!ev->labels)
 
453
      BFT_MALLOC(ev->labels, ev->errors, char*);
 
454
    else
 
455
      BFT_REALLOC(ev->labels, ev->errors, char*);
 
456
 
 
457
    l = strlen(str) + 1;
 
458
    BFT_MALLOC(ev->labels[i], l, char);
 
459
    strncpy(ev->labels[i], str, l);
 
460
  }
 
461
 
 
462
  return iok;
 
463
}
 
464
 
 
465
/*============================================================================
 
466
 * Public function definitions
 
467
 *============================================================================*/
 
468
 
 
469
/*!
 
470
 * \brief Returns a new interpreter. The node member is empty,
 
471
 * the string member contains the mathematical expression and
 
472
 * the symbol table is initialize with the standard symbols.
 
473
 *
 
474
 * \param [in] expr string characters of the mathematical expression
 
475
 * \return new empty interpreter
 
476
 */
 
477
 
 
478
mei_tree_t*
 
479
mei_tree_new(const char *const expr)
 
480
{
 
481
    mei_tree_t *ev = NULL;
 
482
    size_t length;
 
483
 
 
484
    assert(expr != NULL);
 
485
 
 
486
    BFT_MALLOC(ev, 1, mei_tree_t);
 
487
 
 
488
    BFT_MALLOC(ev->symbol, 1, hash_table_t);
 
489
 
 
490
    length = strlen(expr)+1;
 
491
    BFT_MALLOC(ev->string, length, char);
 
492
 
 
493
    strncpy(ev->string, expr, length);
 
494
 
 
495
    mei_hash_table_create(ev->symbol, HASHSIZE);
 
496
    ev->symbol->n_inter = 1;
 
497
    mei_hash_table_init(ev->symbol);
 
498
 
 
499
    /* Default initializations */
 
500
 
 
501
    ev->errors  = 0;
 
502
    ev->columns = NULL;
 
503
    ev->lines   = NULL;
 
504
    ev->labels  = NULL;
 
505
    ev->node    = NULL;
 
506
 
 
507
    return ev;
 
508
}
 
509
 
 
510
/*!
 
511
 * \brief Returns a new interpreter. The node member is empty,
 
512
 * the string member contains the mathematical expression and
 
513
 * the symbol table is initialize with a existing table, which is shared by
 
514
 * multiple interpreter.
 
515
 *
 
516
 * \param [in] expr         string characters of the mathematical expression
 
517
 * \param [in] symbol_table shared table of symbols
 
518
 * \return new empty interpreter
 
519
 */
 
520
 
 
521
mei_tree_t*
 
522
mei_tree_new_with_shared_symbols(const char   *const expr,
 
523
                                 hash_table_t *const symbol_table)
 
524
{
 
525
    mei_tree_t *ev = NULL;
 
526
    size_t length;
 
527
 
 
528
    assert(expr != NULL);
 
529
    assert(symbol_table != NULL);
 
530
 
 
531
    BFT_MALLOC(ev, 1, mei_tree_t);
 
532
 
 
533
    length = strlen(expr)+1;
 
534
    BFT_MALLOC(ev->string, length, char);
 
535
 
 
536
    strncpy(ev->string, expr, length);
 
537
 
 
538
    /* copy the adress of the shared table of symbols and
 
539
      incremente the number of interpreters that share this table */
 
540
 
 
541
    ev->symbol = symbol_table;
 
542
    ev->symbol->n_inter++;
 
543
 
 
544
    /* Default initializations */
 
545
 
 
546
    ev->errors  = 0;
 
547
    ev->columns = NULL;
 
548
    ev->lines   = NULL;
 
549
    ev->labels  = NULL;
 
550
    ev->node    = NULL;
 
551
 
 
552
    return ev;
 
553
}
 
554
 
 
555
/*!
 
556
 * \brief Returns a new table of symbols.
 
557
 * The table contains standard mathematical symbols.
 
558
 *
 
559
 * \return table of symbols
 
560
 */
 
561
 
 
562
hash_table_t*
 
563
mei_table_symbols_new(void)
 
564
{
 
565
    hash_table_t *ht = NULL;
 
566
 
 
567
    BFT_MALLOC(ht, 1, hash_table_t);
 
568
 
 
569
    mei_hash_table_create(ht, HASHSIZE);
 
570
    ht->n_inter = 0;
 
571
    mei_hash_table_init(ht);
 
572
 
 
573
    return ht;
 
574
}
 
575
 
 
576
/*!
 
577
 * \brief Call the yacc parser.
 
578
 * Return 0 if the parsing is ok, or the number of errors, if errors occurs.
 
579
 *
 
580
 * \param [in] ev interpreter
 
581
 * \return number of parsing errors
 
582
 */
 
583
 
 
584
int
 
585
mei_tree_builder(mei_tree_t *ev)
 
586
{
 
587
    int i;
 
588
 
 
589
    assert(ev != NULL);
 
590
 
 
591
    /* Initialize the global variables of the parser */
 
592
    /*-----------------------------------------------*/
 
593
 
 
594
    /* Initialize the pointer on the node returned by the parser */
 
595
 
 
596
    mei_glob_root = NULL;
 
597
 
 
598
    /* Begin/end of the expression is set in these global variables */
 
599
 
 
600
    mei_glob_string_begin = ev->string;
 
601
    mei_glob_string_end   = ev->string + strlen(ev->string);
 
602
 
 
603
    /* Initialize line and column counters,
 
604
       incrementation is done in scanner.l */
 
605
 
 
606
    mei_glob_line   = 1;
 
607
    mei_glob_column = 1;
 
608
 
 
609
    /* Initialize error counter
 
610
       incrementation is done in parser.y (yyerror function) */
 
611
 
 
612
    mei_glob_ierr_list = 0;
 
613
 
 
614
    /* Parse the expression string and construct the interpreter */
 
615
    /*-----------------------------------------------------------*/
 
616
 
 
617
    yyparse();
 
618
 
 
619
    if (mei_glob_ierr_list)
 
620
    {
 
621
 
 
622
        /* Parsing error: copy informations for display */
 
623
 
 
624
        _manage_error(ev);
 
625
 
 
626
       /* Free memory. Warning: if there is more than one error,
 
627
          not all pointers are cleaning */
 
628
 
 
629
        mei_free_node(mei_glob_root);
 
630
    }
 
631
    else
 
632
    {
 
633
        /* If the parsing is ok, copy the data in the current interpreter */
 
634
 
 
635
        ev->node = mei_glob_root;
 
636
 
 
637
        /* For all nodes of the interpreter, copy the symbols table pointer */
 
638
 
 
639
        _init_symbol_table(ev->node, ev->symbol);
 
640
 
 
641
        /* Check if all new symbols are defined in the expression string */
 
642
 
 
643
        mei_glob_ierr_list = _check_symbol(ev->node);
 
644
 
 
645
        if (mei_glob_ierr_list)
 
646
        {
 
647
 
 
648
            /* Check symbol error: copy informations for display */
 
649
 
 
650
            /* if (mei_glob_ierr_list == 1) */
 
651
            /*   bft_printf("Warning: there is %i error.\n",  mei_glob_ierr_list); */
 
652
            /* else if (mei_glob_ierr_list > 1) */
 
653
            /*   bft_printf("Warning: there are %i errors.\n", mei_glob_ierr_list); */
 
654
 
 
655
          _manage_error(ev);
 
656
        }
 
657
 
 
658
    }
 
659
 
 
660
    /* Free memory of the parser global variables if necessary */
 
661
 
 
662
    for (i=0; i < mei_glob_ierr_list; i++)
 
663
        BFT_FREE(mei_glob_label_list[i]);
 
664
 
 
665
    BFT_FREE(mei_glob_label_list);
 
666
    BFT_FREE(mei_glob_line_list);
 
667
    BFT_FREE(mei_glob_column_list);
 
668
 
 
669
    return mei_glob_ierr_list;
 
670
}
 
671
 
 
672
/*!
 
673
 * \brief Inserts a constant (label and value) in the table of symbols
 
674
 * associated to an interpreter.
 
675
 *
 
676
 * \param [in] ev    interpreter
 
677
 * \param [in] str   label of the constant
 
678
 * \param [in] value value associated to the constant
 
679
 */
 
680
 
 
681
void
 
682
mei_tree_insert(mei_tree_t    *ev,
 
683
                const char    *str,
 
684
                const double   value)
 
685
{
 
686
  assert(ev != NULL);
 
687
  assert(str != NULL);
 
688
 
 
689
  mei_hash_table_insert(ev->symbol,
 
690
                        str,
 
691
                        CONSTANT,
 
692
                        value,
 
693
                        NULL,
 
694
                        NULL,
 
695
                        NULL,
 
696
                        NULL);
 
697
}
 
698
 
 
699
/*!
 
700
 * \brief Inserts a constant (label and value) in a table of symbols.
 
701
 *
 
702
 * \param [in]  symbol_table table of symbols
 
703
 * \param [in]  str          label of the constant
 
704
 * \param [in]  value        value associated to the constant
 
705
 */
 
706
 
 
707
void
 
708
mei_symbol_table_insert(hash_table_t  *symbol_table,
 
709
                        const char    *str,
 
710
                        const double   value)
 
711
{
 
712
  assert(symbol_table!= NULL);
 
713
  assert(str != NULL);
 
714
 
 
715
  mei_hash_table_insert(symbol_table,
 
716
                        str,
 
717
                        CONSTANT,
 
718
                        value,
 
719
                        NULL,
 
720
                        NULL,
 
721
                        NULL,
 
722
                        NULL);
 
723
}
 
724
 
 
725
/*!
 
726
 * \brief Check if the symbol \em str exists in the expression stored
 
727
 * in \em ev.
 
728
 * Return 0 if the symbol exists in the symbol table, 1 if not.
 
729
 *
 
730
 * \param [in] ev  interpreter in which we want to know if str exists
 
731
 * \param [in] str symbol to find
 
732
 * \return 0 if the symbol exists in the symbol table, 1 if not
 
733
 */
 
734
 
 
735
int
 
736
mei_tree_find_symbol(mei_tree_t  *ev,
 
737
                     const char  *str)
 
738
{
 
739
  int i;
 
740
 
 
741
  assert(ev != NULL);
 
742
  assert(str != NULL);
 
743
 
 
744
  /* restart error's counter */
 
745
 
 
746
  for (i=0; i < ev->errors; i++)
 
747
    BFT_FREE(ev->labels[i]);
 
748
 
 
749
  BFT_FREE(ev->labels);
 
750
  BFT_FREE(ev->lines);
 
751
  BFT_FREE(ev->columns);
 
752
  ev->errors = 0;
 
753
 
 
754
  return _find_symbol(ev, str);
 
755
}
 
756
 
 
757
/*!
 
758
 * \brief Check if the symbol \em str from a list exists in the expression.
 
759
 * Return 0 if all symbols exist, otherwise return the number of errors.
 
760
 * The list of missing symbols is stored in \em ev->labels.
 
761
 *
 
762
 * \param [in]  ev     interpreter
 
763
 * \param [in]  size   number of symbols to check
 
764
 * \param [in]  symbol list of symbols
 
765
 * \return 0 if all symbols exist, otherwise return the number of errors
 
766
 */
 
767
 
 
768
int
 
769
mei_tree_find_symbols(mei_tree_t   *ev,
 
770
                      const int     size,
 
771
                      const char  **symbol)
 
772
{
 
773
  int i, iok = 0;
 
774
 
 
775
  assert(ev != NULL);
 
776
 
 
777
  /* restart error's counter */
 
778
 
 
779
  for (i=0; i < ev->errors; i++)
 
780
    BFT_FREE(ev->labels[i]);
 
781
 
 
782
  BFT_FREE(ev->labels);
 
783
  BFT_FREE(ev->lines);
 
784
  BFT_FREE(ev->columns);
 
785
  ev->errors = 0;
 
786
 
 
787
  /* check if each symbol from the list exists */
 
788
 
 
789
  for (i=0; i<size; i++)
 
790
    iok += _find_symbol(ev, symbol[i]);
 
791
 
 
792
  return iok;
 
793
}
 
794
 
 
795
/*!
 
796
 * \brief Returns a value of the \em str symbol (variable or constant)
 
797
 *  from table of symbols of \em ev interpreter.
 
798
 *
 
799
 * \param [in]   ev  interpreter
 
800
 * \param [in]   str name of the symbol
 
801
 * \return value of a symbol
 
802
 */
 
803
 
 
804
double
 
805
mei_tree_lookup(mei_tree_t  *ev,
 
806
                const char  *str)
 
807
{
 
808
  struct item *item = NULL;
 
809
 
 
810
  assert(ev != NULL);
 
811
  assert(str != NULL);
 
812
 
 
813
  item = mei_hash_table_lookup(ev->symbol, str);
 
814
 
 
815
  if (!item) {
 
816
    bft_error(__FILE__, __LINE__, 0,
 
817
              "Error in mei_tree_lookup function: "
 
818
              "%s does not exist in the symbol table\n", str);
 
819
  }
 
820
  return item->data->value;
 
821
}
 
822
 
 
823
/*!
 
824
 * \brief Evaluates the expression \em ev :
 
825
 *   1) computes all values for variables inside the expression
 
826
 *   2) returns a value from the intrepreted expression.
 
827
 *
 
828
 * \param [in] ev interpreter
 
829
 * \return value from the intrepreted expression
 
830
 */
 
831
 
 
832
double
 
833
mei_evaluate(mei_tree_t  *ev)
 
834
{
 
835
  assert(ev != NULL);
 
836
  return _evaluate(ev->node);
 
837
}
 
838
 
 
839
/*!
 
840
 * \brief Free memory and return NULL.
 
841
 *
 
842
 * \param [in] ev interpreter
 
843
 */
 
844
 
 
845
void
 
846
mei_tree_destroy(mei_tree_t  *ev)
 
847
{
 
848
  int i;
 
849
 
 
850
  if (ev != NULL) {
 
851
    if (ev->symbol->n_inter == 1) { /* symbol tables for a single interpreter */
 
852
      mei_hash_table_free(ev->symbol);
 
853
      BFT_FREE(ev->symbol);
 
854
    }
 
855
    else {
 
856
      ev->symbol->n_inter--; /* shared symbol tables */
 
857
    }
 
858
    BFT_FREE(ev->string);
 
859
    mei_free_node(ev->node);
 
860
 
 
861
    for (i=0; i < ev->errors; i++)
 
862
      BFT_FREE(ev->labels[i]);
 
863
 
 
864
    BFT_FREE(ev->labels);
 
865
    BFT_FREE(ev->lines);
 
866
    BFT_FREE(ev->columns);
 
867
    BFT_FREE(ev);
 
868
  }
 
869
}
 
870
 
 
871
/*----------------------------------------------------------------------------*/
 
872
 
 
873
#ifdef __cplusplus
 
874
}
 
875
#endif /* __cplusplus */