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 
25 #include <logging/logger.h>
26 
27 extern "C" {
28 #include <clips/clips.h>
29 }
30 #include <clipsmm.h>
31 
32 #define ROUTER_NAME "clips-feature-redefine-warn"
33 
34 using namespace fawkes;
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
59  buffer_warning(const char *str, std::string &buffer_string)
60  {
61  if (strcmp(str, "\n") == 0) {
62  if (warn_buffer_ == warn_filter_) {
63  warn_buffer_.clear();
64  return false;
65  } else {
66  buffer_string = warn_buffer_;
67  warn_buffer_.clear();
68  return true;
69  }
70  } else {
71  warn_buffer_ += str;
72  if (warn_filter_.find(warn_buffer_) == std::string::npos) {
73  warn_buffer_.clear();
74  buffer_string = str;
75  return true;
76  } else {
77  return false;
78  }
79  }
80  }
81 
82  void
83  log(const char *str)
84  {
85  if (strcmp(str, "\n") == 0) {
86  if (buffer_.compare(0, 11, "Redefining ") == 0) {
87  logger_->log_error(component_ ? component_ : "CLIPS", "%s", buffer_.c_str());
88  }
89 
90  buffer_.clear();
91  } else {
92  buffer_ += str;
93  }
94  }
95 
96 private:
97  Logger * logger_;
98  char * component_;
99  std::string buffer_;
100  std::string warn_buffer_;
101  std::string warn_filter_;
102 };
103 
104 static int
105 redefine_warning_router_query(void *env, char *logical_name)
106 {
107  if (strcmp(logical_name, WDIALOG) == 0)
108  return TRUE;
109  if (strcmp(logical_name, WWARNING) == 0)
110  return TRUE;
111  return FALSE;
112 }
113 
114 static int
115 redefine_warning_router_print(void *env, char *logical_name, char *str)
116 {
117  void * rc = GetEnvironmentRouterContext(env);
118  CLIPSRedefineWarningLogger *logger = static_cast<CLIPSRedefineWarningLogger *>(rc);
119 
120  if (strcmp(logical_name, WWARNING) == 0) {
121  // check if it's the ill-guided output of PrintWarningID from prntutil.c
122  std::string wbuffer;
123  ;
124  if (logger->buffer_warning(str, wbuffer)) {
125  // not the warning we were looking for, forward
126  EnvDeactivateRouter(env, (char *)ROUTER_NAME);
127  EnvPrintRouter(env, logical_name, (char *)wbuffer.c_str());
128  if (strcmp(str, "\n") == 0 && wbuffer != "") {
129  EnvPrintRouter(env, logical_name, str);
130  }
131  EnvActivateRouter(env, (char *)ROUTER_NAME);
132  }
133  } else {
134  logger->log(str);
135  }
136 
137  return TRUE;
138 }
139 
140 static int
141 redefine_warning_router_exit(void *env, int exit_code)
142 {
143  return TRUE;
144 }
145 
146 /// @endcond
147 
148 /** @class RedefineWarningCLIPSFeature "feature_redefine_warning.h"
149  * CLIPS warning on redefinition of names.
150  * @author Tim Niemueller
151  */
152 
153 /** Constructor.
154  * @param logger message logger
155  */
157 : CLIPSFeature("redefine-warning"), logger_(logger)
158 {
159 }
160 
161 /** Destructor. */
163 {
164 }
165 
166 void
169 {
170  envs_[env_name] = clips;
171 
172  std::string name = "RWCLIPS|" + env_name;
173 
174  CLIPSRedefineWarningLogger *cl = new CLIPSRedefineWarningLogger(logger_, name.c_str());
175 
176  EnvAddRouterWithContext(clips->cobj(),
177  (char *)ROUTER_NAME,
178  /* exclusive */ 40,
179  redefine_warning_router_query,
180  redefine_warning_router_print,
181  /* getc */ NULL,
182  /* ungetc */ NULL,
183  redefine_warning_router_exit,
184  cl);
185  clips->watch("compilations");
186 }
187 
188 void
190 {
191  std::string name = "RWCLIPS|" + env_name;
192  if (envs_.find(env_name) == envs_.end()) {
193  logger_->log_warn(name.c_str(),
194  "Environment %s has not been registered "
195  "for redefine warning feature",
196  env_name.c_str());
197  return;
198  }
199 
200  fawkes::LockPtr<CLIPS::Environment> &clips = envs_[env_name];
201 
202  CLIPSRedefineWarningLogger *logger = NULL;
203 
204  struct routerData *rd = RouterData(clips->cobj());
205  struct router * r = rd->ListOfRouters;
206  while (r != NULL) {
207  if (strcmp(r->name, ROUTER_NAME) == 0) {
208  logger = static_cast<CLIPSRedefineWarningLogger *>(r->context);
209  break;
210  }
211  r = r->next;
212  }
213 
214  EnvDeleteRouter(clips->cobj(), (char *)ROUTER_NAME);
215  delete logger;
216 
217  envs_.erase(env_name);
218 }
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 ~RedefineWarningCLIPSFeature()
Destructor.
RedefineWarningCLIPSFeature(fawkes::Logger *logger)
Constructor.
virtual void clips_context_destroyed(const std::string &env_name)
Notification that a CLIPS environment has been destroyed.
CLIPS feature maintainer.
Definition: clips_feature.h:42
Interface for logging.
Definition: logger.h:42
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log(LogLevel level, const char *component, const char *format,...)
Log message of given log level.
Definition: multi.cpp:153
Fawkes library namespace.