irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

arithmetics.cpp
Go to the documentation of this file.
1 /* For copyright information please refer to files in the COPYRIGHT directory
2  */
3 
4 #define MAKE_IRODS_ERROR_MAP
5 #include "rodsErrorTable.h"
6 const static std::map<const std::string, const int> irods_error_name_map = irods_error_map_construction::irods_error_name_map;
7 #include "reFuncDefs.hpp"
8 #include "utils.hpp"
9 #include "restructs.hpp"
10 #include "parser.hpp"
11 #include "arithmetics.hpp"
12 #include "datetime.hpp"
13 #include "index.hpp"
14 #include "rules.hpp"
15 #include "functions.hpp"
16 #include "configuration.hpp"
17 #include "reVariableMap.gen.hpp"
18 #include "reVariableMap.hpp"
19 #include "debug.hpp"
20 #include "irods_re_plugin.hpp"
21 
22 // #include "irods_ms_plugin.hpp"
23 // irods::ms_table MicrosTable;
24 // extern int NumOfAction;
25 
26 #define RE_ERROR(x, y) if(x) {if((y)!=NULL){(y)->type.t=RE_ERROR;*errnode=node;}return;}
27 #define OUTOFMEMORY(x, res) if(x) {(res)->value.e = OUT_OF_MEMORY;TYPE(res) = RE_ERROR;return;}
28 
29 #define RE_ERROR2(x,y) if(x) {localErrorMsg=(y);goto error;}
30 extern int GlobalREDebugFlag;
31 extern int GlobalREAuditFlag;
32 
33 /* utilities */
34 int initializeEnv( Node *params, Res *args[MAX_NUM_OF_ARGS_IN_ACTION], int argc, Hashtable *env ) {
35 
36 
37  Node** args2 = params->subtrees;
38  int i;
39  for ( i = 0; i < argc ; i++ ) {
40  insertIntoHashTable( env, args2[i]->text, args[i] );
41  }
42  return 0;
43 }
44 
46  return node->subtrees[0]->text;
47 }
48 
49 
50 Res* evaluateExpression3( Node *expr, int applyAll, int force, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t* errmsg, Region *r ) {
51  /*
52  printTree(expr, 0);
53  */
54  char errbuf[ERR_MSG_LEN];
55  Res *res = newRes( r ), *funcRes = NULL, *argRes = NULL;
56  FunctionDesc *fd = NULL;
57  int i;
58  Res **tupleComps = NULL;
59  /* Only input parameters are evaluated here;
60  * The original AST node is needed for parameters of other IO types in evaluateFunction3.
61  */
62  int discardResult = ( reiSaveFlag & DISCARD_EXPRESSION_RESULT ) != 0;
63  if ( discardResult ) {
64  switch ( getNodeType( expr ) ) {
65  case TK_BOOL:
66  res->exprType = newSimpType( T_UNSPECED, r );
67  break;
68  case TK_INT:
69  res->exprType = newSimpType( T_UNSPECED, r );
70  break;
71  case TK_DOUBLE:
72  res->exprType = newSimpType( T_UNSPECED, r );
73  break;
74  case TK_STRING:
75  res->exprType = newSimpType( T_UNSPECED, r );
76  break;
77  case TK_VAR:
78  res->exprType = newSimpType( T_UNSPECED, r );
79  break;
80  case TK_TEXT:
81  {
82  auto itr = irods_error_name_map.find(expr->text);
83  if(itr != irods_error_name_map.end()) {
84  res->exprType = newSimpType( T_UNSPECED, r );
85  } else {
87  if ( fd != NULL && fd->exprType != NULL ) {
88  int nArgs = 0;
89  ExprType *type = fd->exprType;
90  while ( getNodeType( type ) == T_CONS && strcmp( type->text, FUNC ) == 0 ) {
91  type = type->subtrees[1];
92  nArgs ++;
93  }
94  if ( nArgs == 0 ) {
95  Node *appNode = newPartialApplication( expr, newTupleRes( 0, NULL, r ), 0, r );
96  res = evaluateFunction3( appNode, applyAll, expr, env, rei, reiSaveFlag, errmsg, r );
97  }
98  else {
99  res->exprType = newSimpType( T_UNSPECED, r );
100  }
101  }
102  else {
103  res->exprType = newSimpType( T_UNSPECED, r );
104  }
105  }
106  }
107  break;
108 
109 
110  case N_APPLICATION:
111  /* try to evaluate as a function, */
112  /*
113  printf("start execing %s\n", oper1);
114  printEnvToStdOut(env);
115 
116  */
117  funcRes = evaluateExpression3( expr->subtrees[0], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, r );
118  if ( getNodeType( funcRes ) == N_ERROR ) {
119  res = funcRes;
120  break;
121  }
122  /* printTree(expr->subtrees[1], 0); */
123  argRes = evaluateExpression3( expr->subtrees[1], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, r );
124  if ( getNodeType( argRes ) == N_ERROR ) {
125  res = argRes;
126  break;
127  }
128  res = evaluateFunctionApplication( funcRes, argRes, applyAll, expr, rei, reiSaveFlag, env, errmsg, r );
129  /*
130  printf("finish execing %s\n", oper1);
131  printEnvToStdOut(env);
132  */
133  break;
134  case N_TUPLE:
135  for ( i = 0; i < expr->degree; i++ ) {
136  res = evaluateExpression3( expr->subtrees[i], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, r );
137  if ( getNodeType( res ) == N_ERROR ) {
138  break;
139  }
140  }
141  break;
142  case N_ACTIONS_RECOVERY:
143  res = evaluateActions( expr->subtrees[0], expr->subtrees[1], applyAll, rei, reiSaveFlag, env, errmsg, r );
144  break;
145 
146  case N_ACTIONS:
147  generateErrMsg( "error: evaluate actions using function evaluateExpression3, use function evaluateActions instead.", NODE_EXPR_POS( expr ), expr->base, errbuf );
148  addRErrorMsg( errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf );
150  break;
151  case N_EXTERN_DEF:
152  res = evaluateExpression3( expr->subtrees[0], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, r );
153  break;
154  default:
155  generateErrMsg( "error: unsupported ast node type.", NODE_EXPR_POS( expr ), expr->base, errbuf );
156  addRErrorMsg( errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf );
158  break;
159  }
160  }
161  else if ( force || getIOType( expr ) == IO_TYPE_INPUT ) {
162  switch ( getNodeType( expr ) ) {
163  case TK_BOOL:
164  res->exprType = newSimpType( T_BOOL, r );
165  RES_BOOL_VAL_LVAL( res ) = strcmp( expr->text, "true" ) == 0 ? 1 : 0;
166  break;
167  case TK_INT:
168  res->exprType = newSimpType( T_INT, r );
169  RES_INT_VAL_LVAL( res ) = atoi( expr->text );
170  break;
171  case TK_DOUBLE:
172  res->exprType = newSimpType( T_DOUBLE, r );
173  RES_DOUBLE_VAL_LVAL( res ) = atof( expr->text );
174  break;
175  case TK_STRING:
176  res = newStringRes( r, expr->text );
177  break;
178  case TK_VAR:
179  res = evaluateVar3( expr->text, expr, rei, env, errmsg, r );
180  break;
181  case TK_TEXT:
182  {
183  auto itr = irods_error_name_map.find(expr->text);
184  if(itr != irods_error_name_map.end()) {
185  res = newIntRes(r, itr->second);
186  } else {
188  if ( fd != NULL && fd->exprType != NULL ) {
189  int nArgs = 0;
190  ExprType *type = fd->exprType;
191  while ( getNodeType( type ) == T_CONS && strcmp( type->text, FUNC ) == 0 ) {
192  type = type->subtrees[1];
193  nArgs ++;
194  }
195  if ( nArgs == 0 ) {
196  Node *appNode = newPartialApplication( expr, newTupleRes( 0, NULL, r ), 0, r );
197  res = evaluateFunction3( appNode, applyAll, expr, env, rei, reiSaveFlag, errmsg, r );
198  }
199  else {
200  res = newFuncSymLink( expr->text, nArgs, r );
201  }
202  }
203  else {
204  res = newFuncSymLink( expr->text, 1, r );
205  }
206  }
207  }
208  break;
209 
210 
211  case N_APPLICATION:
212  /* try to evaluate as a function, */
213  /*
214  printf("start execing %s\n", oper1);
215  printEnvToStdOut(env);
216 
217  */
218  funcRes = evaluateExpression3( expr->subtrees[0], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, r );
219  if ( getNodeType( funcRes ) == N_ERROR ) {
220  res = funcRes;
221  break;
222  }
223  /* printTree(expr->subtrees[1], 0); */
224  argRes = evaluateExpression3( expr->subtrees[1], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, r );
225  if ( getNodeType( argRes ) == N_ERROR ) {
226  res = argRes;
227  break;
228  }
229  res = evaluateFunctionApplication( funcRes, argRes, applyAll, expr, rei, reiSaveFlag, env, errmsg, r );
230  /*
231  printf("finish execing %s\n", oper1);
232  printEnvToStdOut(env);
233  */
234  break;
235  case N_TUPLE:
236  tupleComps = ( Res ** ) region_alloc( r, sizeof( Res * ) * expr->degree );
237  for ( i = 0; i < expr->degree; i++ ) {
238  res = tupleComps[i] = evaluateExpression3( expr->subtrees[i], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, r );
239  if ( getNodeType( res ) == N_ERROR ) {
240  break;
241  }
242  }
243  if ( expr->degree == 0 || getNodeType( res ) != N_ERROR ) {
244  if ( N_TUPLE_CONSTRUCT_TUPLE( expr ) || expr->degree != 1 ) {
245  res = newTupleRes( expr->degree, tupleComps, r );
246  }
247  }
248  break;
249  case N_ACTIONS_RECOVERY:
250  res = evaluateActions( expr->subtrees[0], expr->subtrees[1], applyAll, rei, reiSaveFlag, env, errmsg, r );
251  break;
252 
253  case N_ACTIONS:
254  generateErrMsg( "error: evaluate actions using function evaluateExpression3, use function evaluateActions instead.", NODE_EXPR_POS( expr ), expr->base, errbuf );
255  addRErrorMsg( errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf );
257  break;
258  case N_EXTERN_DEF:
259  res = evaluateExpression3( expr->subtrees[0], applyAll > 1 ? applyAll : 0, 0, rei, reiSaveFlag, env, errmsg, r );
260  break;
261  default:
262  generateErrMsg( "error: unsupported ast node type.", NODE_EXPR_POS( expr ), expr->base, errbuf );
263  addRErrorMsg( errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf );
265  break;
266  }
267  }
268  else {
269  res = expr;
270  while ( getNodeType( res ) == N_TUPLE && res->degree == 1 ) {
271  res = res->subtrees[0];
272  }
273  }
274  /* coercions are applied at application locations only */
275  return res;
276 }
277 
278 ExprType* isIterable( ExprType *type, Hashtable* var_type_table, Region *r );
279 Res* processCoercion( Node *node, Res *res, ExprType *type, Hashtable *tvarEnv, rError_t *errmsg, Region *r ) {
280  char buf[ERR_MSG_LEN > 1024 ? ERR_MSG_LEN : 1024];
281  char *buf2;
282  char buf3[ERR_MSG_LEN];
283  ExprType *coercion = type;
284  ExprType *futureCoercion = NULL;
285  if ( getNodeType( coercion ) == T_FLEX ) {
286  coercion = coercion->subtrees[0];
287  }
288  else if ( getNodeType( coercion ) == T_FIXD ) {
289  coercion = coercion->subtrees[1];
290  }
291  if ( coercion->exprType != NULL ) {
292  futureCoercion = coercion->exprType;
293  }
294  coercion = instantiate( coercion, tvarEnv, 0, r );
295  if ( getNodeType( coercion ) == T_VAR ) {
296  if ( T_VAR_NUM_DISJUNCTS( coercion ) == 0 ) {
297  /* generateErrMsg("error: cannot instantiate coercion type for node.", NODE_EXPR_POS(node), node->base, buf);
298  addRErrorMsg(errmsg, -1, buf);
299  return newErrorRes(r, -1); */
300  return res;
301  }
302  /* here T_VAR must be a set of bounds
303  * we fix the set of bounds to the default bound */
304  ExprType *defaultType = T_VAR_DISJUNCT( coercion, 0 );
305  updateInHashTable( tvarEnv, getTVarName( T_VAR_ID( coercion ), buf ), defaultType );
306  coercion = defaultType;
307  }
308  Res *nres = NULL;
309  if ( typeEqSyntatic( coercion, res->exprType ) ) {
310  nres = res;
311  }
312  else {
313  if ( TYPE( res ) == T_UNSPECED ) {
314  generateErrMsg( "error: dynamic coercion from an uninitialized value", NODE_EXPR_POS( node ), node->base, buf );
317  }
318  switch ( getNodeType( coercion ) ) {
319  case T_DYNAMIC:
320  nres = res;
321  break;
322  case T_INT:
323  switch ( TYPE( res ) ) {
324  case T_DOUBLE:
325  if ( ( int )RES_DOUBLE_VAL( res ) != RES_DOUBLE_VAL( res ) ) {
326  generateErrMsg( "error: dynamic type conversion DOUBLE -> INTEGER: the double is not an integer", NODE_EXPR_POS( node ), node->base, buf );
329  }
330  else {
331  nres = newIntRes( r, RES_INT_VAL( res ) );
332  }
333  break;
334  case T_BOOL:
335  nres = newIntRes( r, RES_BOOL_VAL( res ) );
336  break;
337  case T_STRING:
338  nres = newIntRes( r, atoi( res->text ) );
339  break;
340  default:
341  break;
342  }
343  break;
344  case T_DOUBLE:
345  switch ( TYPE( res ) ) {
346  case T_INT:
347  nres = newDoubleRes( r, RES_INT_VAL( res ) );
348  break;
349  case T_BOOL:
350  nres = newDoubleRes( r, RES_BOOL_VAL( res ) );
351  break;
352  case T_STRING:
353  nres = newDoubleRes( r, atof( res->text ) );
354  break;
355  default:
356  break;
357  }
358  break;
359  case T_STRING:
360  switch ( TYPE( res ) ) {
361  case T_INT:
362  case T_DOUBLE:
363  case T_BOOL:
364  buf2 = convertResToString( res );
365 
366  nres = newStringRes( r, buf2 );
367  free( buf2 );
368  break;
369  default:
370  break;
371  }
372  break;
373  case T_PATH:
374  switch ( TYPE( res ) ) {
375  case T_STRING:
376  nres = newPathRes( r, res->text );
377  break;
378  default:
379  break;
380  }
381  break;
382  case T_BOOL:
383  switch ( TYPE( res ) ) {
384  case T_INT:
385  nres = newBoolRes( r, RES_INT_VAL( res ) );
386  break;
387  case T_DOUBLE:
388  nres = newBoolRes( r, ( int ) RES_DOUBLE_VAL( res ) );
389  break;
390  case T_STRING:
391  if ( strcmp( res->text, "true" ) == 0 ) {
392  nres = newBoolRes( r, 1 );
393  }
394  else if ( strcmp( res->text, "false" ) == 0 ) {
395  nres = newBoolRes( r, 0 );
396  }
397  else {
398  generateErrMsg( "error: dynamic type conversion string -> bool: the string is not in {true, false}", NODE_EXPR_POS( node ), node->base, buf );
401  }
402  break;
403  default:
404  break;
405  }
406  break;
407  case T_CONS:
408  /* we can ignore the not top level type constructor and leave type checking to when it is derefed */
409  switch ( TYPE( res ) ) {
410  case T_CONS:
411  nres = res;
412  break;
413  default:
414  if ( isIterable( res->exprType, newHashTable2( 10, r ), r ) != NULL ) {
415  nres = res;
416  }
417  break;
418  }
419  break;
420  case T_DATETIME:
421  switch ( TYPE( res ) ) {
422  case T_INT:
423  nres = newDatetimeRes( r, ( time_t ) RES_INT_VAL( res ) );
424  break;
425  case T_DOUBLE:
426  nres = newDatetimeRes( r, ( time_t ) RES_DOUBLE_VAL( res ) );
427  break;
428  default:
429  break;
430  }
431  break;
432  default:
433  break;
434  }
435  }
436  char typeBuf1[128], typeBuf2[128];
437  if ( nres != NULL ) {
438  if ( futureCoercion != NULL ) {
439  if ( getNodeType( futureCoercion ) != T_VAR || futureCoercion->degree == 0 ) {
440  snprintf( buf, ERR_MSG_LEN, "error: flexible coercion target type supported only for union types, but is applied to %s",
441  typeToString( futureCoercion, tvarEnv, typeBuf1, 128 ) );
442  generateErrMsg( buf, NODE_EXPR_POS( node ), node->base, buf3 );
443  addRErrorMsg( errmsg, RE_TYPE_ERROR, buf3 );
444  return newErrorRes( r, RE_TYPE_ERROR );
445  }
446  switch ( TYPE( nres ) ) {
447  case T_INT:
448  nres = newIntRes( r, RES_INT_VAL( nres ) );
449  nres->exprType->exprType = futureCoercion;
450  break;
451  case T_DOUBLE:
452  nres = newDoubleRes( r, RES_DOUBLE_VAL( nres ) );
453  nres->exprType->exprType = futureCoercion;
454  break;
455  default:
456  snprintf( buf, ERR_MSG_LEN, "error: flexible coercion source type supported only for integer or double, but is applied to %s",
457  typeToString( nres->exprType, tvarEnv, typeBuf1, 128 ) );
458  generateErrMsg( buf, NODE_EXPR_POS( node ), node->base, buf3 );
459  addRErrorMsg( errmsg, RE_TYPE_ERROR, buf3 );
460  return newErrorRes( r, RE_TYPE_ERROR );
461  }
462  }
463  return nres;
464  }
465  snprintf( buf, ERR_MSG_LEN, "error: coerce from type %s to type %s",
466  typeToString( res->exprType, tvarEnv, typeBuf1, 128 ),
467  typeToString( coercion, tvarEnv, typeBuf2, 128 ) );
468  generateErrMsg( buf, NODE_EXPR_POS( node ), node->base, buf3 );
469  addRErrorMsg( errmsg, RE_TYPE_ERROR, buf3 );
470  return newErrorRes( r, RE_TYPE_ERROR );
471 }
472 
473 Res* evaluateActions( Node *expr, Node *reco, int applyAll, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t* errmsg, Region *r ) {
474  /*
475  printTree(expr, 0);
476  */
477  int i;
478  int cutFlag = 0;
479  Res* res = NULL;
480 #ifndef DEBUG
481  char tmpStr[1024];
482 #endif
483  switch ( getNodeType( expr ) ) {
484  case N_ACTIONS:
485  for ( i = 0; i < expr->degree; i++ ) {
486  Node *nodei = expr->subtrees[i];
487  if ( getNodeType( nodei ) == N_APPLICATION && getNodeType( nodei->subtrees[0] ) == TK_TEXT && strcmp( nodei->subtrees[0]->text, "cut" ) == 0 ) {
488  cutFlag = 1;
489  continue;
490  }
491  res = evaluateExpression3( nodei, applyAll, 0, rei, reiSaveFlag | (i == expr->degree - 1? 0 : DISCARD_EXPRESSION_RESULT), env, errmsg, r );
492  if ( getNodeType( res ) == N_ERROR ) {
493 #ifndef DEBUG
494  char *errAction = getNodeType( nodei ) == N_APPLICATION ? N_APP_FUNC( nodei )->text : nodei->text;
495  sprintf( tmpStr, "executeRuleAction Failed for %s", errAction );
496  rodsLogError( LOG_ERROR, RES_ERR_CODE( res ), tmpStr );
497  rodsLog( LOG_NOTICE, "executeRuleBody: Microservice or Action %s Failed with status %i", errAction, RES_ERR_CODE( res ) );
498 #endif
499  /* run recovery chain */
500  if ( RES_ERR_CODE( res ) != RETRY_WITHOUT_RECOVERY_ERR && reco != NULL ) {
501  int i2;
502  for ( i2 = reco->degree - 1 < i ? reco->degree - 1 : i; i2 >= 0; i2-- ) {
503 #ifndef DEBUG
504  if ( reTestFlag > 0 ) {
506  fprintf( stdout, "***RollingBack\n" );
507  }
508  else if ( reTestFlag == HTML_TEST_1 ) {
509  fprintf( stdout, "<FONT COLOR=#FF0000>***RollingBack</FONT><BR>\n" );
510  }
511  else if ( reTestFlag == LOG_TEST_1 )
512  if ( rei != NULL && rei->rsComm != NULL && &( rei->rsComm->rError ) != NULL ) {
513  rodsLog( LOG_NOTICE, "***RollingBack\n" );
514  }
515  }
516 #endif
517 
518  Res *res2 = evaluateExpression3( reco->subtrees[i2], 0, 0, rei, reiSaveFlag, env, errmsg, r );
519  if ( getNodeType( res2 ) == N_ERROR ) {
520 #ifndef DEBUG
521  char *errAction = getNodeType( reco->subtrees[i2] ) == N_APPLICATION ? N_APP_FUNC( reco->subtrees[i2] )->text : reco->subtrees[i2]->text;
522  sprintf( tmpStr, "executeRuleRecovery Failed for %s", errAction );
523  rodsLogError( LOG_ERROR, RES_ERR_CODE( res2 ), tmpStr );
524 #endif
525  }
526  }
527  }
528  if ( cutFlag ) {
530  }
531  else {
532  return res;
533  }
534  }
535  else if ( TYPE( res ) == T_BREAK ) {
536  return res;
537  }
538  else if ( TYPE( res ) == T_SUCCESS ) {
539  return res;
540  }
541 
542  }
543  return res == NULL ? newIntRes( r, 0 ) : res;
544  default:
545  break;
546  }
547  char errbuf[ERR_MSG_LEN];
548  generateErrMsg( "error: unsupported ast node type.", NODE_EXPR_POS( expr ), expr->base, errbuf );
549  addRErrorMsg( errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf );
551 }
552 
553 Res *evaluateFunctionApplication( Node *func, Node *arg, int applyAll, Node *node, ruleExecInfo_t* rei, int reiSaveFlag, Env *env, rError_t *errmsg, Region *r ) {
554  Res *res;
555  char errbuf[ERR_MSG_LEN];
556  int discardResult = ( reiSaveFlag & DISCARD_EXPRESSION_RESULT ) != 0;
557  switch ( getNodeType( func ) ) {
558  case N_VAL:
559  return func;
560  case N_SYM_LINK:
562  res = newPartialApplication( func, arg, RES_FUNC_N_ARGS( func ) - 1, r );
563  if ( RES_FUNC_N_ARGS( res ) == 0 ) {
564  res = evaluateFunction3( res, applyAll, node, env, rei, reiSaveFlag, errmsg, r );
565  } else if(discardResult)
566  res = newUnspecifiedRes( r );
567  return res;
568  default:
569  generateErrMsg( "unsupported function node type.", NODE_EXPR_POS( node ), node->base, errbuf );
570  addRErrorMsg( errmsg, RE_UNSUPPORTED_AST_NODE_TYPE, errbuf );
572  }
573 }
574 
580 Res* evaluateFunction3( Node *appRes, int applyAll, Node *node, Env *env, ruleExecInfo_t* rei, int reiSaveFlag, rError_t *errmsg, Region *r ) {
581  unsigned int i;
582  unsigned int n;
583  int discardResult = ( reiSaveFlag & DISCARD_EXPRESSION_RESULT ) != 0;
584  i = 0;
585  Node *appFuncRes = appRes;
586  while ( getNodeType( appFuncRes ) == N_PARTIAL_APPLICATION ) {
587  i++;
588  appFuncRes = appFuncRes->subtrees[0];
589  }
590  /* app can only be N_FUNC_SYM_LINK */
591  char* fn = appFuncRes->text;
592  if ( strcmp( fn, "nop" ) == 0 ) {
593  return newIntRes( r, 0 );
594  }
595  /* printEnvIndent(env);
596  printf("calling function %s\n", fn);
597  char buf0[ERR_MSG_LEN];
598  generateErrMsg("", NODE_EXPR_POS(node), node->base, buf0);
599  printf("%s", buf0); */
600  Res *appArgRes = appRes->subtrees[1];
601 
602  n = appArgRes->degree;
603  std::vector<Node*> args(n,nullptr);
604  std::vector<Node*> argsProcessed(n,nullptr);
605  Res** appArgs = appArgRes->subtrees;
606  Node** nodeArgs = node->subtrees[1]->subtrees;
607  ExprType *coercionType = NULL;
608 #ifdef DEBUG
609  char buf[ERR_MSG_LEN > 1024 ? ERR_MSG_LEN : 1024];
610  sprintf( buf, "Action: %s\n", fn );
611  writeToTmp( "eval.log", buf );
612 #endif
613  /* char buf2[ERR_MSG_LEN]; */
614 
615  Res* res;
616  Region *newRegion = make_region( 0, NULL );
617  Env *global = globalEnv( env );
618  Env *nEnv = newEnv( newHashTable2( 10, newRegion ), global, env, newRegion );
619 
620  List *localTypingConstraints = NULL;
621  FunctionDesc *fd = NULL;
622  /* look up function descriptor */
624 
625  localTypingConstraints = newList( r );
626  std::vector<int> ioParam(n,0);
627  /* evaluation parameters and try to resolve remaining tvars with unification */
628  for ( i = 0; i < n; i++ ) {
629  switch ( getIOType( nodeArgs[i] ) ) {
630  case IO_TYPE_INPUT | IO_TYPE_OUTPUT: /* input/output */
631  ioParam[i] = IO_TYPE_INPUT | IO_TYPE_OUTPUT;
632  if ( !isVariableNode( appArgs[i] ) ) {
634  generateAndAddErrMsg( "unsupported output parameter type", appArgs[i], RE_UNSUPPORTED_AST_NODE_TYPE, errmsg );
635  RETURN;
636  }
637  args[i] = evaluateExpression3( appArgs[i], applyAll > 1 ? applyAll : 0, 1, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, newRegion );
638  if ( getNodeType( args[i] ) == N_ERROR ) {
639  res = ( Res * )args[i];
640  RETURN;
641  }
642  break;
643  case IO_TYPE_INPUT: /* input */
644  ioParam[i] = IO_TYPE_INPUT;
645  args[i] = appArgs[i];
646  break;
647  case IO_TYPE_DYNAMIC: /* dynamic */
648  if ( isVariableNode( appArgs[i] ) ) {
649  args[i] = attemptToEvaluateVar3( appArgs[i]->text, appArgs[i], rei, env, errmsg, newRegion );
650  if ( getNodeType( args[i] ) == N_ERROR ) {
651  res = args[i];
652  RETURN;
653  }
654  else if ( TYPE( args[i] ) == T_UNSPECED ) {
655  ioParam[i] = IO_TYPE_OUTPUT;
656  }
657  else {
658  ioParam[i] = IO_TYPE_INPUT | IO_TYPE_OUTPUT;
659  if ( getNodeType( args[i] ) == N_ERROR ) {
660  res = ( Res * )args[i];
661  RETURN;
662  }
663  }
664  }
665  else {
666  ioParam[i] = IO_TYPE_INPUT;
667  args[i] = evaluateExpression3( appArgs[i], applyAll > 1 ? applyAll : 0, 1, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, newRegion );
668  if ( getNodeType( args[i] ) == N_ERROR ) {
669  res = ( Res * )args[i];
670  RETURN;
671  }
672  }
673  break;
674  case IO_TYPE_OUTPUT: /* output */
675  ioParam[i] = IO_TYPE_OUTPUT;
676  args[i] = newUnspecifiedRes( r );
677  break;
678  case IO_TYPE_EXPRESSION: /* expression */
679  ioParam[i] = IO_TYPE_EXPRESSION;
680  args[i] = appArgs[i];
681  break;
682  case IO_TYPE_ACTIONS: /* actions */
683  ioParam[i] = IO_TYPE_ACTIONS;
684  args[i] = appArgs[i];
685  break;
686  }
687  }
688  /* try to type all input parameters */
689  coercionType = node->subtrees[1]->coercionType;
690  if ( coercionType != NULL ) {
691  /*for(i=0;i<n;i++) {
692  if((ioParam[i] == 'i' || ioParam[i] == 'p') && nodeArgs[i]->exprType != NULL) {
693  if(unifyWith(args[i]->exprType, nodeArgs[i]->exprType, env->current, r) == NULL) {
694  snprintf(buf, ERR_MSG_LEN, "error: dynamically typed parameter does not have expected type.");
695  generateErrMsg(buf, nodeArgs[i]->expr, nodeArgs[i]->base, buf2);
696  addRErrorMsg(errmsg, TYPE_ERROR, buf2);
697  res = newErrorRes(r, TYPE_ERROR);
698  RETURN;
699  }
700  }
701  }*/
702 
703 
704  ExprType *argType = newTupleRes( n, &args[0], r )->exprType;
705  if ( typeFuncParam( node->subtrees[1], argType, coercionType, env->current, localTypingConstraints, errmsg, newRegion ) != 0 ) {
706  res = newErrorRes( r, RE_TYPE_ERROR );
707  RETURN;
708  }
709  /* solve local typing constraints */
710  /* typingConstraintsToString(localTypingConstraints, buf, 1024);
711  printf("%s\n", buf); */
712  Node *errnode;
713  if ( !solveConstraints( localTypingConstraints, env->current, errmsg, &errnode, r ) ) {
715  RETURN;
716  }
717  /*printVarTypeEnvToStdOut(localTVarEnv); */
718  /* do the input value conversion */
719  ExprType **coercionTypes = coercionType->subtrees;
720  for ( i = 0; i < n; i++ ) {
721  if ( ( ( ioParam[i] & IO_TYPE_INPUT ) == IO_TYPE_INPUT ) && ( nodeArgs[i]->option & OPTION_COERCE ) != 0 ) {
722  argsProcessed[i] = processCoercion( nodeArgs[i], args[i], coercionTypes[i], env->current, errmsg, newRegion );
723  if ( getNodeType( argsProcessed[i] ) == N_ERROR ) {
724  res = ( Res * )argsProcessed[i];
725  RETURN;
726  }
727  }
728  else {
729  argsProcessed[i] = args[i];
730  }
731  }
732  }
733  else {
734  memcpy( &argsProcessed[0], &args[0], sizeof( Res * ) * n );
735  }
736 
737 
738  if ( GlobalREAuditFlag > 0 ) {
739  RuleEngineEventParam param;
740  param.actionName = fn;
741  param.ruleIndex = -1;
742  reDebug( EXEC_ACTION_BEGIN, -4, &param, node, env, rei );
743  }
744 
745  if ( fd != NULL ) {
746  if(discardResult)
747  switch ( getNodeType( fd ) ) {
748  case N_FD_DECONSTRUCTOR:
749  res = newUnspecifiedRes( r );
750  break;
751  case N_FD_CONSTRUCTOR:
752  res = newUnspecifiedRes( r );
753  break;
754  case N_FD_FUNCTION:
755  res = (Res *) FD_SMSI_FUNC_PTR( fd )( &argsProcessed[0], n, node, rei, reiSaveFlag, env, errmsg, newRegion );
756  if(getNodeType(res) != N_ERROR) {
757  switch ( TYPE( res ) ) {
758  case T_BREAK:
759  case T_SUCCESS:
760  break;
761  default:
762  res = newUnspecifiedRes( r );
763  break;
764  }
765  }
766  break;
767  case N_FD_EXTERNAL:
768  res = execAction3( fn, &argsProcessed[0], n, applyAll, node, nEnv, rei, reiSaveFlag, errmsg, newRegion );
769  break;
771  res = execAction3( fn, &argsProcessed[0], n, applyAll, node, nEnv, rei, reiSaveFlag, errmsg, newRegion );
772  break;
773  default:
775  generateAndAddErrMsg( "unsupported function descriptor type", node, RE_UNSUPPORTED_AST_NODE_TYPE, errmsg );
776  RETURN;
777  }
778  else
779  switch ( getNodeType( fd ) ) {
780  case N_FD_DECONSTRUCTOR:
781  res = deconstruct( &argsProcessed[0], FD_PROJ( fd ) );
782  break;
783  case N_FD_CONSTRUCTOR:
784  res = construct( fn, &argsProcessed[0], n, instantiate( node->exprType, env->current, 1, r ), r );
785  break;
786  case N_FD_FUNCTION:
787  res = ( Res * ) FD_SMSI_FUNC_PTR( fd )( &argsProcessed[0], n, node, rei, reiSaveFlag, env, errmsg, newRegion );
788  break;
789  case N_FD_EXTERNAL:
790  res = execAction3( fn, &argsProcessed[0], n, applyAll, node, nEnv, rei, reiSaveFlag, errmsg, newRegion );
791  break;
793  res = execAction3( fn, &argsProcessed[0], n, applyAll, node, nEnv, rei, reiSaveFlag, errmsg, newRegion );
794  break;
795  default:
797  generateAndAddErrMsg( "unsupported function descriptor type", node, RE_UNSUPPORTED_AST_NODE_TYPE, errmsg );
798  RETURN;
799  }
800  }
801  else {
802  res = execAction3( fn, &argsProcessed[0], n, applyAll, node, nEnv, rei, reiSaveFlag, errmsg, newRegion );
803  }
804 
805  if ( GlobalREAuditFlag > 0 ) {
806  RuleEngineEventParam param;
807  param.actionName = fn;
808  param.ruleIndex = -1;
809 
810  reDebug( EXEC_ACTION_END, -4, &param, node, env, rei );
811  }
812 
813  if ( getNodeType( res ) == N_ERROR && strcmp( fn, "msiExecCmd" ) != 0 ) {
814  RETURN;
815  }
816 
817  for ( i = 0; i < n; i++ ) {
818  Res *resp = NULL;
819 
820  if ( ( ioParam[i] & IO_TYPE_OUTPUT ) == IO_TYPE_OUTPUT ) {
821  if ( ( appArgs[i]->option & OPTION_COERCE ) != 0 ) {
822  argsProcessed[i] = processCoercion( nodeArgs[i], argsProcessed[i], appArgs[i]->exprType, env->current, errmsg, newRegion );
823  }
824  if ( getNodeType( argsProcessed[i] ) == N_ERROR ) {
825  res = ( Res * )argsProcessed[i];
826  RETURN ;
827  }
828  if ( ( ioParam[i] & IO_TYPE_INPUT ) == 0 || !definitelyEq( args[i], argsProcessed[i] ) ) {
829  resp = setVariableValue( appArgs[i]->text, argsProcessed[i], nodeArgs[i], rei, env, errmsg, r );
830  }
831  /*char *buf = convertResToString(args[i]);
832  printEnvIndent(env);
833  printf("setting variable %s to %s\n", appArgs[i]->text, buf);
834  free(buf);*/
835  }
836  if ( resp != NULL && getNodeType( resp ) == N_ERROR ) {
837  res = resp;
838  RETURN;
839  }
840  }
841  /*printEnvIndent(env);
842  printf("exiting function %s\n", fn);
843  */
844  /*return res;*/
845 ret:
846  /*deleteEnv(nEnv, 2);*/
847  cpEnv2( env, newRegion, r );
848  res = cpRes2( res, newRegion, r );
849  region_free( newRegion );
850  return res;
851 
852 }
853 
854 Res* attemptToEvaluateVar3( char* vn, Node *node, ruleExecInfo_t *rei, Env *env, rError_t *errmsg, Region *r ) {
855  if ( vn[0] == '*' ) { /* local variable */
856  /* try to get local var from env */
857  Res* res0 = ( Res * )lookupFromEnv( env, vn );
858  if ( res0 == NULL ) {
859  return newUnspecifiedRes( r );
860  }
861  else {
862  return res0;
863  }
864  }
865  else if ( vn[0] == '$' ) { /* session variable */
866  Res *res = getSessionVar( "", node, vn, rei, errmsg, r );
867  if ( res == NULL ) {
868  return newUnspecifiedRes( r );
869  }
870  else {
871  return res;
872  }
873  }
874  else {
875  return NULL;
876  }
877 }
878 
879 Res* evaluateVar3( char* vn, Node *node, ruleExecInfo_t *rei, Env *env, rError_t *errmsg, Region *r ) {
880  char buf[ERR_MSG_LEN > 1024 ? ERR_MSG_LEN : 1024];
881  char buf2[ERR_MSG_LEN];
882  Res *res = attemptToEvaluateVar3( vn, node, rei, env, errmsg, r );
883  if ( getNodeType( res ) == N_ERROR ) {
884  return res;
885  }
886  if ( res == NULL || TYPE( res ) == T_UNSPECED ) {
887  if ( vn[0] == '*' ) { /* local variable */
888  snprintf( buf, ERR_MSG_LEN, "error: unable to read local variable %s.", vn );
889  generateErrMsg( buf, NODE_EXPR_POS( node ), node->base, buf2 );
890  addRErrorMsg( errmsg, RE_UNABLE_TO_READ_LOCAL_VAR, buf2 );
891  /*printEnvToStdOut(env); */
893  }
894  else if ( vn[0] == '$' ) { /* session variable */
895  snprintf( buf, ERR_MSG_LEN, "error: unable to read session variable %s.", vn );
896  generateErrMsg( buf, NODE_EXPR_POS( node ), node->base, buf2 );
899  }
900  else {
901  snprintf( buf, ERR_MSG_LEN, "error: unable to read variable %s.", vn );
902  generateErrMsg( buf, NODE_EXPR_POS( node ), node->base, buf2 );
903  addRErrorMsg( errmsg, RE_UNABLE_TO_READ_VAR, buf2 );
904  return newErrorRes( r, RE_UNABLE_TO_READ_VAR );
905  }
906  }
907  return res;
908 }
909 
914 Res* getSessionVar( char *action, Node *node, char *varName, ruleExecInfo_t *rei, rError_t *errmsg, Region *r ) {
915  /* Maps varName to the standard name and make varMap point to it. */
916  /* It seems that for each pair of varName and standard name there is a list of actions that are supported. */
917  /* vinx stores the index of the current pair so that we can start for the next pair if the current pair fails. */
918  char *varMap = NULL;
919  for ( int vinx = getVarMap( action, varName, &varMap, 0 ); vinx >= 0;
920  vinx = getVarMap( action, varName, &varMap, vinx + 1 ) ) {
921  /* Get the value of session variable referenced by varMap. */
922  Res *varValue = NULL;
923  int i = getVarValue( varMap, rei, &varValue, r ); /* reVariableMap.c */
924  if ( i >= 0 ) {
925 
927  if ( fd != NULL ) {
928  ExprType *type = fd->exprType->subtrees[0]; /* get var type from varMap */
929  Hashtable *tvarEnv = newHashTable2( 10, r );
930  varValue = processCoercion( node, varValue, type, tvarEnv, errmsg, r );
931  }
932  free( varMap );
933  return varValue;
934  }
935  else if ( i != NULL_VALUE_ERR ) { /* On error, return 0. */
936  free( varMap );
937  return NULL;
938  }
939  free( varMap );
940  varMap = NULL;
941  /* Try next varMap */
942  }
943  free( varMap );
944  return NULL;
945 }
946 
947 /*
948  * execute an external microserive or a rule
949  */
950 Res* execAction3( char *actionName, Res** args, unsigned int nargs, int applyAllRule, Node *node, Env *env, ruleExecInfo_t* rei, int reiSaveFlag, rError_t *errmsg, Region *r ) {
951  char buf[ERR_MSG_LEN > 1024 ? ERR_MSG_LEN : 1024];
952  char buf2[ERR_MSG_LEN];
953  char action[MAX_NAME_LEN];
954  snprintf( action, sizeof( action ), "%s", actionName );
956 
957  // this rule engine prioritizes its own rules before using the pluggable rule engine framework
958  Res *actionRet = execRule( actionName, args, nargs, applyAllRule, env, rei, reiSaveFlag, errmsg, r );
959  if ( getNodeType( actionRet ) == N_ERROR && (
960  RES_ERR_CODE( actionRet ) == NO_RULE_FOUND_ERR ) ) {
961 
962  bool safe_to_redirect_to_re_framework = true;
963  // actionName aka rule name was found, so must have failed because had the wrong number of arguments.
964  // pluggable rule engine framework does not check type signature of rules when matching (rule_exists
965  // operation only checks the rule name) so don't forward to framework to prevent infinite recursion
966  if ( lookupFromEnv(ruleEngineConfig.extFuncDescIndex, actionName) != NULL ) {
967  safe_to_redirect_to_re_framework = false;
968  }
969 
970  // if redirecting to framework with something besides strings and expecting the call to eventually be handled by a microservice,
971  // the code that converts REPF arguments back to msParams will need to be updated to handle the new types
972  for (unsigned int i = 0; i < nargs; i++) {
973  if (TYPE(args[i]) != T_STRING) {
974  safe_to_redirect_to_re_framework = false;
975  break;
976  }
977  }
978 
979  if (safe_to_redirect_to_re_framework) {
982 
983  irods::error err;
984  std::vector<std::string> args_storage;
985  args_storage.reserve(nargs);
986  std::list<boost::any> args2;
987  for(unsigned int i = 0; i < nargs; i++) {
988  args_storage.emplace_back(args[i]->text);
989  args2.emplace_back(&args_storage.back());
990  }
991  err = re_ctx_mgr.exec_rule(action, irods::unpack(args2));
992  for(unsigned int i = 0; i < nargs; i++) {
993  args[i] = newStringRes(r, args_storage[i].c_str());
994  }
995  if(err.ok()) {
996  return newIntRes(r, err.code() );
997  } else {
998  return newErrorRes( r, err.code() );
999  }
1000 
1001  } else {
1002  // =-=-=-=-=-=-=-
1003  // didnt find a rule, try a msvc
1004  irods::ms_table_entry ms_entry;
1005  int actionInx = actionTableLookUp( ms_entry, action );
1006  if ( actionInx >= 0 ) { /* rule */
1007 
1008  return execMicroService3( action, args, nargs, node, env, rei, errmsg, r );
1009  }
1010  else {
1011  snprintf( buf, ERR_MSG_LEN, "error: cannot find rule for action \"%s\" available: %d.", action, availableRules() );
1012  generateErrMsg( buf, NODE_EXPR_POS( node ), node->base, buf2 );
1015  }
1016 
1017  }
1018 
1019  }
1020  else {
1021  return actionRet;
1022  }
1023 }
1024 
1025 
1026 
1030 Res* execMicroService3( char *msName, Res **args, unsigned int nargs, Node *node, Env *env, ruleExecInfo_t *rei, rError_t *errmsg, Region *r ) {
1031  Res *res = NULL;
1032 
1033  /* look up the micro service */
1034  irods::ms_table_entry ms_entry;
1035  int actionInx = actionTableLookUp( ms_entry, msName );
1036 
1037  char errbuf[ERR_MSG_LEN];
1038  if ( actionInx < 0 ) {
1039  int ret = NO_MICROSERVICE_FOUND_ERR;
1040  generateErrMsg( "execMicroService3: no micro service found", NODE_EXPR_POS( node ), node->base, errbuf );
1041  addRErrorMsg( errmsg, ret, errbuf );
1042  return newErrorRes( r, ret );
1043 
1044  }
1045 
1046  unsigned int numOfStrArgs = ms_entry.num_args();
1047  if ( nargs != numOfStrArgs ) {
1048  int ret = ACTION_ARG_COUNT_MISMATCH;
1049  generateErrMsg( "execMicroService3: wrong number of arguments", NODE_EXPR_POS( node ), node->base, errbuf );
1050  addRErrorMsg( errmsg, ret, errbuf );
1051  return newErrorRes( r, ret );
1052  }
1053 
1054  std::vector<msParam_t*> myArgv;
1055  myArgv.resize( numOfStrArgs );
1056 
1057  /* convert arguments from Res to msParam_t */
1058  /* char buf[1024]; */
1059  int fillInParamLabel = node->degree == 2 && node->subtrees[1]->degree == ( int ) numOfStrArgs;
1060  for ( unsigned int i = 0; i < numOfStrArgs; i++ ) {
1061  myArgv[i] = ( msParam_t * )malloc( sizeof( msParam_t ) );
1062  Res *res = args[i];
1063  if ( res != NULL ) {
1064  int ret =
1065  convertResToMsParam( myArgv[i], res, errmsg );
1066  if ( ret != 0 ) {
1067  generateErrMsg( "execMicroService3: error converting arguments to MsParam", NODE_EXPR_POS( node->subtrees[1]->subtrees[i] ), node->subtrees[1]->subtrees[i]->base, errbuf );
1068  addRErrorMsg( errmsg, ret, errbuf );
1069  for ( int j = i - 1; j >= 0; j-- ) {
1070  int freeStruct = 1;
1071  if ( NULL != args[j] && NULL != args[j]->exprType ) {
1072  freeStruct = ( T_IRODS != TYPE( args[j] ) ) ? 1 : 0;
1073  }
1074  clearMsParam( myArgv[j], freeStruct );
1075  free( myArgv[j] );
1076  }
1077  return newErrorRes( r, ret );
1078  }
1079  myArgv[i]->label = fillInParamLabel && isVariableNode( node->subtrees[1]->subtrees[i] ) ? strdup( node->subtrees[1]->subtrees[i]->text ) : NULL;
1080  }
1081  else {
1082  myArgv[i]->inOutStruct = NULL;
1083  myArgv[i]->inpOutBuf = NULL;
1084  myArgv[i]->type = strdup( STR_MS_T );
1085  }
1086  /* sprintf(buf,"**%d",i); */
1087  /* myArgv[i]->label = strdup(buf); */
1088  }
1089  int ii = 0;
1090 
1091  if ( GlobalREAuditFlag > 0 ) {
1092  RuleEngineEventParam param;
1093  param.actionName = msName;
1094  param.ruleIndex = -1;
1095  reDebug( EXEC_MICRO_SERVICE_BEGIN, -4, &param, node, env, rei );
1096  }
1097 
1098  ii = ms_entry.call( rei, myArgv );
1099 
1100  /* move errmsgs from rei to errmsg */
1101  if ( rei->rsComm != NULL ) {
1102  replErrorStack( &rei->rsComm->rError, errmsg );
1103  freeRErrorContent( &rei->rsComm->rError );
1104  }
1105 
1106  if ( ii < 0 ) {
1107  if ( strcmp( msName, "msiExecCmd" ) == 0 ) {
1108  for ( unsigned int i = 0; i < numOfStrArgs; i++ ) {
1109  if ( myArgv[i] != NULL ) {
1110  res = convertMsParamToRes( myArgv[i], r );
1111  args[i] = res;
1112  }
1113  else {
1114  args[i] = NULL;
1115  }
1116  }
1117  }
1118  res = newErrorRes( r, ii );
1119  RETURN;
1120  }
1121 
1122  if ( GlobalREAuditFlag > 0 ) {
1123  RuleEngineEventParam param;
1124  param.actionName = msName;
1125  param.ruleIndex = -1;
1126  reDebug( EXEC_MICRO_SERVICE_END, -4, &param, node, env, rei );
1127  }
1128 
1129  /* params */
1130  for ( unsigned int i = 0; i < numOfStrArgs; i++ ) {
1131  if ( myArgv[i] != NULL ) {
1132  res = convertMsParamToRes( myArgv[i], r );
1133  if ( res != NULL && getNodeType( res ) == N_ERROR ) {
1134  generateErrMsg( "execMicroService3: error converting arguments from MsParam", NODE_EXPR_POS( node ), node->base, errbuf );
1135  addRErrorMsg( errmsg, RES_ERR_CODE(res), errbuf );
1136  RETURN;
1137  }
1138  args[i] = res;
1139  }
1140  else {
1141  args[i] = NULL;
1142  }
1143  }
1144 
1145  /*
1146  char vn[100];
1147  for(i=0;i<numOfStrArgs;i++) {
1148  sprintf(vn,"**%d",i);
1149  largs[i] = lookupFromHashTable(env, vn);
1150  }
1151  */
1152  res = newIntRes( r, ii );
1153 ret:
1154  for ( unsigned int i = 0; i < numOfStrArgs; i++ ) {
1155  int freeStruct = 1;
1156  if ( NULL != args[i] && NULL != args[i]->exprType ) {
1157  freeStruct = ( T_IRODS != TYPE( args[i] ) ) ? 1 : 0;
1158  }
1159  clearMsParam( myArgv[i], freeStruct );
1160  free( myArgv[i] );
1161  }
1162  if ( getNodeType( res ) == N_ERROR ) {
1163  generateErrMsg( "execMicroService3: error when executing microservice", NODE_EXPR_POS( node ), node->base, errbuf );
1164  addRErrorMsg( errmsg, RES_ERR_CODE( res ), errbuf );
1165  }
1166  return res;
1167 }
1168 
1169 Res* execRuleFromCondIndex( char *ruleName, Res **args, int argc, CondIndexVal *civ, int applyAll, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r ) {
1170  /*printTree(civ->condExp, 0); */
1171  Res *status;
1172  Env *envNew = newEnv( newHashTable2( 10, r ), globalEnv( env ), env, r );
1173  RuleDesc *rd;
1174  Node* rule = NULL;
1175  RuleIndexListNode *indexNode = NULL;
1176  Res* res = NULL;
1177 
1178 
1179  if ( civ->params->degree != argc ) {
1180  char buf[ERR_MSG_LEN];
1181  snprintf( buf, ERR_MSG_LEN, "error: cannot apply rule %s from rule conditional index because of wrong number of arguments, declared %d, supplied %d.", ruleName, civ->params->degree, argc );
1184  }
1185 
1186  int i = initializeEnv( civ->params, args, argc, envNew->current );
1187  if ( i != 0 ) {
1188  status = newErrorRes( r, i );
1189  RETURN;
1190  }
1191 
1192  res = evaluateExpression3( civ->condExp, 0, 0, rei, reiSaveFlag, envNew, errmsg, r );
1193  if ( getNodeType( res ) == N_ERROR ) {
1194  status = res;
1195  RETURN;
1196  }
1197  if ( TYPE( res ) != T_STRING ) {
1198  /* todo try coercion */
1199  addRErrorMsg( errmsg, RE_DYNAMIC_TYPE_ERROR, "error: the lhs of indexed rule condition does not evaluate to a string" );
1201  RETURN;
1202  }
1203 
1204  indexNode = ( RuleIndexListNode * )lookupFromHashTable( civ->valIndex, res->text );
1205  if ( indexNode == NULL ) {
1206 #ifndef DEBUG
1207  rodsLog( LOG_NOTICE, "cannot find rule in condIndex: %s", ruleName );
1208 #endif
1210  RETURN;
1211  }
1212 
1213  rd = getRuleDesc( indexNode->ruleIndex ); /* increase the index to move it to core rules index below MAX_NUM_APP_RULES are app rules */
1214 
1215  if ( rd->ruleType != RK_REL && rd->ruleType != RK_FUNC ) {
1216 #ifndef DEBUG
1217  rodsLog( LOG_NOTICE, "wrong node type in condIndex: %s", ruleName );
1218 #endif
1220  RETURN;
1221  }
1222 
1223  rule = rd->node;
1224 
1225  status = execRuleNodeRes( rule, args, argc, applyAll > 1 ? applyAll : 0, env, rei, reiSaveFlag, errmsg, r );
1226 
1227  if ( getNodeType( status ) == N_ERROR ) {
1228  rodsLog( LOG_NOTICE, "execRuleFromCondIndex: applyRule Failed: %s with status %i", ruleName, RES_ERR_CODE( status ) );
1229  }
1230 
1231 ret:
1232  /* deleteEnv(envNew, 2); */
1233  return status;
1234 
1235 
1236 }
1237 /*
1238  * look up rule node by rulename from index
1239  * apply rule condition index if possible
1240  * call execRuleNodeRes until success or no more rules
1241  */
1242 Res *execRule( char *ruleNameInp, Res** args, unsigned int argc, int applyAllRuleInp, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r ) {
1243  int ruleInx = 0, statusI;
1244  Res *statusRes = NULL;
1245  int inited = 0;
1246  ruleExecInfo_t *saveRei = NULL;
1247  int reTryWithoutRecovery = 0;
1248  char ruleName[MAX_NAME_LEN];
1249  int applyAllRule = applyAllRuleInp;
1250 
1251 #ifdef DEBUG
1252  char buf[1024];
1253  snprintf( buf, 1024, "execRule: %s\n", ruleNameInp );
1254  writeToTmp( "entry.log", buf );
1255 #endif
1256 
1257  ruleInx = 0; /* new rule */
1258  if ( strlen( ruleNameInp ) < sizeof( ruleName ) ) {
1259  snprintf( ruleName, sizeof( ruleName ), "%s", ruleNameInp );
1260  }
1261  else {
1262  rodsLog( LOG_ERROR, "ruleName: [%s] must be fewer than %ju characters in length.",
1263  ruleNameInp, sizeof( ruleName ) );
1264  ruleName[0] = '\0';
1265  }
1266 
1267  mapExternalFuncToInternalProc2( ruleName );
1268 
1269  int systemSpaceRuleFlag = ( reiSaveFlag & SYSTEM_SPACE_RULE ) != 0 || lookupFromHashTable( ruleEngineConfig.coreFuncDescIndex->current, ruleName ) != NULL ? SYSTEM_SPACE_RULE : 0;
1270  int _reiSaveFlag = reiSaveFlag & SAVE_REI;
1271 
1273  int success = 0;
1274  int first = 1;
1275  while ( 1 ) {
1276  if ( systemSpaceRuleFlag != 0 ) {
1278  }
1279  else {
1280  statusI = findNextRule2( ruleName, ruleInx, &ruleIndexListNode );
1281  }
1282 
1283  if ( statusI != 0 ) {
1284  if ( applyAllRule == 0 ) {
1285 #ifndef DEBUG
1286 // rodsLog (LOG_NOTICE,"execRule: no more rules: %s with status %i",ruleName, statusI);
1287 #endif
1288  statusRes = statusRes == NULL ? newErrorRes( r, NO_RULE_FOUND_ERR ) : statusRes;
1289  }
1290  else { // apply all rules succeeds even when 0 rule is applied
1291  success = 1;
1292  }
1293  break;
1294  }
1295  if ( _reiSaveFlag == SAVE_REI ) {
1296  int statusCopy = 0;
1297  if ( inited == 0 ) {
1298  saveRei = ( ruleExecInfo_t * ) mallocAndZero( sizeof( ruleExecInfo_t ) );
1299  statusCopy = copyRuleExecInfo( rei, saveRei );
1300  inited = 1;
1301  }
1302  else if ( reTryWithoutRecovery == 0 ) {
1303  statusCopy = copyRuleExecInfo( saveRei, rei );
1304  }
1305  if ( statusCopy != 0 ) {
1306  statusRes = newErrorRes( r, statusCopy );
1307  break;
1308  }
1309  }
1310 
1311  if ( !first ) {
1312  addRErrorMsg( errmsg, statusI, ERR_MSG_SEP );
1313  }
1314  else {
1315  first = 0;
1316  }
1317 
1319  statusRes = execRuleFromCondIndex( ruleName, args, argc, ruleIndexListNode->condIndex, applyAllRule, env, rei, reiSaveFlag | systemSpaceRuleFlag, errmsg, r );
1320  }
1321  else {
1322 
1324  if ( rd->ruleType == RK_REL || rd->ruleType == RK_FUNC ) {
1325 
1326  Node* rule = rd->node;
1327  unsigned int inParamsCount = RULE_NODE_NUM_PARAMS( rule );
1328  if ( inParamsCount != argc ) {
1329  ruleInx++;
1330  continue;
1331  }
1332 
1333  if ( GlobalREAuditFlag > 0 ) {
1334  RuleEngineEventParam param;
1335  param.actionName = ruleName;
1336  param.ruleIndex = ruleInx;
1337  reDebug( GOT_RULE, 0, &param, rule, env, rei );
1338 
1339  }
1340 
1341 #ifndef DEBUG
1342  if ( reTestFlag > 0 ) {
1343  if ( reTestFlag == COMMAND_TEST_1 ) {
1344  fprintf( stdout, "+Testing Rule Number:%i for Action:%s\n", ruleInx, ruleName );
1345  }
1346  else if ( reTestFlag == HTML_TEST_1 ) {
1347  fprintf( stdout, "+Testing Rule Number:<FONT COLOR=#FF0000>%i</FONT> for Action:<FONT COLOR=#0000FF>%s</FONT><BR>\n", ruleInx, ruleName );
1348  }
1349  else if ( rei != 0 && rei->rsComm != 0 && &( rei->rsComm->rError ) != 0 ) {
1350  rodsLog( LOG_NOTICE, "+Testing Rule Number:%i for Action:%s\n", ruleInx, ruleName );
1351  }
1352  }
1353 #endif
1354  /* printTree(rule, 0); */
1355 
1356  statusRes = execRuleNodeRes( rule, args, argc, applyAllRule > 1 ? applyAllRule : 0, env, rei, reiSaveFlag | systemSpaceRuleFlag, errmsg, r );
1357 
1358  }
1359  }
1360  if ( statusRes != NULL && getNodeType( statusRes ) != N_ERROR ) {
1361  success = 1;
1362  if ( applyAllRule == 0 ) { /* apply first rule */
1363  break;
1364  }
1365  else { /* apply all rules */
1366  if ( _reiSaveFlag == SAVE_REI ) {
1367  freeRuleExecInfoStruct( saveRei, 0 );
1368  inited = 0;
1369  }
1370  }
1371  }
1372  else if ( statusRes != NULL && RES_ERR_CODE( statusRes ) == RETRY_WITHOUT_RECOVERY_ERR ) {
1373  reTryWithoutRecovery = 1;
1374  }
1375  else if ( statusRes != NULL && RES_ERR_CODE( statusRes ) == CUT_ACTION_PROCESSED_ERR ) {
1376  break;
1377  }
1378 
1379  ruleInx++;
1380  }
1381 
1382  if ( inited == 1 ) {
1383  freeRuleExecInfoStruct( saveRei, 0 );
1384  }
1385 
1386  if ( success ) {
1387  if ( applyAllRule ) {
1388  /* if we apply all rules, then it succeeds even if some of the rules fail */
1389  return newIntRes( r, 0 );
1390  }
1391  else if ( statusRes != NULL && TYPE( statusRes ) == T_SUCCESS ) {
1392  return newIntRes( r, 0 );
1393  }
1394  else {
1395  return statusRes;
1396  }
1397  }
1398  else {
1399 #ifndef DEBUG
1400 // rodsLog (LOG_NOTICE,"execRule: applyRule Failed: %s with status %i",ruleName, RES_ERR_CODE(statusRes));
1401 #endif
1402  return statusRes;
1403  }
1404 }
1405 void copyFromEnv( Res **args, char **inParams, int inParamsCount, Hashtable *env, Region *r ) {
1406  for ( int i = 0; i < inParamsCount; i++ ) {
1407  if ( Res * res = ( Res * )lookupFromHashTable( env, inParams[i] ) ) {
1408  args[i] = cpRes( res, r );
1409  }
1410  }
1411 }
1412 /*
1413  * execute a rule given by an AST node
1414  * create a new environment and intialize it with parameters
1415  */
1416 Res* execRuleNodeRes( Node *rule, Res** args, unsigned int argc, int applyAll, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r ) {
1417  int restoreGlobalREAuditFlag = 0;
1418  int globalREAuditFlag = 0;
1419  if ( GlobalREAuditFlag > 0 ) {
1420  /* get meta data */
1421  Node *metadata = rule->subtrees[4];
1422  int i;
1423  for ( i = 0; i < metadata->degree; i++ ) {
1424  Node *attribute = metadata->subtrees[i]->subtrees[0];
1425  Node *value = metadata->subtrees[i]->subtrees[1];
1426  if ( strcmp( attribute->text, "logging" ) == 0 && strcmp( value->text, "false" ) == 0 ) {
1427  restoreGlobalREAuditFlag = 1;
1428  globalREAuditFlag = GlobalREAuditFlag;
1429  GlobalREAuditFlag = 0;
1430  break;
1431  }
1432  }
1433 
1434  RuleEngineEventParam param;
1435  param.actionName = RULE_NAME( rule );
1436  param.ruleIndex = -1;
1437  reDebug( EXEC_RULE_BEGIN, -4, &param, rule, env, rei ); /* pass in NULL for inMsParamArray for now */
1438  }
1439  Node* ruleCondition = rule->subtrees[1];
1440  Node* ruleAction = rule->subtrees[2];
1441  Node* ruleRecovery = rule->subtrees[3];
1442  Node* ruleHead = rule->subtrees[0];
1443  Node** paramsNodes = ruleHead->subtrees[0]->subtrees;
1444  char* paramsNames[MAX_NUM_OF_ARGS_IN_ACTION];
1445  unsigned int inParamsCount = RULE_NODE_NUM_PARAMS( rule );
1446  Res *statusRes;
1447 
1448  if ( inParamsCount != argc ) {
1449  generateAndAddErrMsg( "error: action argument count mismatch", rule, ACTION_ARG_COUNT_MISMATCH, errmsg );
1451 
1452  }
1453  unsigned int k;
1454  for ( k = 0; k < inParamsCount ; k++ ) {
1455  paramsNames[k] = paramsNodes[k]->text;
1456  }
1457 
1458  Env *global = globalEnv( env );
1459  Region *rNew = make_region( 0, NULL );
1460  Env *envNew = newEnv( newHashTable2( 10, rNew ), global, env, rNew );
1461 
1462  int statusInitEnv;
1463  /* printEnvToStdOut(envNew->current); */
1464  statusInitEnv = initializeEnv( ruleHead->subtrees[0], args, argc, envNew->current );
1465  if ( statusInitEnv != 0 ) {
1466  return newErrorRes( r, statusInitEnv );
1467  }
1468  /* printEnvToStdOut(envNew->current); */
1469  Res *res = evaluateExpression3( ruleCondition, 0, 0, rei, reiSaveFlag & ~ DISCARD_EXPRESSION_RESULT, envNew, errmsg, rNew );
1470  /* todo consolidate every error into T_ERROR except OOM */
1471  if ( getNodeType( res ) != N_ERROR && TYPE( res ) == T_BOOL && RES_BOOL_VAL( res ) != 0 ) {
1472  if ( getNodeType( ruleAction ) == N_ACTIONS ) {
1473  statusRes = evaluateActions( ruleAction, ruleRecovery, applyAll, rei, reiSaveFlag, envNew, errmsg, rNew );
1474  }
1475  else {
1476  statusRes = evaluateExpression3( ruleAction, applyAll, 0, rei, reiSaveFlag, envNew, errmsg, rNew );
1477  }
1478  /* copy parameters */
1479  copyFromEnv( args, paramsNames, inParamsCount, envNew->current, r );
1480  /* copy return values */
1481  statusRes = cpRes( statusRes, r );
1482 
1483  if ( getNodeType( statusRes ) == N_ERROR ) {
1484 #ifndef DEBUG
1485  rodsLog( LOG_NOTICE, "execRuleNodeRes: applyRule Failed: %s with status %i", ruleHead->text, RES_ERR_CODE( statusRes ) );
1486 #endif
1487  }
1488  }
1489  else {
1490  if ( getNodeType( res ) != N_ERROR && TYPE( res ) != T_BOOL ) {
1491  char buf[ERR_MSG_LEN];
1492  generateErrMsg( "error: the rule condition does not evaluate to a boolean value", NODE_EXPR_POS( ruleCondition ), ruleCondition->base, buf );
1493  addRErrorMsg( errmsg, RE_TYPE_ERROR, buf );
1494  }
1495  statusRes = newErrorRes( r, RULE_FAILED_ERR );
1496  }
1497  /* copy global variables */
1498  cpEnv( global, r );
1499  /* deleteEnv(envNew, 2); */
1500  region_free( rNew );
1501  if ( GlobalREAuditFlag > 0 ) {
1502  RuleEngineEventParam param;
1503  param.actionName = RULE_NAME( rule );
1504  param.ruleIndex = -1;
1505  reDebug( EXEC_RULE_END, -4, &param, rule, env, rei );
1506  }
1507 
1508  if ( restoreGlobalREAuditFlag != 0 ) {
1509  GlobalREAuditFlag = globalREAuditFlag;
1510  }
1511 
1512  return statusRes;
1513 
1514 }
1515 
1516 Res* matchPattern( Node *pattern, Node *val, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r ) {
1517  char errbuf[ERR_MSG_LEN];
1518  char *localErrorMsg = NULL;
1519  Node *p = pattern, *v = val;
1520  Res *res;
1521  char *varName;
1522  char matcherName[MAX_NAME_LEN];
1524 
1525  if ( getNodeType( pattern ) == N_APPLICATION && pattern->subtrees[1]->degree == 0 ) {
1526  char *fn = pattern->subtrees[0]->text;
1527  if ( findNextRule2( fn, 0, &node ) == 0 && node->secondaryIndex == 0 ) {
1528  RuleDesc *rd = getRuleDesc( node->ruleIndex );
1529  if ( rd->ruleType == RK_FUNC &&
1530  ( getNodeType( rd->node->subtrees[2] ) == TK_BOOL ||
1531  getNodeType( rd->node->subtrees[2] ) == TK_STRING ||
1532  getNodeType( rd->node->subtrees[2] ) == TK_INT ||
1533  getNodeType( rd->node->subtrees[2] ) == TK_DOUBLE ) ) {
1534  pattern = rd->node->subtrees[2];
1535  }
1536  }
1537  }
1538 
1539  switch ( getNodeType( pattern ) ) {
1540  case N_APPLICATION:
1541  if ( strcmp( N_APP_FUNC( pattern )->text, "." ) == 0 ) {
1542  char *key = NULL;
1543  RE_ERROR2( TYPE( v ) != T_STRING , "not a string." );
1544  if ( getNodeType( N_APP_ARG( pattern, 1 ) ) == N_APPLICATION && N_APP_ARITY( N_APP_ARG( pattern, 1 ) ) == 0 ) {
1545  key = N_APP_FUNC( N_APP_ARG( pattern, 1 ) )->text;
1546  }
1547  else {
1548  Res *res = evaluateExpression3( N_APP_ARG( pattern, 1 ), 0, 1, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, r );
1549  if ( res->exprType != NULL && TYPE( res ) == T_STRING ) {
1550  key = res->text;
1551  }
1552  else {
1553  RE_ERROR2( 1, "malformatted key pattern." );
1554  }
1555  }
1556  varName = N_APP_ARG( pattern, 0 )->text;
1557  if ( getNodeType( N_APP_ARG( pattern, 0 ) ) == TK_VAR && varName[0] == '*' &&
1558  ( ( res = ( Res * ) lookupFromEnv( env, varName ) ) == NULL || TYPE( res ) == T_UNSPECED ) ) { /* if local var is empty then create new kvp */
1559  keyValPair_t *kvp = ( keyValPair_t * ) malloc( sizeof( keyValPair_t ) );
1560  memset( kvp, 0, sizeof( keyValPair_t ) );
1561  Res *res2 = newUninterpretedRes( r, KeyValPair_MS_T, kvp, NULL );
1562  if ( res != NULL ) {
1563  updateInEnv( env, varName, res2 );
1564  }
1565  else {
1566  if ( insertIntoHashTable( env->current, varName, res2 ) == 0 ) {
1567  char localErrorMsg[ERR_MSG_LEN];
1568  snprintf( localErrorMsg, ERR_MSG_LEN, "error: unable to write to local variable \"%s\".", varName );
1569  generateErrMsg( localErrorMsg, NODE_EXPR_POS( N_APP_ARG( pattern, 0 ) ), N_APP_ARG( pattern, 0 )->base, errbuf );
1570  addRErrorMsg( errmsg, RE_UNABLE_TO_WRITE_LOCAL_VAR, errbuf );
1572  }
1573  }
1574 
1575  res = res2;
1576  }
1577  else {
1578  res = evaluateExpression3( N_APP_ARG( pattern, 0 ), 0, 0, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, r ); /* kvp */
1579  CASCADE_N_ERROR( res );
1580  RE_ERROR2( TYPE( res ) != T_IRODS || strcmp( res->exprType->text, KeyValPair_MS_T ) != 0, "not a KeyValPair." );
1581  }
1582  addKeyVal( ( keyValPair_t* ) RES_UNINTER_STRUCT( res ), key, v->text );
1583  return newIntRes( r, 0 );
1584  }
1585  else {
1586  matcherName[0] = '~';
1587  strcpy( matcherName + 1, pattern->subtrees[0]->text );
1588  if ( findNextRule2( matcherName, 0, &node ) == 0 ) {
1589  v = execRule( matcherName, &val, 1, 0, env, rei, reiSaveFlag, errmsg, r );
1590  RE_ERROR2( getNodeType( v ) == N_ERROR, "user defined pattern function error" );
1591  if ( getNodeType( v ) != N_TUPLE ) {
1592  Res **tupleComp = ( Res ** )region_alloc( r, sizeof( Res * ) );
1593  *tupleComp = v;
1594  v = newTupleRes( 1, tupleComp , r );
1595  }
1596  }
1597  else {
1598  RE_ERROR2( v->text == NULL || strcmp( pattern->subtrees[0]->text, v->text ) != 0, "pattern mismatch constructor" );
1599  Res **tupleComp = ( Res ** )region_alloc( r, sizeof( Res * ) * v->degree );
1600  memcpy( tupleComp, v->subtrees, sizeof( Res * ) * v->degree );
1601  v = newTupleRes( v->degree, tupleComp , r );
1602  }
1603  res = matchPattern( p->subtrees[1], v, env, rei, reiSaveFlag, errmsg, r );
1604  return res;
1605  }
1606  case TK_VAR:
1607  varName = pattern->text;
1608  if ( varName[0] == '*' ) {
1609  if ( lookupFromEnv( env, varName ) == NULL ) {
1610  /* new variable */
1611  if ( insertIntoHashTable( env->current, varName, val ) == 0 ) {
1612  char localErrorMsg[ERR_MSG_LEN];
1613  snprintf( localErrorMsg, ERR_MSG_LEN, "error: unable to write to local variable \"%s\".", varName );
1614  generateErrMsg( localErrorMsg, NODE_EXPR_POS( pattern ), pattern->base, errbuf );
1615  addRErrorMsg( errmsg, RE_UNABLE_TO_WRITE_LOCAL_VAR, errbuf );
1617  }
1618  }
1619  else {
1620  updateInEnv( env, varName, val );
1621  }
1622  }
1623  else if ( varName[0] == '$' ) {
1624  return setVariableValue( varName, val, pattern, rei, env, errmsg, r );
1625  }
1626  return newIntRes( r, 0 );
1627 
1628  case N_TUPLE:
1629  RE_ERROR2( getNodeType( v ) != N_TUPLE, "pattern mismatch value is not a tuple." );
1630  RE_ERROR2( p->degree != v->degree, "pattern mismatch arity" );
1631  int i;
1632  for ( i = 0; i < p->degree; i++ ) {
1633  Res *res = matchPattern( p->subtrees[i], v->subtrees[i], env, rei, reiSaveFlag, errmsg, r );
1634  if ( getNodeType( res ) == N_ERROR ) {
1635  return res;
1636  }
1637  }
1638  return newIntRes( r, 0 );
1639  case TK_STRING:
1640  RE_ERROR2( getNodeType( v ) != N_VAL || TYPE( v ) != T_STRING, "pattern mismatch value is not a string." );
1641  RE_ERROR2( strcmp( pattern->text, v->text ) != 0 , "pattern mismatch string." );
1642  return newIntRes( r, 0 );
1643  case TK_BOOL:
1644  RE_ERROR2( getNodeType( v ) != N_VAL || TYPE( v ) != T_BOOL, "pattern mismatch value is not a boolean." );
1645  res = evaluateExpression3( pattern, 0, 1, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, r );
1646  CASCADE_N_ERROR( res );
1647  RE_ERROR2( RES_BOOL_VAL( res ) != RES_BOOL_VAL( v ) , "pattern mismatch boolean." );
1648  return newIntRes( r, 0 );
1649  case TK_INT:
1650  RE_ERROR2( getNodeType( v ) != N_VAL || ( TYPE( v ) != T_INT && TYPE( v ) != T_DOUBLE ), "pattern mismatch value is not an integer." );
1651  res = evaluateExpression3( pattern, 0, 1, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, r );
1652  CASCADE_N_ERROR( res );
1653  RE_ERROR2( RES_INT_VAL( res ) != ( TYPE( v ) == T_INT ? RES_INT_VAL( v ) : RES_DOUBLE_VAL( v ) ) , "pattern mismatch integer." );
1654  return newIntRes( r, 0 );
1655  case TK_DOUBLE:
1656  RE_ERROR2( getNodeType( v ) != N_VAL || ( TYPE( v ) != T_DOUBLE && TYPE( v ) != T_INT ), "pattern mismatch value is not a double." );
1657  res = evaluateExpression3( pattern, 0, 1, rei, reiSaveFlag & ~DISCARD_EXPRESSION_RESULT, env, errmsg, r );
1658  CASCADE_N_ERROR( res );
1659  RE_ERROR2( RES_DOUBLE_VAL( res ) != ( TYPE( v ) == T_DOUBLE ? RES_DOUBLE_VAL( v ) : RES_INT_VAL( v ) ), "pattern mismatch integer." );
1660  return newIntRes( r, 0 );
1661  default:
1662  RE_ERROR2( 1, "malformatted pattern error" );
1663  break;
1664  }
1665 error:
1666  generateErrMsg( localErrorMsg, NODE_EXPR_POS( pattern ), pattern->base, errbuf );
1667  rodsLog(LOG_DEBUG, errbuf);
1668  return newErrorRes( r, RE_PATTERN_NOT_MATCHED );
1669 
1670 }
1671 
1672 Res *setVariableValue( char *varName, Res *val, Node *node, ruleExecInfo_t *rei, Env *env, rError_t *errmsg, Region *r ) {
1673  int i;
1674  char *varMap;
1675  char errbuf[ERR_MSG_LEN];
1676  if ( varName[0] == '$' ) {
1677  const char *arg = varName + 1;
1678  if ( ( i = applyRuleArg( "acPreProcForWriteSessionVariable", &arg, 1, rei, 0 ) ) < 0 ) {
1679  return newErrorRes( r, i );
1680  }
1681  i = getVarMap( "", varName, &varMap, 0 );
1682  if ( i < 0 ) {
1683  snprintf( errbuf, ERR_MSG_LEN, "error: unsupported session variable \"%s\".", varName );
1684  addRErrorMsg( errmsg, RE_UNSUPPORTED_SESSION_VAR, errbuf );
1685  free( varMap );
1687  }
1689  Hashtable *tvarEnv = newHashTable2( 10, r );
1690  if ( fd != NULL ) {
1691  ExprType *type = fd->exprType->subtrees[0]; /* get var type from varMap */
1692  val = processCoercion( node, val, type, tvarEnv, errmsg, r );
1693  if ( getNodeType( val ) == N_ERROR ) {
1694  free( varMap );
1695  return val;
1696  }
1697  }
1698  ExprType *varType = getVarType( varMap, r );
1699  val = processCoercion( node, val, varType, tvarEnv, errmsg, r );
1700  if ( getNodeType( val ) == N_ERROR ) {
1701  free( varMap );
1702  return val;
1703  }
1704  setVarValue( varMap, rei, val );
1705  free( varMap );
1706  return newIntRes( r, 0 );
1707  }
1708  else if ( varName[0] == '*' ) {
1709  if ( lookupFromEnv( env, varName ) == NULL ) {
1710  /* new variable */
1711  if ( insertIntoHashTable( env->current, varName, val ) == 0 ) {
1712  snprintf( errbuf, ERR_MSG_LEN, "error: unable to write to local variable \"%s\".", varName );
1713  addRErrorMsg( errmsg, RE_UNABLE_TO_WRITE_LOCAL_VAR, errbuf );
1715  }
1716  }
1717  else {
1718  updateInEnv( env, varName, val );
1719  }
1720  return newIntRes( r, 0 );
1721  }
1722  return newIntRes( r, 0 );
1723 }
1724 
1725 int definitelyEq( Res *a, Res *b ) {
1726  if ( a != b && TYPE( a ) == TYPE( b ) ) {
1727  switch ( TYPE( a ) ) {
1728  case T_INT:
1729  return RES_INT_VAL( a ) == RES_INT_VAL( b );
1730  case T_DOUBLE:
1731  return RES_DOUBLE_VAL( a ) == RES_DOUBLE_VAL( b );
1732  case T_STRING:
1733  return strcmp( a->text, b->text ) == 0 ? 1 : 0;
1734  case T_DATETIME:
1735  return RES_TIME_VAL( a ) == RES_TIME_VAL( b );
1736  case T_BOOL:
1737  return RES_BOOL_VAL( a ) == RES_BOOL_VAL( b );
1738  case T_IRODS:
1740  case T_PATH:
1741  return strcmp( a->text, b->text ) == 0 ? 1 : 0;
1742  case T_CONS:
1743  if ( a->degree == b->degree ) {
1744  if ( a->text == b->text || strcmp( a->text, b->text ) == 0 ) {
1745  int res = 1;
1746  for ( int i = 0; i < a->degree; i++ ) {
1747  if ( !definitelyEq( a->subtrees[i], b->subtrees[i] ) ) {
1748  res = 0;
1749  break;
1750  }
1751  }
1752  return res;
1753  }
1754  }
1755  return 0;
1756  case T_TUPLE:
1757  if ( a->degree == b->degree ) {
1758  int res = 1;
1759  for ( int i = 0; i < a->degree; i++ ) {
1760  if ( !definitelyEq( a->subtrees[i], b->subtrees[i] ) ) {
1761  res = 0;
1762  break;
1763  }
1764  }
1765  return res;
1766  }
1767  return 0;
1768  default:
1769  return 0;
1770  }
1771 
1772  }
1773  return a == b;
1774 }
NO_RULE_FOUND_ERR
@ NO_RULE_FOUND_ERR
Definition: rodsErrorTable.h:593
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
processCoercion
Res * processCoercion(Node *node, Res *res, ExprType *type, Hashtable *tvarEnv, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:279
irods_error_name_map
static const std::map< const std::string, const int > irods_error_name_map
Definition: arithmetics.cpp:6
NULL
#define NULL
Definition: rodsDef.h:70
COMMAND_TEST_MSI
#define COMMAND_TEST_MSI
Definition: reDefines.h:35
reDebug
int reDebug(RuleEngineEvent callLabel, int flag, RuleEngineEventParam *param, Node *node, Env *env, ruleExecInfo_t *rei)
Definition: nre.reHelpers1.cpp:641
attemptToEvaluateVar3
Res * attemptToEvaluateVar3(char *vn, Node *node, ruleExecInfo_t *rei, Env *env, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:854
parser.hpp
generateAndAddErrMsg
void generateAndAddErrMsg(char *msg, Node *node, int errcode, rError_t *errmsg)
Definition: parser.cpp:3550
addKeyVal
int addKeyVal(keyValPair_t *condInput, const char *keyWord, const char *value)
Definition: rcMisc.cpp:789
convertResToString
char * convertResToString(Res *res0)
Definition: conversion.cpp:556
TK_BOOL
@ TK_BOOL
Definition: restructs.hpp:116
GlobalREAuditFlag
int GlobalREAuditFlag
Definition: libirods_rule_engine_plugin-irods_rule_language.cpp:59
ACTION_ARG_COUNT_MISMATCH
@ ACTION_ARG_COUNT_MISMATCH
Definition: rodsErrorTable.h:597
NO_MICROSERVICE_FOUND_ERR
@ NO_MICROSERVICE_FOUND_ERR
Definition: rodsErrorTable.h:676
lookupFromEnv
const void * lookupFromEnv(Env *env, const char *key)
Definition: utils.cpp:813
IO_TYPE_OUTPUT
#define IO_TYPE_OUTPUT
Definition: restructs.hpp:82
COMMAND_TEST_1
#define COMMAND_TEST_1
Definition: reDefines.h:33
solveConstraints
Satisfiability solveConstraints(List *typingConstraints, Hashtable *typingEnv, rError_t *errmsg, Node **errnode, Region *r)
Definition: typing.cpp:550
GlobalREDebugFlag
int GlobalREDebugFlag
Definition: libirods_rule_engine_plugin-irods_rule_language.cpp:58
N_FD_DECONSTRUCTOR
@ N_FD_DECONSTRUCTOR
Definition: restructs.hpp:145
RE_PATTERN_NOT_MATCHED
@ RE_PATTERN_NOT_MATCHED
Definition: rodsErrorTable.h:710
RK_FUNC
@ RK_FUNC
Definition: restructs.hpp:265
FUNC
#define FUNC
Definition: reconstants.hpp:20
index.hpp
EXEC_MICRO_SERVICE_BEGIN
@ EXEC_MICRO_SERVICE_BEGIN
Definition: restructs.hpp:304
utils.hpp
RE_ERROR2
#define RE_ERROR2(x, y)
Definition: arithmetics.cpp:29
IO_TYPE_EXPRESSION
#define IO_TYPE_EXPRESSION
Definition: restructs.hpp:84
execRuleFromCondIndex
Res * execRuleFromCondIndex(char *ruleName, Res **args, int argc, CondIndexVal *civ, int applyAll, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:1169
irods::rule_engine_context_manager
Definition: irods_re_plugin.hpp:522
mapExternalFuncToInternalProc2
int mapExternalFuncToInternalProc2(char *funcName)
Definition: index.cpp:337
RE_DYNAMIC_COERCION_ERROR
@ RE_DYNAMIC_COERCION_ERROR
Definition: rodsErrorTable.h:723
copyFromEnv
void copyFromEnv(Res **args, char **inParams, int inParamsCount, Hashtable *env, Region *r)
Definition: arithmetics.cpp:1405
region_alloc
void * region_alloc(Region *r, size_t s)
Definition: region.cpp:138
initializeEnv
int initializeEnv(Node *params, Res *args[20], int argc, Hashtable *env)
Definition: arithmetics.cpp:34
run_tests.nargs
nargs
Definition: run_tests.py:125
NO_RULE_OR_MSI_FUNCTION_FOUND_ERR
@ NO_RULE_OR_MSI_FUNCTION_FOUND_ERR
Definition: rodsErrorTable.h:671
T_UNSPECED
@ T_UNSPECED
Definition: restructs.hpp:156
RE_DYNAMIC_TYPE_ERROR
@ RE_DYNAMIC_TYPE_ERROR
Definition: rodsErrorTable.h:722
definitelyEq
int definitelyEq(Res *a, Res *b)
Definition: arithmetics.cpp:1725
getNodeType
#define getNodeType(x)
Definition: restructs.hpp:69
N_PARTIAL_APPLICATION
@ N_PARTIAL_APPLICATION
Definition: restructs.hpp:129
RES_TIME_VAL
#define RES_TIME_VAL(x)
Definition: restructs.hpp:60
convertResToMsParam
int convertResToMsParam(msParam_t *var, Res *res, rError_t *errmsg)
Definition: conversion.cpp:350
getVarType
ExprType * getVarType(char *varMap, Region *r)
Definition: reVariableMap.cpp:136
env
Definition: restructs.hpp:226
EXEC_ACTION_END
@ EXEC_ACTION_END
Definition: restructs.hpp:306
restructs.hpp
configuration.hpp
IO_TYPE_ACTIONS
#define IO_TYPE_ACTIONS
Definition: restructs.hpp:85
RE_UNSUPPORTED_SESSION_VAR
@ RE_UNSUPPORTED_SESSION_VAR
Definition: rodsErrorTable.h:703
N_TUPLE_CONSTRUCT_TUPLE
#define N_TUPLE_CONSTRUCT_TUPLE(x)
Definition: restructs.hpp:52
irods::unpack
Definition: irods_re_plugin.hpp:66
evaluateVar3
Res * evaluateVar3(char *vn, Node *node, ruleExecInfo_t *rei, Env *env, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:879
typeToString
char * typeToString(ExprType *type, Hashtable *var_types, char *buf, int bufsize)
Definition: utils.cpp:522
RuleDesc::ruleType
RuleType ruleType
Definition: restructs.hpp:276
N_APP_ARITY
#define N_APP_ARITY(x)
Definition: restructs.hpp:44
pid_age.p
p
Definition: pid_age.py:13
T_DOUBLE
@ T_DOUBLE
Definition: restructs.hpp:159
T_PATH
@ T_PATH
Definition: restructs.hpp:168
getRuleDesc
RuleDesc * getRuleDesc(int ri)
Definition: rules.cpp:595
RULE_NODE_NUM_PARAMS
#define RULE_NODE_NUM_PARAMS(r)
Definition: restructs.hpp:45
N_APPLICATION
@ N_APPLICATION
Definition: restructs.hpp:128
make_region
Region * make_region(size_t is, jmp_buf *label)
Definition: region.cpp:85
T_BREAK
@ T_BREAK
Definition: restructs.hpp:169
RES_DOUBLE_VAL
#define RES_DOUBLE_VAL(x)
Definition: restructs.hpp:57
node
Definition: restructs.hpp:244
datetime.hpp
LOG_TEST_1
#define LOG_TEST_1
Definition: reDefines.h:31
condIndexVal::condExp
Node * condExp
Definition: restructs.hpp:209
N_FD_RULE_INDEX_LIST
@ N_FD_RULE_INDEX_LIST
Definition: restructs.hpp:147
TYPE
#define TYPE(x)
Definition: restructs.hpp:23
ruleIndexListNode::ruleIndex
int ruleIndex
Definition: restructs.hpp:216
T_VAR_DISJUNCT
#define T_VAR_DISJUNCT(x, n)
Definition: restructs.hpp:35
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
ruleIndexListNode::secondaryIndex
int secondaryIndex
Definition: restructs.hpp:215
CASCADE_N_ERROR
#define CASCADE_N_ERROR(x)
Definition: utils.hpp:22
N_SYM_LINK
@ N_SYM_LINK
Definition: restructs.hpp:148
RES_UNINTER_BUFFER
#define RES_UNINTER_BUFFER(x)
Definition: restructs.hpp:66
run_tests.action
action
Definition: run_tests.py:114
copyRuleExecInfo
int copyRuleExecInfo(ruleExecInfo_t *from, ruleExecInfo_t *to)
Definition: reStruct.cpp:21
TK_INT
@ TK_INT
Definition: restructs.hpp:112
ruleEngineEventParam::actionName
char * actionName
Definition: restructs.hpp:319
OPTION_COERCE
#define OPTION_COERCE
Definition: restructs.hpp:77
T_CONS
@ T_CONS
Definition: restructs.hpp:167
mallocAndZero
void * mallocAndZero(int s)
Definition: reStruct.cpp:13
STR_MS_T
#define STR_MS_T
Definition: msParam.h:21
newPartialApplication
Node * newPartialApplication(Node *func, Node *arg, int nArgsLeft, Region *r)
Definition: restructs.cpp:137
irods_re_plugin.hpp
deconstruct
Node * deconstruct(Node **args, int proj)
Definition: functions.cpp:2518
RuleExecInfo::rsComm
rsComm_t * rsComm
Definition: irods_re_structs.hpp:22
freeRuleExecInfoStruct
int freeRuleExecInfoStruct(ruleExecInfo_t *rs, int freeSpecialStructFlag)
Definition: reStruct.cpp:100
IO_TYPE_DYNAMIC
#define IO_TYPE_DYNAMIC
Definition: restructs.hpp:83
node::text
char * text
Definition: restructs.hpp:252
functions.hpp
TK_VAR
@ TK_VAR
Definition: restructs.hpp:119
newIntRes
Res * newIntRes(Region *r, int n)
Definition: restructs.cpp:204
DISCARD_EXPRESSION_RESULT
#define DISCARD_EXPRESSION_RESULT
Definition: restructs.hpp:93
getVariableName
char * getVariableName(Node *node)
Definition: arithmetics.cpp:45
EXEC_MICRO_SERVICE_END
@ EXEC_MICRO_SERVICE_END
Definition: restructs.hpp:307
IO_TYPE_INPUT
#define IO_TYPE_INPUT
Definition: restructs.hpp:81
newHashTable2
Hashtable * newHashTable2(int size, Region *r)
Definition: hashtable.cpp:72
rsComm_t::rError
rError_t rError
Definition: rcConnect.h:158
irods::error::code
long long code() const
Definition: irods_error.cpp:194
newUninterpretedRes
Res * newUninterpretedRes(Region *r, const char *typeName, void *ioStruct, bytesBuf_t *ioBuf)
Definition: restructs.cpp:183
rError_t
Definition: rodsError.h:24
cpEnv2
void cpEnv2(Env *env, Region *oldr, Region *newr)
Definition: utils.cpp:479
cpRes2
#define cpRes2(p, oldr, r)
Definition: utils.hpp:50
T_IRODS
@ T_IRODS
Definition: restructs.hpp:172
SAVE_REI
#define SAVE_REI
Definition: rodsDef.h:104
newErrorRes
Res * newErrorRes(Region *r, int errcode)
Definition: restructs.cpp:259
N_ACTIONS
@ N_ACTIONS
Definition: restructs.hpp:134
setVarValue
int setVarValue(char *varMap, ruleExecInfo_t *rei, Res *newVarValue)
Definition: reVariableMap.cpp:176
TK_TEXT
@ TK_TEXT
Definition: restructs.hpp:114
availableRules
int availableRules()
Definition: configuration.cpp:603
N_EXTERN_DEF
@ N_EXTERN_DEF
Definition: restructs.hpp:152
N_APP_FUNC
#define N_APP_FUNC(x)
Definition: restructs.hpp:43
node::subtrees
struct node ** subtrees
Definition: restructs.hpp:254
LOG_DEBUG
#define LOG_DEBUG
Definition: rodsLog.h:23
RULE_NAME
#define RULE_NAME(r)
Definition: restructs.hpp:46
Cache::coreFuncDescIndex
Env * coreFuncDescIndex
Definition: configuration.hpp:57
N_FD_EXTERNAL
@ N_FD_EXTERNAL
Definition: restructs.hpp:146
N_ACTIONS_RECOVERY
@ N_ACTIONS_RECOVERY
Definition: restructs.hpp:135
typeFuncParam
int typeFuncParam(Node *param, Node *paramType, Node *formalParamType, Hashtable *var_type_table, List *typingConstraints, rError_t *errmsg, Region *r)
Definition: typing.cpp:987
newDoubleRes
Res * newDoubleRes(Region *r, double a)
Definition: restructs.cpp:210
clearMsParam
int clearMsParam(msParam_t *msParam, int freeStruct)
Definition: msParam.cpp:468
condIndexVal::params
Node * params
Definition: restructs.hpp:208
RULE_FAILED_ERR
@ RULE_FAILED_ERR
Definition: rodsErrorTable.h:675
RE_TYPE_ERROR
@ RE_TYPE_ERROR
Definition: rodsErrorTable.h:720
HTML_TEST_1
#define HTML_TEST_1
Definition: reDefines.h:32
rules.hpp
typeEqSyntatic
int typeEqSyntatic(ExprType *a, ExprType *b)
Definition: utils.cpp:18
evaluateExpression3
Res * evaluateExpression3(Node *expr, int applyAll, int force, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:50
T_DATETIME
@ T_DATETIME
Definition: restructs.hpp:162
node::degree
int degree
Definition: restructs.hpp:246
execRuleNodeRes
Res * execRuleNodeRes(Node *rule, Res **args, unsigned int argc, int applyAll, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:1416
updateInEnv
void updateInEnv(Env *env, char *varname, Res *res)
Definition: utils.cpp:821
isVariableNode
int isVariableNode(Node *node)
Definition: parser.cpp:98
applyRuleArg
int applyRuleArg(const char *action, const char *args[20], int argc, ruleExecInfo_t *rei, int reiSaveFlag)
Definition: irods_re_structs.cpp:95
NO_MORE_RULES_ERR
@ NO_MORE_RULES_ERR
Definition: rodsErrorTable.h:594
newPathRes
Res * newPathRes(Region *r, const char *s)
Definition: restructs.cpp:241
T_STRING
@ T_STRING
Definition: restructs.hpp:161
MAX_NAME_LEN
#define MAX_NAME_LEN
Definition: rodsDef.h:61
irods::ms_table_entry::num_args
unsigned int num_args()
Definition: irods_ms_plugin.hpp:118
NODE_EXPR_POS
#define NODE_EXPR_POS(x)
Definition: restructs.hpp:68
MAX_NUM_OF_ARGS_IN_ACTION
#define MAX_NUM_OF_ARGS_IN_ACTION
Definition: irods_re_structs.hpp:13
globalEnv
Env * globalEnv(Env *env)
Definition: utils.cpp:754
NULL_VALUE_ERR
@ NULL_VALUE_ERR
Definition: rodsErrorTable.h:669
cpRes
#define cpRes(p, r)
Definition: utils.hpp:48
getVarMap
int getVarMap(char *action, char *varName, char **varMap, int index)
Definition: reVariableMap.cpp:77
newSimpType
ExprType * newSimpType(NodeType t, Region *r)
Definition: restructs.cpp:70
EXEC_RULE_BEGIN
@ EXEC_RULE_BEGIN
Definition: restructs.hpp:302
insertIntoHashTable
int insertIntoHashTable(Hashtable *h, const char *key, const void *value)
Definition: hashtable.cpp:99
ruleIndexListNode
Definition: restructs.hpp:213
evaluateFunction3
Res * evaluateFunction3(Node *appRes, int applyAll, Node *node, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:580
addRErrorMsg
int addRErrorMsg(rError_t *myError, int status, const char *msg)
Definition: rcMisc.cpp:121
newFuncSymLink
FunctionDesc * newFuncSymLink(char *fn, int nArgs, Region *r)
Definition: restructs.cpp:128
N_FD_CONSTRUCTOR
@ N_FD_CONSTRUCTOR
Definition: restructs.hpp:144
RETURN
#define RETURN(status)
Definition: microservice.hpp:351
get_irods_version.value
dictionary value
Definition: get_irods_version.py:27
RES_FUNC_N_ARGS
#define RES_FUNC_N_ARGS(x)
Definition: restructs.hpp:51
RE_UNSUPPORTED_AST_NODE_TYPE
@ RE_UNSUPPORTED_AST_NODE_TYPE
Definition: rodsErrorTable.h:717
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
TK_DOUBLE
@ TK_DOUBLE
Definition: restructs.hpp:113
newDatetimeRes
Res * newDatetimeRes(Region *r, long dt)
Definition: restructs.cpp:253
execRule
Res * execRule(char *ruleNameInp, Res **args, unsigned int argc, int applyAllRuleInp, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:1242
MsParam
Definition: msParam.h:76
N_FD_FUNCTION
@ N_FD_FUNCTION
Definition: restructs.hpp:143
ruleEngineEventParam::ruleIndex
int ruleIndex
Definition: restructs.hpp:318
node::coercionType
ExprType * coercionType
Definition: restructs.hpp:251
debug.hpp
RETRY_WITHOUT_RECOVERY_ERR
@ RETRY_WITHOUT_RECOVERY_ERR
Definition: rodsErrorTable.h:662
LOG_NOTICE
#define LOG_NOTICE
Definition: rodsLog.h:33
lookupFromHashTable
const void * lookupFromHashTable(Hashtable *h, const char *key)
Definition: hashtable.cpp:222
node::base
char * base
Definition: restructs.hpp:255
actionTableLookUp
int actionTableLookUp(irods::ms_table_entry &, char *action)
Definition: irods_re_structs.cpp:34
FD_SMSI_FUNC_PTR
#define FD_SMSI_FUNC_PTR(x)
Definition: restructs.hpp:63
T_FIXD
@ T_FIXD
Definition: restructs.hpp:165
cpEnv
void cpEnv(Env *env, Region *r)
Definition: utils.cpp:396
region
Definition: region.h:45
T_BOOL
@ T_BOOL
Definition: restructs.hpp:163
irods::error
Definition: irods_error.hpp:23
CUT_ACTION_PROCESSED_ERR
@ CUT_ACTION_PROCESSED_ERR
Definition: rodsErrorTable.h:663
RES_UNINTER_STRUCT
#define RES_UNINTER_STRUCT(x)
Definition: restructs.hpp:65
int
typedef int((*funcPtr)())
RES_INT_VAL
#define RES_INT_VAL(x)
Definition: restructs.hpp:58
irods::ms_table_entry
Definition: irods_ms_plugin.hpp:28
arithmetics.hpp
RE_UNABLE_TO_READ_VAR
@ RE_UNABLE_TO_READ_VAR
Definition: rodsErrorTable.h:709
FD_PROJ
#define FD_PROJ(x)
Definition: restructs.hpp:48
RuleDesc
Definition: restructs.hpp:272
N_VAL
@ N_VAL
Definition: restructs.hpp:126
newList
List * newList(Region *r)
Definition: list.cpp:6
newEnv
Env * newEnv(Hashtable *current, Env *previous, Env *lower, Region *r)
Definition: restructs.cpp:281
node::exprType
ExprType * exprType
Definition: restructs.hpp:250
findNextRule2
int findNextRule2(const char *action, int i, RuleIndexListNode **node)
Definition: index.cpp:322
N_TUPLE
@ N_TUPLE
Definition: restructs.hpp:127
newBoolRes
Res * newBoolRes(Region *r, int n)
Definition: restructs.cpp:216
condIndexVal
Definition: restructs.hpp:207
execMicroService3
Res * execMicroService3(char *msName, Res **args, unsigned int nargs, Node *node, Env *env, ruleExecInfo_t *rei, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:1030
matchPattern
Res * matchPattern(Node *pattern, Node *val, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:1516
newRes
Res * newRes(Region *r)
Definition: restructs.cpp:176
evaluateActions
Res * evaluateActions(Node *expr, Node *reco, int applyAll, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:473
RES_DOUBLE_VAL_LVAL
#define RES_DOUBLE_VAL_LVAL(x)
Definition: restructs.hpp:54
updateInHashTable
const void * updateInHashTable(Hashtable *h, const char *key, const void *value)
Definition: hashtable.cpp:164
KeyValPair_MS_T
#define KeyValPair_MS_T
Definition: msParam.h:37
reVariableMap.gen.hpp
irods.six.b
def b(s)
Definition: six.py:606
T_VAR
@ T_VAR
Definition: restructs.hpp:171
execAction3
Res * execAction3(char *actionName, Res **args, unsigned int nargs, int applyAllRule, Node *node, Env *env, ruleExecInfo_t *rei, int reiSaveFlag, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:950
irods::ms_table_entry::call
int call(ruleExecInfo_t *, std::vector< msParam_t * > &)
Definition: irods_ms_plugin.cpp:60
error
int error
Definition: filesystem.cpp:101
ruleIndexListNode::condIndex
CondIndexVal * condIndex
Definition: restructs.hpp:217
findNextRuleFromIndex
int findNextRuleFromIndex(Env *ruleIndex, const char *action, int i, RuleIndexListNode **node)
Definition: index.cpp:290
RuleDesc::node
Node * node
Definition: restructs.hpp:275
RuleExecInfo
Definition: irods_re_structs.hpp:18
T_VAR_NUM_DISJUNCTS
#define T_VAR_NUM_DISJUNCTS(x)
Definition: restructs.hpp:37
T_INT
@ T_INT
Definition: restructs.hpp:160
Cache::extFuncDescIndex
Env * extFuncDescIndex
Definition: configuration.hpp:59
N_ERROR
@ N_ERROR
Definition: restructs.hpp:111
rodsLogError
void rodsLogError(int level, int errCode, char *formatStr,...)
Definition: rodsLog.cpp:422
T_TUPLE
@ T_TUPLE
Definition: restructs.hpp:166
getSessionVar
Res * getSessionVar(char *action, Node *node, char *varName, ruleExecInfo_t *rei, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:914
generateErrMsg
char * generateErrMsg(char *msg, long errloc, char *ruleBaseName, char errbuf[1024])
Definition: parser.cpp:3555
env::current
Hashtable * current
Definition: restructs.hpp:227
TK_STRING
@ TK_STRING
Definition: restructs.hpp:115
RE_UNABLE_TO_WRITE_LOCAL_VAR
@ RE_UNABLE_TO_WRITE_LOCAL_VAR
Definition: rodsErrorTable.h:704
region_free
void region_free(Region *r)
Definition: region.cpp:146
ruleEngineEventParam
Definition: restructs.hpp:317
GOT_RULE
@ GOT_RULE
Definition: restructs.hpp:308
getVarValue
int getVarValue(char *varMap, ruleExecInfo_t *rei, Res **varValue, Region *r)
Definition: reVariableMap.cpp:155
T_DYNAMIC
@ T_DYNAMIC
Definition: restructs.hpp:158
RE_UNABLE_TO_READ_LOCAL_VAR
@ RE_UNABLE_TO_READ_LOCAL_VAR
Definition: rodsErrorTable.h:705
construct
Node * construct(char *fn, Node **args, int argc, Node *constype, Region *r)
Definition: functions.cpp:2508
newUnspecifiedRes
Res * newUnspecifiedRes(Region *r)
Definition: restructs.cpp:247
replErrorStack
int replErrorStack(rError_t *srcRError, rError_t *destRError)
Definition: rcMisc.cpp:152
ruleEngineConfig
Cache ruleEngineConfig
Definition: configuration.cpp:68
reVariableMap.hpp
condIndexVal::valIndex
Hashtable * valIndex
Definition: restructs.hpp:210
newTupleRes
Res * newTupleRes(int arity, Res **compTypes, Region *r)
Definition: restructs.cpp:148
hashtable
Definition: irods_hashtable.h:16
rodsErrorTable.h
EXEC_RULE_END
@ EXEC_RULE_END
Definition: restructs.hpp:305
writeToTmp
int writeToTmp(char *fileName, char *text)
Definition: utils.cpp:681
instantiate
ExprType * instantiate(ExprType *type, Hashtable *type_table, int replaceFreeVars, Region *r)
Definition: utils.cpp:642
RES_ERR_CODE
#define RES_ERR_CODE(x)
Definition: restructs.hpp:50
reTestFlag
int reTestFlag
Definition: libirods_rule_engine_plugin-irods_rule_language.cpp:55
RE_UNABLE_TO_READ_SESSION_VAR
@ RE_UNABLE_TO_READ_SESSION_VAR
Definition: rodsErrorTable.h:707
SYSTEM_SPACE_RULE
#define SYSTEM_SPACE_RULE
Definition: restructs.hpp:92
RES_INT_VAL_LVAL
#define RES_INT_VAL_LVAL(x)
Definition: restructs.hpp:55
KeyValPair
Definition: objInfo.h:120
reFuncDefs.hpp
irods::error::ok
bool ok()
Definition: irods_error.cpp:258
N_APP_ARG
#define N_APP_ARG(x, n)
Definition: restructs.hpp:42
newStringRes
Res * newStringRes(Region *r, const char *s)
Definition: restructs.cpp:235
buf
static char buf[64+50+1]
Definition: rsAuthRequest.cpp:21
type
int type
Definition: filesystem.cpp:103
T_VAR_ID
#define T_VAR_ID(x)
Definition: restructs.hpp:34
RES_BOOL_VAL
#define RES_BOOL_VAL(x)
Definition: restructs.hpp:59
T_SUCCESS
@ T_SUCCESS
Definition: restructs.hpp:170
ERR_MSG_SEP
#define ERR_MSG_SEP
Definition: reconstants.hpp:21
irods::re_plugin_globals
std::unique_ptr< struct irods::global_re_plugin_mgr > re_plugin_globals
Definition: irods_re_plugin.cpp:16
list
Definition: irods_list.h:13
freeRErrorContent
int freeRErrorContent(rError_t *myError)
Definition: rcMisc.cpp:182
getIOType
#define getIOType(n)
Definition: restructs.hpp:89
isIterable
ExprType * isIterable(ExprType *type, Hashtable *var_type_table, Region *r)
Definition: typing.cpp:762
setVariableValue
Res * setVariableValue(char *varName, Res *val, Node *node, ruleExecInfo_t *rei, Env *env, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:1672
T_FLEX
@ T_FLEX
Definition: restructs.hpp:164
ERR_MSG_LEN
#define ERR_MSG_LEN
Definition: rodsError.h:16
convertMsParamToRes
int convertMsParamToRes(msParam_t *mP, Res *res, Region *r)
Definition: conversion.cpp:142
evaluateFunctionApplication
Res * evaluateFunctionApplication(Node *func, Node *arg, int applyAll, Node *node, ruleExecInfo_t *rei, int reiSaveFlag, Env *env, rError_t *errmsg, Region *r)
Definition: arithmetics.cpp:553
EXEC_ACTION_BEGIN
@ EXEC_ACTION_BEGIN
Definition: restructs.hpp:303
RES_BOOL_VAL_LVAL
#define RES_BOOL_VAL_LVAL(x)
Definition: restructs.hpp:56
getTVarName
char * getTVarName(int vid, char name[128])
Definition: utils.cpp:298
RK_REL
@ RK_REL
Definition: restructs.hpp:264