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
27extern "C" {
28#include <clips/clips.h>
29}
30#include <clipsmm.h>
31
32#define ROUTER_NAME "clips-feature-redefine-warn"
33
34using namespace fawkes;
35
36/// @cond INTERNALS
37class CLIPSRedefineWarningLogger
38{
39public:
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
96private:
97 Logger * logger_;
98 char * component_;
99 std::string buffer_;
100 std::string warn_buffer_;
101 std::string warn_filter_;
102};
103
104static int
105redefine_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
114static int
115redefine_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
140static int
141redefine_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
166void
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
188void
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.