Fawkes API  Fawkes Development Version
feature_redefine_warning.cpp
1 
2 /***************************************************************************
3  * feature_redefine_warning.cpp - CLIPS warning on redefinitions
4  *
5  * Created: Tue Jan 21 20:31:17 2014
6  * Copyright 2006-2014 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "feature_redefine_warning.h"
24 #include <logging/logger.h>
25 
26 extern "C" {
27 #include <clips/clips.h>
28 }
29 #include <clipsmm.h>
30 
31 #define ROUTER_NAME "clips-feature-redefine-warn"
32 
33 using namespace fawkes;
34 
35 
36 /// @cond INTERNALS
37 class CLIPSRedefineWarningLogger
38 {
39  public:
40  CLIPSRedefineWarningLogger(Logger *logger, const char *component = NULL)
41  {
42  logger_ = logger;
43  if (component) {
44  component_ = strdup(component);
45  } else {
46  component_ = NULL;
47  }
48  warn_filter_ = "[CSTRCPSR1] WARNING: ";
49  }
50 
51  ~CLIPSRedefineWarningLogger()
52  {
53  if (component_) {
54  free(component_);
55  }
56  }
57 
58  bool buffer_warning(const char *str, std::string &buffer_string)
59  {
60  if (strcmp(str, "\n") == 0) {
61  if (warn_buffer_ == warn_filter_) {
62  warn_buffer_.clear();
63  return false;
64  } else {
65  buffer_string = warn_buffer_;
66  warn_buffer_.clear();
67  return true;
68  }
69  } else {
70  warn_buffer_ += str;
71  if (warn_filter_.find(warn_buffer_) == std::string::npos) {
72  warn_buffer_.clear();
73  buffer_string = str;
74  return true;
75  } else {
76  return false;
77  }
78  }
79  }
80 
81  void log(const char *str)
82  {
83  if (strcmp(str, "\n") == 0) {
84  if (buffer_.find("Redefining ") == 0) {
85  logger_->log_error(component_ ? component_ : "CLIPS", "%s", buffer_.c_str());
86  }
87 
88  buffer_.clear();
89  } else {
90  buffer_ += str;
91  }
92  }
93 
94  private:
95  Logger *logger_;
96  char *component_;
97  std::string buffer_;
98  std::string warn_buffer_;
99  std::string warn_filter_;
100 };
101 
102 static int
103 redefine_warning_router_query(void *env, char *logical_name)
104 {
105  if (strcmp(logical_name, WDIALOG) == 0) return TRUE;
106  if (strcmp(logical_name, WWARNING) == 0) return TRUE;
107  return FALSE;
108 }
109 
110 static int
111 redefine_warning_router_print(void *env, char *logical_name, char *str)
112 {
113  void *rc = GetEnvironmentRouterContext(env);
114  CLIPSRedefineWarningLogger *logger = static_cast<CLIPSRedefineWarningLogger *>(rc);
115 
116  if (strcmp(logical_name, WWARNING) == 0) {
117  // check if it's the ill-guided output of PrintWarningID from prntutil.c
118  std::string wbuffer;
119  ;
120  if (logger->buffer_warning(str, wbuffer)) {
121  // not the warning we were looking for, forward
122  EnvDeactivateRouter(env, (char *)ROUTER_NAME);
123  EnvPrintRouter(env, logical_name, (char *)wbuffer.c_str());
124  if (strcmp(str, "\n") == 0 && wbuffer != "") {
125  EnvPrintRouter(env, logical_name, str);
126  }
127  EnvActivateRouter(env, (char *)ROUTER_NAME);
128  }
129  } else {
130  logger->log(str);
131  }
132 
133  return TRUE;
134 }
135 
136 static int
137 redefine_warning_router_exit(void *env, int exit_code)
138 {
139  return TRUE;
140 }
141 
142 /// @endcond
143 
144 
145 /** @class RedefineWarningCLIPSFeature "feature_redefine_warning.h"
146  * CLIPS warning on redefinition of names.
147  * @author Tim Niemueller
148  */
149 
150 /** Constructor.
151  * @param logger message logger
152  */
154 : CLIPSFeature("redefine-warning"), logger_(logger)
155 {
156 }
157 
158 
159 /** Destructor. */
161 {
162 }
163 
164 
165 void
168 {
169  envs_[env_name] = clips;
170 
171  std::string name = "RWCLIPS|" + env_name;
172 
173  CLIPSRedefineWarningLogger *cl = new CLIPSRedefineWarningLogger(logger_, name.c_str());
174 
175  EnvAddRouterWithContext(clips->cobj(), (char *)ROUTER_NAME,
176  /* exclusive */ 40,
177  redefine_warning_router_query,
178  redefine_warning_router_print,
179  /* getc */ NULL,
180  /* ungetc */ NULL,
181  redefine_warning_router_exit,
182  cl);
183  clips->watch("compilations");
184 
185 }
186 
187 void
189 {
190  std::string name = "RWCLIPS|" + env_name;
191  if (envs_.find(env_name) == envs_.end()) {
192  logger_->log_warn(name.c_str(), "Environment %s has not been registered "
193  "for redefine warning feature", env_name.c_str());
194  return;
195  }
196 
197  fawkes::LockPtr<CLIPS::Environment> &clips = envs_[env_name];
198 
199  CLIPSRedefineWarningLogger *logger = NULL;
200 
201  struct routerData *rd = RouterData(clips->cobj());
202  struct router *r = rd->ListOfRouters;
203  while (r != NULL) {
204  if (strcmp(r->name, ROUTER_NAME) == 0) {
205  logger = static_cast<CLIPSRedefineWarningLogger *>(r->context);
206  break;
207  }
208  r = r->next;
209  }
210 
211  EnvDeleteRouter(clips->cobj(), (char *)ROUTER_NAME);
212  delete logger;
213 
214  envs_.erase(env_name);
215 }
Fawkes library namespace.
virtual ~RedefineWarningCLIPSFeature()
Destructor.
RedefineWarningCLIPSFeature(fawkes::Logger *logger)
Constructor.
CLIPS feature maintainer.
Definition: clips_feature.h:41
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void clips_context_init(const std::string &env_name, fawkes::LockPtr< CLIPS::Environment > &clips)
Initialize a CLIPS context to use the provided feature.
virtual void clips_context_destroyed(const std::string &env_name)
Notification that a CLIPS environment has been destroyed.
Interface for logging.
Definition: logger.h:34