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 <algorithm>
26 #include <cstdio>
27 #include <cstring>
28 #include <string>
29 #include <unistd.h>
30 
31 // clang-format off
32 #include <opaque-pub.h>
33 #include <action_f-pub.h>
34 #include <constant-pub.h>
35 #include <ev-function_f-pub.h>
36 #include <ev-predicate_f-pub.h>
37 #include <intention_f-pub.h>
38 #include <macro-pub.h>
39 #include <oprs-type-pub.h>
40 #include <oprs-type_f-pub.h>
41 #include <shashPack_f.h>
42 #include <slistPack-pub.h>
43 #include <user-end-hook_f-pub.h>
44 // clang-format on
45 
46 /// @cond EXTERNAL
47 extern "C" {
48 typedef Slist *List_Envar;
49 List_Envar global_var_list;
50 Shash * id_hash;
51 
52 typedef struct type Type;
53 typedef Slist * TypeList;
54 typedef Slist * SymList;
55 Symbol wait_sym;
56 
57 /* type de Variable */
58 typedef enum { LOGICAL_VARIABLE, PROGRAM_VARIABLE } Variable_Type;
59 
60 struct envar
61 { /* Un envar */
62  Symbol name; /* son name */
63  Term * value; /* le term sur lequel elle pointe */
64  Type * unif_type;
65  Variable_Type type BITFIELDS( : 8); /* Le type de la variable */
66 };
67 
68 struct type
69 {
70  Symbol name;
71  Type * father;
72  TypeList sur_types; /* Plus itself */
73  SymList elts;
74 };
75 }
76 /// @endcond
77 
78 /** Get Fawkes host and port.
79  * This goes through the list of global variables and extracts the
80  * parent Fawkes hostname from @@FAWKES_HOST and the TCP port from
81  * @@FAWKES_PORT.
82  * @return true if the data could be gathered successfully, false otherwise
83  */
84 bool
85 get_fawkes_host_port(std::string &fawkes_host, unsigned short &fawkes_port)
86 {
87  Envar *env;
88  sl_loop_through_slist(global_var_list, env, Envar *)
89  {
90  if (strcmp(env->name, "@@FAWKES_HOST") == 0 || strcmp(env->name, "@@fawkes_host") == 0) {
91  if (env->value->type != STRING) {
92  fprintf(stderr, "Error: @@FAWKES_HOST is not of type STRING\n");
93  return false;
94  }
95  fawkes_host = env->value->u.string;
96  } else if (strcmp(env->name, "@@FAWKES_PORT") == 0 || strcmp(env->name, "@@fawkes_port") == 0) {
97  if (env->value->type != STRING) {
98  fprintf(stderr, "Error: @@FAWKES_PORT is not of type STRING\n");
99  return false;
100  }
101  fawkes_port = atoi(env->value->u.string);
102  }
103  }
104 
105  if (fawkes_host.empty()) {
106  fawkes_host = getenv("FAWKES_HOST");
107  }
108  if (fawkes_port == 0) {
109  fawkes_port = atoi(getenv("FAWKES_PORT"));
110  }
111 
112  return (!fawkes_host.empty() && fawkes_port != 0);
113 }
114 
115 //define ACTION_DEBUG
116 
117 #ifdef ACTION_DEBUG
118 # define ACTION_RETURN(value) \
119  do { \
120  if (value == nil_sym || value == lisp_t_sym) { \
121  printf("Action returns: %s\n", \
122  value == nil_sym ? "FAIL" : (value == wait_sym ? ":WAIT" : "FINAL")); \
123  } \
124  Term *res = MAKE_OBJECT(Term); \
125  res->type = ATOM; \
126  res->u.id = value; \
127  return res; \
128  } while (0);
129 #else
130 # define ACTION_RETURN(value) \
131  do { \
132  Term *res = MAKE_OBJECT(Term); \
133  res->type = ATOM; \
134  res->u.id = value; \
135  return res; \
136  } while (0);
137 #endif
138 #define ACTION_FAIL() ACTION_RETURN(nil_sym);
139 #define ACTION_WAIT() ACTION_RETURN(wait_sym);
140 #define ACTION_FINAL() ACTION_RETURN(lisp_t_sym);
141 
142 bool
143 assert_arg_type(const char *func_name, TermList &tl, int index, Term_Type t_type)
144 {
145  Term *t = (Term *)get_list_pos(tl, index);
146  if (t->type != t_type) {
147  const char *type = "UNKNOWN";
148  switch (t_type) {
149  case INTEGER: type = "INTEGER"; break;
150  case LONG_LONG: type = "LONG_LONG"; break;
151  case TT_FLOAT: type = "TT_FLOAT"; break;
152  case STRING: type = "STRING"; break;
153  case TT_ATOM: type = "TT_ATOM"; break;
154  case EXPRESSION: type = "EXPRESSION"; break;
155  case VARIABLE: type = "VARIABLE"; break;
156  case LISP_LIST: type = "LISP_LIST"; break;
157  case INT_ARRAY: type = "INT_ARRAY"; break;
158  case FLOAT_ARRAY: type = "FLOAT_ARRAY"; break;
159  case C_LIST: type = "C_LIST"; break;
160  case TT_FACT: type = "TT_FACT"; break;
161  case TT_GOAL: type = "FF_GOAL"; break;
162  case TT_INTENTION: type = "TT_INTENTION"; break;
163  case TT_OP_INSTANCE: type = "TT_OP_INSTANCE"; break;
164  case U_POINTER: type = "U_POINTER"; break;
165  case U_MEMORY: type = "U_MEMORY"; break;
166  }
167  fprintf(stderr, "Error[%s]: argument type is not a %s\n", func_name, type);
168  return false;
169  } else {
170  return true;
171  }
172 }
173 
174 #define ACTION_ASSERT_ARG_LENGTH(func_name, tl, length) \
175  do { \
176  int terms_len = sl_slist_length(tl); \
177  if (terms_len != length) { \
178  fprintf(stderr, \
179  "Error[%s]: invalid number of arguments:" \
180  " req %i, got %i\n", \
181  func_name, \
182  length, \
183  terms_len); \
184  ACTION_FAIL(); \
185  } \
186  } while (0);
187 
188 #define ACTION_SET_AND_ASSERT_ARG_TYPE(func_name, var, tl, index, t_type) \
189  do { \
190  if (!assert_arg_type(func_name, tl, index, t_type)) \
191  ACTION_FAIL(); \
192  var = (Term *)get_list_pos(tl, index); \
193  } while (0);
194 
195 // Boolean return versions
196 #define ACTION_ASSERT_B_ARG_LENGTH(func_name, tl, length) \
197  do { \
198  int terms_len = sl_slist_length(tl); \
199  if (terms_len != length) { \
200  fprintf(stderr, \
201  "Error[%s]: invalid number of arguments:" \
202  " req %i, got %i\n", \
203  func_name, \
204  length, \
205  terms_len); \
206  return false; \
207  } \
208  } while (0);
209 
210 #define ACTION_SET_AND_ASSERT_B_ARG_TYPE(func_name, var, tl, index, t_type) \
211  do { \
212  if (!assert_arg_type(func_name, tl, index, t_type)) \
213  return false; \
214  var = (Term *)get_list_pos(tl, index); \
215  } while (0);
216 
217 #define ACTION_ASSERT_B_ARG_TYPE(func_name, var, tl, index, t_type) \
218  do { \
219  if (!assert_arg_type(func_name, tl, index, t_type)) \
220  return false; \
221  } while (0);
222 
223 #endif