1 /*******************************************************/
2 /* "C" Language Integrated Production System */
3 /* */
4 /* CLIPS Version 6.30 08/22/14 */
5 /* */
6 /* WATCH MODULE */
7 /*******************************************************/
8
9
10 /*************************************************************/
11 /* Purpose: Support functions for the watch and unwatch */
12 /* commands. */
13 /* */
14 /* Principal Programmer(s): */
15 /* Gary D. Riley */
16 /* */
17 /* Contributing Programmer(s): */
18 /* Brian Dantes */
19 /* */
20 /* Revision History: */
21 /* */
22 /* 6.23: Changed name of variable log to logName */
23 /* because of Unix compiler warnings of shadowed */
24 /* definitions. */
25 /* */
26 /* 6.24: Renamed BOOLEAN macro type to intBool. */
27 /* */
28 /* Added EnvSetWatchItem function. */
29 /* */
30 /* 6.30: Removed conditional code for unsupported */
31 /* compilers/operating systems (IBM_MCW, */
32 /* MAC_MCW, and IBM_TBC). */
33 /* */
34 /* Added const qualifiers to remove C++ */
35 /* deprecation warnings. */
36 /* */
37 /* Converted API macros to function calls. */
38 /* */
39 /*************************************************************/
40
41 #define _WATCH_SOURCE_
42
43 #include "setup.h"
44
45 #if DEBUGGING_FUNCTIONS
46
47 #include <stdio.h>
48 #define _STDIO_INCLUDED_
49 #include <string.h>
50
51 #include "constant.h"
52 #include "envrnmnt.h"
53 #include "memalloc.h"
54 #include "router.h"
55 #include "argacces.h"
56 #include "extnfunc.h"
57 #include "watch.h"
58
59 /***************************************/
60 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
61 /***************************************/
62
63 static struct watchItem *ValidWatchItem(void *,const char *,int *);
64 static intBool RecognizeWatchRouters(void *,const char *);
65 static int CaptureWatchPrints(void *,const char *,const char *);
66 static void DeallocateWatchData(void *);
67
68 /**********************************************/
69 /* InitializeWatchData: Allocates environment */
70 /* data for watch items. */
71 /**********************************************/
InitializeWatchData(void * theEnv)72 globle void InitializeWatchData(
73 void *theEnv)
74 {
75 AllocateEnvironmentData(theEnv,WATCH_DATA,sizeof(struct watchData),DeallocateWatchData);
76 }
77
78 /************************************************/
79 /* DeallocateWatchData: Deallocates environment */
80 /* data for watch items. */
81 /************************************************/
DeallocateWatchData(void * theEnv)82 static void DeallocateWatchData(
83 void *theEnv)
84 {
85 struct watchItem *tmpPtr, *nextPtr;
86
87 tmpPtr = WatchData(theEnv)->ListOfWatchItems;
88 while (tmpPtr != NULL)
89 {
90 nextPtr = tmpPtr->next;
91 rtn_struct(theEnv,watchItem,tmpPtr);
92 tmpPtr = nextPtr;
93 }
94 }
95
96 /*************************************************************/
97 /* AddWatchItem: Adds an item to the list of watchable items */
98 /* that can be set using the watch and unwatch commands. */
99 /* Returns FALSE if the item is already in the list, */
100 /* otherwise returns TRUE. */
101 /*************************************************************/
AddWatchItem(void * theEnv,const char * name,int code,unsigned * flag,int priority,unsigned (* accessFunc)(void *,int,unsigned,struct expr *),unsigned (* printFunc)(void *,const char *,int,struct expr *))102 globle intBool AddWatchItem(
103 void *theEnv,
104 const char *name,
105 int code,
106 unsigned *flag,
107 int priority,
108 unsigned (*accessFunc)(void *,int,unsigned,struct expr *),
109 unsigned (*printFunc)(void *,const char *,int,struct expr *))
110 {
111 struct watchItem *newPtr, *currentPtr, *lastPtr;
112
113 /*================================================================*/
114 /* Find the insertion point in the watchable items list to place */
115 /* the new item. If the item is already in the list return FALSE. */
116 /*================================================================*/
117
118 for (currentPtr = WatchData(theEnv)->ListOfWatchItems, lastPtr = NULL;
119 currentPtr != NULL;
120 currentPtr = currentPtr->next)
121 {
122 if (strcmp(currentPtr->name,name) == 0) return(FALSE);
123 if (priority < currentPtr->priority) lastPtr = currentPtr;
124 }
125
126 /*============================*/
127 /* Create the new watch item. */
128 /*============================*/
129
130 newPtr = get_struct(theEnv,watchItem);
131 newPtr->name = name;
132 newPtr->flag = flag;
133 newPtr->code = code;
134 newPtr->priority = priority;
135 newPtr->accessFunc = accessFunc;
136 newPtr->printFunc = printFunc;
137
138 /*=================================================*/
139 /* Insert the new item in the list of watch items. */
140 /*=================================================*/
141
142 if (lastPtr == NULL)
143 {
144 newPtr->next = WatchData(theEnv)->ListOfWatchItems;
145 WatchData(theEnv)->ListOfWatchItems = newPtr;
146 }
147 else
148 {
149 newPtr->next = lastPtr->next;
150 lastPtr->next = newPtr;
151 }
152
153 /*==================================================*/
154 /* Return TRUE to indicate the item has been added. */
155 /*==================================================*/
156
157 return(TRUE);
158 }
159
160 /*****************************************************/
161 /* EnvWatch: C access routine for the watch command. */
162 /*****************************************************/
EnvWatch(void * theEnv,const char * itemName)163 globle intBool EnvWatch(
164 void *theEnv,
165 const char *itemName)
166 {
167 return(EnvSetWatchItem(theEnv,itemName,ON,NULL));
168 }
169
170 /*********************************************************/
171 /* EnvUnwatch: C access routine for the unwatch command. */
172 /*********************************************************/
EnvUnwatch(void * theEnv,const char * itemName)173 globle intBool EnvUnwatch(
174 void *theEnv,
175 const char *itemName)
176 {
177 return(EnvSetWatchItem(theEnv,itemName,OFF,NULL));
178 }
179
180 /***********************************************************************/
181 /* EnvSetWatchItem: Sets the state of a specified watch item to either */
182 /* on or off. Returns TRUE if the item was set, otherwise FALSE. */
183 /***********************************************************************/
EnvSetWatchItem(void * theEnv,const char * itemName,unsigned newState,struct expr * argExprs)184 globle int EnvSetWatchItem(
185 void *theEnv,
186 const char *itemName,
187 unsigned newState,
188 struct expr *argExprs)
189 {
190 struct watchItem *wPtr;
191
192 /*======================================================*/
193 /* If the new state isn't on or off, then return FALSE. */
194 /*======================================================*/
195
196 if ((newState != ON) && (newState != OFF)) return(FALSE);
197
198 /*===================================================*/
199 /* If the name of the watch item to set is all, then */
200 /* all watch items are set to the new state and TRUE */
201 /* is returned. */
202 /*===================================================*/
203
204 if (strcmp(itemName,"all") == 0)
205 {
206 for (wPtr = WatchData(theEnv)->ListOfWatchItems; wPtr != NULL; wPtr = wPtr->next)
207 {
208 /*==============================================*/
209 /* If no specific arguments are specified, then */
210 /* set the global flag for the watch item. */
211 /*==============================================*/
212
213 if (argExprs == NULL) *(wPtr->flag) = newState;
214
215 /*=======================================*/
216 /* Set flags for individual watch items. */
217 /*=======================================*/
218
219 if ((wPtr->accessFunc == NULL) ? FALSE :
220 ((*wPtr->accessFunc)(theEnv,wPtr->code,newState,argExprs) == FALSE))
221 {
222 SetEvaluationError(theEnv,TRUE);
223 return(FALSE);
224 }
225 }
226 return(TRUE);
227 }
228
229 /*=================================================*/
230 /* Search for the watch item to be set in the list */
231 /* of watch items. If found, set the watch item to */
232 /* its new state and return TRUE. */
233 /*=================================================*/
234
235 for (wPtr = WatchData(theEnv)->ListOfWatchItems; wPtr != NULL; wPtr = wPtr->next)
236 {
237 if (strcmp(itemName,wPtr->name) == 0)
238 {
239 /*==============================================*/
240 /* If no specific arguments are specified, then */
241 /* set the global flag for the watch item. */
242 /*==============================================*/
243
244 if (argExprs == NULL) *(wPtr->flag) = newState;
245
246 /*=======================================*/
247 /* Set flags for individual watch items. */
248 /*=======================================*/
249
250 if ((wPtr->accessFunc == NULL) ? FALSE :
251 ((*wPtr->accessFunc)(theEnv,wPtr->code,newState,argExprs) == FALSE))
252 {
253 SetEvaluationError(theEnv,TRUE);
254 return(FALSE);
255 }
256
257 return(TRUE);
258 }
259 }
260
261 /*=================================================*/
262 /* If the specified item was not found in the list */
263 /* of watchable items then return FALSE. */
264 /*=================================================*/
265
266 return(FALSE);
267 }
268
269 /******************************************************************/
270 /* EnvGetWatchItem: Gets the current state of the specified watch */
271 /* item. Returns the state of the watch item (0 for off and 1 */
272 /* for on) if the watch item is found in the list of watch */
273 /* items, otherwise -1 is returned. */
274 /******************************************************************/
EnvGetWatchItem(void * theEnv,const char * itemName)275 globle int EnvGetWatchItem(
276 void *theEnv,
277 const char *itemName)
278 {
279 struct watchItem *wPtr;
280
281 for (wPtr = WatchData(theEnv)->ListOfWatchItems; wPtr != NULL; wPtr = wPtr->next)
282 {
283 if (strcmp(itemName,wPtr->name) == 0)
284 { return((int) *(wPtr->flag)); }
285 }
286
287 return(-1);
288 }
289
290 /****************************************************************/
291 /* ValidWatchItem: Returns TRUE if the specified name is found */
292 /* in the list of watch items, otherwise returns FALSE. */
293 /****************************************************************/
ValidWatchItem(void * theEnv,const char * itemName,int * recognized)294 static struct watchItem *ValidWatchItem(
295 void *theEnv,
296 const char *itemName,
297 int *recognized)
298 {
299 struct watchItem *wPtr;
300
301 *recognized = TRUE;
302 if (strcmp(itemName,"all") == 0)
303 return(NULL);
304
305 for (wPtr = WatchData(theEnv)->ListOfWatchItems; wPtr != NULL; wPtr = wPtr->next)
306 { if (strcmp(itemName,wPtr->name) == 0) return(wPtr); }
307
308 *recognized = FALSE;
309 return(NULL);
310 }
311
312 /*************************************************************/
313 /* GetNthWatchName: Returns the name associated with the nth */
314 /* item in the list of watchable items. If the nth item */
315 /* does not exist, then NULL is returned. */
316 /*************************************************************/
GetNthWatchName(void * theEnv,int whichItem)317 globle const char *GetNthWatchName(
318 void *theEnv,
319 int whichItem)
320 {
321 int i;
322 struct watchItem *wPtr;
323
324 for (wPtr = WatchData(theEnv)->ListOfWatchItems, i = 1;
325 wPtr != NULL;
326 wPtr = wPtr->next, i++)
327 { if (i == whichItem) return(wPtr->name); }
328
329 return(NULL);
330 }
331
332 /***************************************************************/
333 /* GetNthWatchValue: Returns the current state associated with */
334 /* the nth item in the list of watchable items. If the nth */
335 /* item does not exist, then -1 is returned. */
336 /***************************************************************/
GetNthWatchValue(void * theEnv,int whichItem)337 globle int GetNthWatchValue(
338 void *theEnv,
339 int whichItem)
340 {
341 int i;
342 struct watchItem *wPtr;
343
344 for (wPtr = WatchData(theEnv)->ListOfWatchItems, i = 1;
345 wPtr != NULL;
346 wPtr = wPtr->next, i++)
347 { if (i == whichItem) return((int) *(wPtr->flag)); }
348
349 return(-1);
350 }
351
352 /**************************************/
353 /* WatchCommand: H/L access routine */
354 /* for the watch command. */
355 /**************************************/
WatchCommand(void * theEnv)356 globle void WatchCommand(
357 void *theEnv)
358 {
359 DATA_OBJECT theValue;
360 const char *argument;
361 int recognized;
362 struct watchItem *wPtr;
363
364 /*========================================*/
365 /* Determine which item is to be watched. */
366 /*========================================*/
367
368 if (EnvArgTypeCheck(theEnv,"watch",1,SYMBOL,&theValue) == FALSE) return;
369 argument = DOToString(theValue);
370 wPtr = ValidWatchItem(theEnv,argument,&recognized);
371 if (recognized == FALSE)
372 {
373 SetEvaluationError(theEnv,TRUE);
374 ExpectedTypeError1(theEnv,"watch",1,"watchable symbol");
375 return;
376 }
377
378 /*=================================================*/
379 /* Check to make sure extra arguments are allowed. */
380 /*=================================================*/
381
382 if (GetNextArgument(GetFirstArgument()) != NULL)
383 {
384 if ((wPtr == NULL) ? TRUE : (wPtr->accessFunc == NULL))
385 {
386 SetEvaluationError(theEnv,TRUE);
387 ExpectedCountError(theEnv,"watch",EXACTLY,1);
388 return;
389 }
390 }
391
392 /*=====================*/
393 /* Set the watch item. */
394 /*=====================*/
395
396 EnvSetWatchItem(theEnv,argument,ON,GetNextArgument(GetFirstArgument()));
397 }
398
399 /****************************************/
400 /* UnwatchCommand: H/L access routine */
401 /* for the unwatch command. */
402 /****************************************/
UnwatchCommand(void * theEnv)403 globle void UnwatchCommand(
404 void *theEnv)
405 {
406 DATA_OBJECT theValue;
407 const char *argument;
408 int recognized;
409 struct watchItem *wPtr;
410
411 /*==========================================*/
412 /* Determine which item is to be unwatched. */
413 /*==========================================*/
414
415 if (EnvArgTypeCheck(theEnv,"unwatch",1,SYMBOL,&theValue) == FALSE) return;
416 argument = DOToString(theValue);
417 wPtr = ValidWatchItem(theEnv,argument,&recognized);
418 if (recognized == FALSE)
419 {
420 SetEvaluationError(theEnv,TRUE);
421 ExpectedTypeError1(theEnv,"unwatch",1,"watchable symbol");
422 return;
423 }
424
425 /*=================================================*/
426 /* Check to make sure extra arguments are allowed. */
427 /*=================================================*/
428
429 if (GetNextArgument(GetFirstArgument()) != NULL)
430 {
431 if ((wPtr == NULL) ? TRUE : (wPtr->accessFunc == NULL))
432 {
433 SetEvaluationError(theEnv,TRUE);
434 ExpectedCountError(theEnv,"unwatch",EXACTLY,1);
435 return;
436 }
437 }
438
439 /*=====================*/
440 /* Set the watch item. */
441 /*=====================*/
442
443 EnvSetWatchItem(theEnv,argument,OFF,GetNextArgument(GetFirstArgument()));
444 }
445
446 /************************************************/
447 /* ListWatchItemsCommand: H/L access routines */
448 /* for the list-watch-items command. */
449 /************************************************/
ListWatchItemsCommand(void * theEnv)450 globle void ListWatchItemsCommand(
451 void *theEnv)
452 {
453 struct watchItem *wPtr;
454 DATA_OBJECT theValue;
455 int recognized;
456
457 /*=======================*/
458 /* List the watch items. */
459 /*=======================*/
460
461 if (GetFirstArgument() == NULL)
462 {
463 for (wPtr = WatchData(theEnv)->ListOfWatchItems; wPtr != NULL; wPtr = wPtr->next)
464 {
465 EnvPrintRouter(theEnv,WDISPLAY,wPtr->name);
466 if (*(wPtr->flag)) EnvPrintRouter(theEnv,WDISPLAY," = on\n");
467 else EnvPrintRouter(theEnv,WDISPLAY," = off\n");
468 }
469 return;
470 }
471
472 /*=======================================*/
473 /* Determine which item is to be listed. */
474 /*=======================================*/
475
476 if (EnvArgTypeCheck(theEnv,"list-watch-items",1,SYMBOL,&theValue) == FALSE) return;
477 wPtr = ValidWatchItem(theEnv,DOToString(theValue),&recognized);
478 if ((recognized == FALSE) || (wPtr == NULL))
479 {
480 SetEvaluationError(theEnv,TRUE);
481 ExpectedTypeError1(theEnv,"list-watch-items",1,"watchable symbol");
482 return;
483 }
484
485 /*=================================================*/
486 /* Check to make sure extra arguments are allowed. */
487 /*=================================================*/
488
489 if ((wPtr->printFunc == NULL) &&
490 (GetNextArgument(GetFirstArgument()) != NULL))
491 {
492 SetEvaluationError(theEnv,TRUE);
493 ExpectedCountError(theEnv,"list-watch-items",EXACTLY,1);
494 return;
495 }
496
497 /*====================================*/
498 /* List the status of the watch item. */
499 /*====================================*/
500
501 EnvPrintRouter(theEnv,WDISPLAY,wPtr->name);
502 if (*(wPtr->flag)) EnvPrintRouter(theEnv,WDISPLAY," = on\n");
503 else EnvPrintRouter(theEnv,WDISPLAY," = off\n");
504
505 /*============================================*/
506 /* List the status of individual watch items. */
507 /*============================================*/
508
509 if (wPtr->printFunc != NULL)
510 {
511 if ((*wPtr->printFunc)(theEnv,WDISPLAY,wPtr->code,
512 GetNextArgument(GetFirstArgument())) == FALSE)
513 { SetEvaluationError(theEnv,TRUE); }
514 }
515 }
516
517 /*******************************************/
518 /* GetWatchItemCommand: H/L access routine */
519 /* for the get-watch-item command. */
520 /*******************************************/
GetWatchItemCommand(void * theEnv)521 globle int GetWatchItemCommand(
522 void *theEnv)
523 {
524 DATA_OBJECT theValue;
525 const char *argument;
526 int recognized;
527
528 /*============================================*/
529 /* Check for the correct number of arguments. */
530 /*============================================*/
531
532 if (EnvArgCountCheck(theEnv,"get-watch-item",EXACTLY,1) == -1)
533 { return(FALSE); }
534
535 /*========================================*/
536 /* Determine which item is to be watched. */
537 /*========================================*/
538
539 if (EnvArgTypeCheck(theEnv,"get-watch-item",1,SYMBOL,&theValue) == FALSE)
540 { return(FALSE); }
541
542 argument = DOToString(theValue);
543 ValidWatchItem(theEnv,argument,&recognized);
544 if (recognized == FALSE)
545 {
546 SetEvaluationError(theEnv,TRUE);
547 ExpectedTypeError1(theEnv,"get-watch-item",1,"watchable symbol");
548 return(FALSE);
549 }
550
551 /*===========================*/
552 /* Get the watch item value. */
553 /*===========================*/
554
555 if (EnvGetWatchItem(theEnv,argument) == 1)
556 { return(TRUE); }
557
558 return(FALSE);
559 }
560
561 /*************************************************************/
562 /* WatchFunctionDefinitions: Initializes the watch commands. */
563 /*************************************************************/
WatchFunctionDefinitions(void * theEnv)564 globle void WatchFunctionDefinitions(
565 void *theEnv)
566 {
567 #if ! RUN_TIME
568 EnvDefineFunction2(theEnv,"watch", 'v', PTIEF WatchCommand, "WatchCommand", "1**w");
569 EnvDefineFunction2(theEnv,"unwatch", 'v', PTIEF UnwatchCommand, "UnwatchCommand", "1**w");
570 EnvDefineFunction2(theEnv,"get-watch-item", 'b', PTIEF GetWatchItemCommand, "GetWatchItemCommand", "11w");
571 EnvDefineFunction2(theEnv,"list-watch-items", 'v', PTIEF ListWatchItemsCommand,
572 "ListWatchItemsCommand", "0**w");
573 #endif
574
575 EnvAddRouter(theEnv,WTRACE,1000,RecognizeWatchRouters,CaptureWatchPrints,NULL,NULL,NULL);
576 EnvDeactivateRouter(theEnv,WTRACE);
577 }
578
579 /**************************************************/
580 /* RecognizeWatchRouters: Looks for WTRACE prints */
581 /**************************************************/
RecognizeWatchRouters(void * theEnv,const char * logName)582 static intBool RecognizeWatchRouters(
583 void *theEnv,
584 const char *logName)
585 {
586 #if MAC_XCD
587 #pragma unused(theEnv)
588 #endif
589
590 if (strcmp(logName,WTRACE) == 0) return(TRUE);
591
592 return(FALSE);
593 }
594
595 /**************************************************/
596 /* CaptureWatchPrints: Suppresses WTRACE messages */
597 /**************************************************/
CaptureWatchPrints(void * theEnv,const char * logName,const char * str)598 static int CaptureWatchPrints(
599 void *theEnv,
600 const char *logName,
601 const char *str)
602 {
603 #if MAC_XCD
604 #pragma unused(logName)
605 #pragma unused(str)
606 #pragma unused(theEnv)
607 #endif
608 return(1);
609 }
610
611 /*#####################################*/
612 /* ALLOW_ENVIRONMENT_GLOBALS Functions */
613 /*#####################################*/
614
615 #if ALLOW_ENVIRONMENT_GLOBALS
616
Watch(const char * itemName)617 globle intBool Watch(
618 const char *itemName)
619 {
620 return(EnvWatch(GetCurrentEnvironment(),itemName));
621 }
622
Unwatch(const char * itemName)623 globle intBool Unwatch(
624 const char *itemName)
625 {
626 return(EnvUnwatch(GetCurrentEnvironment(),itemName));
627 }
628
GetWatchItem(const char * itemName)629 globle int GetWatchItem(
630 const char *itemName)
631 {
632 return EnvGetWatchItem(GetCurrentEnvironment(),itemName);
633 }
634
SetWatchItem(const char * itemName,unsigned newState,struct expr * argExprs)635 globle int SetWatchItem(
636 const char *itemName,
637 unsigned newState,
638 struct expr *argExprs)
639 {
640 return EnvSetWatchItem(GetCurrentEnvironment(),itemName,newState,argExprs);
641 }
642
643 #endif
644
645 #endif /* DEBUGGING_FUNCTIONS */
646
647