Fawkes API  Fawkes Development Version
mod_utils.h
1 
2 /***************************************************************************
3  * mod_utils.cpp - OpenPRS module utils
4  *
5  * Created: Tue Aug 26 17:33:01 2014
6  * Copyright 2014 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Library General Public License for more details.
18  *
19  * Read the full text in the LICENSE.GPL file in the doc directory.
20  */
21 
22 #ifndef __PLUGINS_OPENPRS_AGENT_MOD_UTILS_H_
23 #define __PLUGINS_OPENPRS_AGENT_MOD_UTILS_H_
24 
25 #include <cstdio>
26 
27 #include <constant-pub.h>
28 #include <opaque-pub.h>
29 #include <oprs-type-pub.h>
30 #include <oprs-type_f-pub.h>
31 #include <macro-pub.h>
32 #include <slistPack-pub.h>
33 #include <shashPack_f.h>
34 #include <user-end-hook_f-pub.h>
35 #include <action_f-pub.h>
36 #include <intention_f-pub.h>
37 #include <ev-function_f-pub.h>
38 #include <ev-predicate_f-pub.h>
39 
40 #include <string>
41 #include <algorithm>
42 #include <cstring>
43 #include <unistd.h>
44 
45 /// @cond EXTERNAL
46 extern "C" {
47  typedef Slist *List_Envar;
48  List_Envar global_var_list;
49  Shash *id_hash;
50 
51  typedef struct type Type;
52  typedef Slist *TypeList;
53  typedef Slist *SymList;
54  Symbol wait_sym;
55 
56  /* type de Variable */
57  typedef enum {LOGICAL_VARIABLE, PROGRAM_VARIABLE} Variable_Type;
58 
59  struct envar { /* Un envar */
60  Symbol name; /* son name */
61  Term *value; /* le term sur lequel elle pointe */
62  Type *unif_type;
63  Variable_Type type BITFIELDS(:8); /* Le type de la variable */
64  };
65 
66  struct type {
67  Symbol name;
68  Type *father;
69  TypeList sur_types; /* Plus itself */
70  SymList elts;
71  };
72 }
73 /// @endcond
74 
75 /** Get Fawkes host and port.
76  * This goes through the list of global variables and extracts the
77  * parent Fawkes hostname from @@FAWKES_HOST and the TCP port from
78  * @@FAWKES_PORT.
79  * @return true if the data could be gathered successfully, false otherwise
80  */
81 bool
82 get_fawkes_host_port(std::string &fawkes_host, unsigned short &fawkes_port)
83 {
84  Envar *env;
85  sl_loop_through_slist(global_var_list, env, Envar *) {
86  if (strcmp(env->name, "@@FAWKES_HOST") == 0 || strcmp(env->name, "@@fawkes_host") == 0) {
87  if (env->value->type != STRING) {
88  fprintf(stderr, "Error: @@FAWKES_HOST is not of type STRING\n");
89  return false;
90  }
91  fawkes_host = env->value->u.string;
92  } else if (strcmp(env->name, "@@FAWKES_PORT") == 0 || strcmp(env->name, "@@fawkes_port") == 0) {
93  if (env->value->type != STRING) {
94  fprintf(stderr, "Error: @@FAWKES_PORT is not of type STRING\n");
95  return false;
96  }
97  fawkes_port = atoi(env->value->u.string);
98  }
99  }
100 
101  if (fawkes_host.empty()) {
102  fawkes_host = getenv("FAWKES_HOST");
103  }
104  if (fawkes_port == 0) {
105  fawkes_port = atoi(getenv("FAWKES_PORT"));
106  }
107 
108  return (! fawkes_host.empty() && fawkes_port != 0);
109 }
110 
111 //define ACTION_DEBUG
112 
113 #ifdef ACTION_DEBUG
114 # define ACTION_RETURN(value) \
115  do { \
116  if (value == nil_sym || value == lisp_t_sym) { \
117  printf("Action returns: %s\n", value == nil_sym ? "FAIL" : (value == wait_sym ? ":WAIT" : "FINAL")); \
118  } \
119  Term *res = MAKE_OBJECT(Term); res->type = ATOM; res->u.id = value; return res; \
120  } while (0);
121 #else
122 # define ACTION_RETURN(value) \
123  do { Term *res = MAKE_OBJECT(Term); res->type = ATOM; res->u.id = value; return res; } while (0);
124 #endif
125 #define ACTION_FAIL() ACTION_RETURN(nil_sym);
126 #define ACTION_WAIT() ACTION_RETURN(wait_sym);
127 #define ACTION_FINAL() ACTION_RETURN(lisp_t_sym);
128 
129 bool
130 assert_arg_type(const char *func_name, TermList &tl, int index, Term_Type t_type)
131 {
132  Term *t = (Term *)get_list_pos(tl, index);
133  if (t->type != t_type) {
134  const char *type = "UNKNOWN";
135  switch (t_type) {
136  case INTEGER: type = "INTEGER"; break;
137  case LONG_LONG: type = "LONG_LONG"; break;
138  case TT_FLOAT: type = "TT_FLOAT"; break;
139  case STRING: type = "STRING"; break;
140  case TT_ATOM: type = "TT_ATOM"; break;
141  case EXPRESSION: type = "EXPRESSION"; break;
142  case VARIABLE: type = "VARIABLE"; break;
143  case LISP_LIST: type = "LISP_LIST"; break;
144  case INT_ARRAY: type = "INT_ARRAY"; break;
145  case FLOAT_ARRAY: type = "FLOAT_ARRAY"; break;
146  case C_LIST: type = "C_LIST"; break;
147  case TT_FACT: type = "TT_FACT"; break;
148  case TT_GOAL: type = "FF_GOAL"; break;
149  case TT_INTENTION: type = "TT_INTENTION"; break;
150  case TT_OP_INSTANCE: type = "TT_OP_INSTANCE"; break;
151  case U_POINTER: type = "U_POINTER"; break;
152  case U_MEMORY: type = "U_MEMORY"; break;
153  }
154  fprintf(stderr, "Error[%s]: argument type is not a %s\n",
155  func_name, type);
156  return false;
157  } else {
158  return true;
159  }
160 }
161 
162 #define ACTION_ASSERT_ARG_LENGTH(func_name, tl, length) \
163  do { \
164  int terms_len = sl_slist_length(tl); \
165  if (terms_len != length) { \
166  fprintf(stderr, "Error[%s]: invalid number of arguments:" \
167  " req %i, got %i\n", func_name, length, terms_len); \
168  ACTION_FAIL(); \
169  } \
170  } while (0);
171 
172 #define ACTION_SET_AND_ASSERT_ARG_TYPE(func_name, var, tl, index, t_type) \
173  do { \
174  if (! assert_arg_type(func_name, tl, index, t_type)) ACTION_FAIL(); \
175  var = (Term *)get_list_pos(tl, index); \
176  } while (0);
177 
178 
179 // Boolean return versions
180 #define ACTION_ASSERT_B_ARG_LENGTH(func_name, tl, length) \
181  do { \
182  int terms_len = sl_slist_length(tl); \
183  if (terms_len != length) { \
184  fprintf(stderr, "Error[%s]: invalid number of arguments:" \
185  " req %i, got %i\n", func_name, length, terms_len); \
186  return false; \
187  } \
188  } while (0);
189 
190 #define ACTION_SET_AND_ASSERT_B_ARG_TYPE(func_name, var, tl, index, t_type) \
191  do { \
192  if (! assert_arg_type(func_name, tl, index, t_type)) return false; \
193  var = (Term *)get_list_pos(tl, index); \
194  } while (0);
195 
196 #define ACTION_ASSERT_B_ARG_TYPE(func_name, var, tl, index, t_type) \
197  do { if (! assert_arg_type(func_name, tl, index, t_type)) return false; } while (0);
198 
199 #endif