1 /*******************************************************/
2 /* "C" Language Integrated Production System */
3 /* */
4 /* CLIPS Version 6.30 08/16/14 */
5 /* */
6 /* CONSTRAINT UTILITY MODULE */
7 /*******************************************************/
8
9 /*************************************************************/
10 /* Purpose: Utility routines for manipulating, initializing, */
11 /* creating, copying, and comparing constraint records. */
12 /* */
13 /* Principal Programmer(s): */
14 /* Gary D. Riley */
15 /* */
16 /* Contributing Programmer(s): */
17 /* Brian Dantes */
18 /* */
19 /* Revision History: */
20 /* */
21 /* 6.24: Added allowed-classes slot facet. */
22 /* */
23 /* 6.30: Support for long long integers. */
24 /* */
25 /*************************************************************/
26
27 #define _CSTRNUTL_SOURCE_
28
29 #include <stdio.h>
30 #define _STDIO_INCLUDED_
31 #include <stdlib.h>
32
33 #include "setup.h"
34
35 #include "constant.h"
36 #include "envrnmnt.h"
37 #include "memalloc.h"
38 #include "router.h"
39 #include "extnfunc.h"
40 #include "scanner.h"
41 #include "multifld.h"
42 #include "argacces.h"
43
44 #include "cstrnutl.h"
45
46 /************************************************/
47 /* GetConstraintRecord: Creates and initializes */
48 /* the values of a constraint record. */
49 /************************************************/
GetConstraintRecord(void * theEnv)50 globle struct constraintRecord *GetConstraintRecord(
51 void *theEnv)
52 {
53 CONSTRAINT_RECORD *constraints;
54 unsigned i;
55
56 constraints = get_struct(theEnv,constraintRecord);
57
58 for (i = 0 ; i < sizeof(CONSTRAINT_RECORD) ; i++)
59 { ((char *) constraints)[i] = '\0'; }
60
61 SetAnyAllowedFlags(constraints,TRUE);
62
63 constraints->multifieldsAllowed = FALSE;
64 constraints->singlefieldsAllowed = TRUE;
65
66 constraints->anyRestriction = FALSE;
67 constraints->symbolRestriction = FALSE;
68 constraints->stringRestriction = FALSE;
69 constraints->floatRestriction = FALSE;
70 constraints->integerRestriction = FALSE;
71 constraints->classRestriction = FALSE;
72 constraints->instanceNameRestriction = FALSE;
73 constraints->classList = NULL;
74 constraints->restrictionList = NULL;
75 constraints->minValue = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->NegativeInfinity);
76 constraints->maxValue = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->PositiveInfinity);
77 constraints->minFields = GenConstant(theEnv,INTEGER,SymbolData(theEnv)->Zero);
78 constraints->maxFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->PositiveInfinity);
79 constraints->bucket = -1;
80 constraints->count = 0;
81 constraints->multifield = NULL;
82 constraints->next = NULL;
83
84 return(constraints);
85 }
86
87 /********************************************************/
88 /* SetAnyAllowedFlags: Sets the allowed type flags of a */
89 /* constraint record to allow all types. If passed an */
90 /* argument of TRUE, just the "any allowed" flag is */
91 /* set to TRUE. If passed an argument of FALSE, then */
92 /* all of the individual type flags are set to TRUE. */
93 /********************************************************/
SetAnyAllowedFlags(CONSTRAINT_RECORD * theConstraint,int justOne)94 globle void SetAnyAllowedFlags(
95 CONSTRAINT_RECORD *theConstraint,
96 int justOne)
97 {
98 int flag1, flag2;
99
100 if (justOne)
101 {
102 flag1 = TRUE;
103 flag2 = FALSE;
104 }
105 else
106 {
107 flag1 = FALSE;
108 flag2 = TRUE;
109 }
110
111 theConstraint->anyAllowed = flag1;
112 theConstraint->symbolsAllowed = flag2;
113 theConstraint->stringsAllowed = flag2;
114 theConstraint->floatsAllowed = flag2;
115 theConstraint->integersAllowed = flag2;
116 theConstraint->instanceNamesAllowed = flag2;
117 theConstraint->instanceAddressesAllowed = flag2;
118 theConstraint->externalAddressesAllowed = flag2;
119 theConstraint->voidAllowed = flag2;
120 theConstraint->factAddressesAllowed = flag2;
121 }
122
123 /*****************************************************/
124 /* CopyConstraintRecord: Copies a constraint record. */
125 /*****************************************************/
CopyConstraintRecord(void * theEnv,CONSTRAINT_RECORD * sourceConstraint)126 globle struct constraintRecord *CopyConstraintRecord(
127 void *theEnv,
128 CONSTRAINT_RECORD *sourceConstraint)
129 {
130 CONSTRAINT_RECORD *theConstraint;
131
132 if (sourceConstraint == NULL) return(NULL);
133
134 theConstraint = get_struct(theEnv,constraintRecord);
135
136 theConstraint->anyAllowed = sourceConstraint->anyAllowed;
137 theConstraint->symbolsAllowed = sourceConstraint->symbolsAllowed;
138 theConstraint->stringsAllowed = sourceConstraint->stringsAllowed;
139 theConstraint->floatsAllowed = sourceConstraint->floatsAllowed;
140 theConstraint->integersAllowed = sourceConstraint->integersAllowed;
141 theConstraint->instanceNamesAllowed = sourceConstraint->instanceNamesAllowed;
142 theConstraint->instanceAddressesAllowed = sourceConstraint->instanceAddressesAllowed;
143 theConstraint->externalAddressesAllowed = sourceConstraint->externalAddressesAllowed;
144 theConstraint->voidAllowed = sourceConstraint->voidAllowed;
145 theConstraint->multifieldsAllowed = sourceConstraint->multifieldsAllowed;
146 theConstraint->singlefieldsAllowed = sourceConstraint->singlefieldsAllowed;
147 theConstraint->factAddressesAllowed = sourceConstraint->factAddressesAllowed;
148 theConstraint->anyRestriction = sourceConstraint->anyRestriction;
149 theConstraint->symbolRestriction = sourceConstraint->symbolRestriction;
150 theConstraint->stringRestriction = sourceConstraint->stringRestriction;
151 theConstraint->floatRestriction = sourceConstraint->floatRestriction;
152 theConstraint->integerRestriction = sourceConstraint->integerRestriction;
153 theConstraint->classRestriction = sourceConstraint->classRestriction;
154 theConstraint->instanceNameRestriction = sourceConstraint->instanceNameRestriction;
155 theConstraint->classList = CopyExpression(theEnv,sourceConstraint->classList);
156 theConstraint->restrictionList = CopyExpression(theEnv,sourceConstraint->restrictionList);
157 theConstraint->minValue = CopyExpression(theEnv,sourceConstraint->minValue);
158 theConstraint->maxValue = CopyExpression(theEnv,sourceConstraint->maxValue);
159 theConstraint->minFields = CopyExpression(theEnv,sourceConstraint->minFields);
160 theConstraint->maxFields = CopyExpression(theEnv,sourceConstraint->maxFields);
161 theConstraint->bucket = -1;
162 theConstraint->count = 0;
163 theConstraint->multifield = CopyConstraintRecord(theEnv,sourceConstraint->multifield);
164 theConstraint->next = NULL;
165
166 return(theConstraint);
167 }
168
169 #if (! RUN_TIME) && (! BLOAD_ONLY)
170
171 /**************************************************************/
172 /* SetAnyRestrictionFlags: Sets the restriction type flags of */
173 /* a constraint record to indicate there are restriction on */
174 /* all types. If passed an argument of TRUE, just the */
175 /* "any restriction" flag is set to TRUE. If passed an */
176 /* argument of FALSE, then all of the individual type */
177 /* restriction flags are set to TRUE. */
178 /**************************************************************/
SetAnyRestrictionFlags(CONSTRAINT_RECORD * theConstraint,int justOne)179 globle void SetAnyRestrictionFlags(
180 CONSTRAINT_RECORD *theConstraint,
181 int justOne)
182 {
183 int flag1, flag2;
184
185 if (justOne)
186 {
187 flag1 = TRUE;
188 flag2 = FALSE;
189 }
190 else
191 {
192 flag1 = FALSE;
193 flag2 = TRUE;
194 }
195
196 theConstraint->anyRestriction = flag1;
197 theConstraint->symbolRestriction = flag2;
198 theConstraint->stringRestriction = flag2;
199 theConstraint->floatRestriction = flag2;
200 theConstraint->integerRestriction = flag2;
201 theConstraint->instanceNameRestriction = flag2;
202 }
203
204 /*****************************************************/
205 /* SetConstraintType: Given a constraint type and a */
206 /* constraint, sets the allowed type flags for the */
207 /* specified type in the constraint to TRUE. */
208 /*****************************************************/
SetConstraintType(int theType,CONSTRAINT_RECORD * constraints)209 globle int SetConstraintType(
210 int theType,
211 CONSTRAINT_RECORD *constraints)
212 {
213 int rv = TRUE;
214
215 switch(theType)
216 {
217 case UNKNOWN_VALUE:
218 rv = constraints->anyAllowed;
219 constraints->anyAllowed = TRUE;
220 break;
221
222 case SYMBOL:
223 rv = constraints->symbolsAllowed;
224 constraints->symbolsAllowed = TRUE;
225 break;
226
227 case STRING:
228 rv = constraints->stringsAllowed;
229 constraints->stringsAllowed = TRUE;
230 break;
231
232 case SYMBOL_OR_STRING:
233 rv = (constraints->stringsAllowed | constraints->symbolsAllowed);
234 constraints->symbolsAllowed = TRUE;
235 constraints->stringsAllowed = TRUE;
236 break;
237
238 case INTEGER:
239 rv = constraints->integersAllowed;
240 constraints->integersAllowed = TRUE;
241 break;
242
243 case FLOAT:
244 rv = constraints->floatsAllowed;
245 constraints->floatsAllowed = TRUE;
246 break;
247
248 case INTEGER_OR_FLOAT:
249 rv = (constraints->integersAllowed | constraints->floatsAllowed);
250 constraints->integersAllowed = TRUE;
251 constraints->floatsAllowed = TRUE;
252 break;
253
254 case INSTANCE_ADDRESS:
255 rv = constraints->instanceAddressesAllowed;
256 constraints->instanceAddressesAllowed = TRUE;
257 break;
258
259 case INSTANCE_NAME:
260 rv = constraints->instanceNamesAllowed;
261 constraints->instanceNamesAllowed = TRUE;
262 break;
263
264 case INSTANCE_OR_INSTANCE_NAME:
265 rv = (constraints->instanceNamesAllowed | constraints->instanceAddressesAllowed);
266 constraints->instanceNamesAllowed = TRUE;
267 constraints->instanceAddressesAllowed = TRUE;
268 break;
269
270 case EXTERNAL_ADDRESS:
271 rv = constraints->externalAddressesAllowed;
272 constraints->externalAddressesAllowed = TRUE;
273 break;
274
275 case RVOID:
276 rv = constraints->voidAllowed;
277 constraints->voidAllowed = TRUE;
278 break;
279
280 case FACT_ADDRESS:
281 rv = constraints->factAddressesAllowed;
282 constraints->factAddressesAllowed = TRUE;
283 break;
284
285 case MULTIFIELD:
286 rv = constraints->multifieldsAllowed;
287 constraints->multifieldsAllowed = TRUE;
288 break;
289 }
290
291 if (theType != UNKNOWN_VALUE) constraints->anyAllowed = FALSE;
292 return(rv);
293 }
294
295 #endif /* (! RUN_TIME) && (! BLOAD_ONLY) */
296
297 /*************************************************************/
298 /* CompareNumbers: Given two numbers (which can be integers, */
299 /* floats, or the symbols for positive/negative infinity) */
300 /* returns the relationship between the numbers (greater */
301 /* than, less than or equal). */
302 /*************************************************************/
CompareNumbers(void * theEnv,int type1,void * vptr1,int type2,void * vptr2)303 globle int CompareNumbers(
304 void *theEnv,
305 int type1,
306 void *vptr1,
307 int type2,
308 void *vptr2)
309 {
310 /*============================================*/
311 /* Handle the situation in which the values */
312 /* are exactly equal (same type, same value). */
313 /*============================================*/
314
315 if (vptr1 == vptr2) return(EQUAL);
316
317 /*=======================================*/
318 /* Handle the special cases for positive */
319 /* and negative infinity. */
320 /*=======================================*/
321
322 if (vptr1 == SymbolData(theEnv)->PositiveInfinity) return(GREATER_THAN);
323
324 if (vptr1 == SymbolData(theEnv)->NegativeInfinity) return(LESS_THAN);
325
326 if (vptr2 == SymbolData(theEnv)->PositiveInfinity) return(LESS_THAN);
327
328 if (vptr2 == SymbolData(theEnv)->NegativeInfinity) return(GREATER_THAN);
329
330 /*=======================*/
331 /* Compare two integers. */
332 /*=======================*/
333
334 if ((type1 == INTEGER) && (type2 == INTEGER))
335 {
336 if (ValueToLong(vptr1) < ValueToLong(vptr2))
337 { return(LESS_THAN); }
338 else if (ValueToLong(vptr1) > ValueToLong(vptr2))
339 { return(GREATER_THAN); }
340
341 return(EQUAL);
342 }
343
344 /*=====================*/
345 /* Compare two floats. */
346 /*=====================*/
347
348 if ((type1 == FLOAT) && (type2 == FLOAT))
349 {
350 if (ValueToDouble(vptr1) < ValueToDouble(vptr2))
351 { return(LESS_THAN); }
352 else if (ValueToDouble(vptr1) > ValueToDouble(vptr2))
353 { return(GREATER_THAN); }
354
355 return(EQUAL);
356 }
357
358 /*================================*/
359 /* Compare an integer to a float. */
360 /*================================*/
361
362 if ((type1 == INTEGER) && (type2 == FLOAT))
363 {
364 if (((double) ValueToLong(vptr1)) < ValueToDouble(vptr2))
365 { return(LESS_THAN); }
366 else if (((double) ValueToLong(vptr1)) > ValueToDouble(vptr2))
367 { return(GREATER_THAN); }
368
369 return(EQUAL);
370 }
371
372 /*================================*/
373 /* Compare a float to an integer. */
374 /*================================*/
375
376 if ((type1 == FLOAT) && (type2 == INTEGER))
377 {
378 if (ValueToDouble(vptr1) < ((double) ValueToLong(vptr2)))
379 { return(LESS_THAN); }
380 else if (ValueToDouble(vptr1) > ((double) ValueToLong(vptr2)))
381 { return(GREATER_THAN); }
382
383 return(EQUAL);
384 }
385
386 /*===================================*/
387 /* One of the arguments was invalid. */
388 /* Return -1 to indicate an error. */
389 /*===================================*/
390
391 return(-1);
392 }
393
394 /****************************************************************/
395 /* ExpressionToConstraintRecord: Converts an expression into a */
396 /* constraint record. For example, an expression representing */
397 /* the symbol BLUE would be converted to a record with */
398 /* allowed types SYMBOL and allow-values BLUE. */
399 /****************************************************************/
ExpressionToConstraintRecord(void * theEnv,struct expr * theExpression)400 globle CONSTRAINT_RECORD *ExpressionToConstraintRecord(
401 void *theEnv,
402 struct expr *theExpression)
403 {
404 CONSTRAINT_RECORD *rv;
405
406 /*================================================*/
407 /* A NULL expression is converted to a constraint */
408 /* record with no values allowed. */
409 /*================================================*/
410
411 if (theExpression == NULL)
412 {
413 rv = GetConstraintRecord(theEnv);
414 rv->anyAllowed = FALSE;
415 return(rv);
416 }
417
418 /*=============================================================*/
419 /* Convert variables and function calls to constraint records. */
420 /*=============================================================*/
421
422 if ((theExpression->type == SF_VARIABLE) ||
423 (theExpression->type == MF_VARIABLE) ||
424 #if DEFGENERIC_CONSTRUCT
425 (theExpression->type == GCALL) ||
426 #endif
427 #if DEFFUNCTION_CONSTRUCT
428 (theExpression->type == PCALL) ||
429 #endif
430 (theExpression->type == GBL_VARIABLE) ||
431 (theExpression->type == MF_GBL_VARIABLE))
432 {
433 rv = GetConstraintRecord(theEnv);
434 rv->multifieldsAllowed = TRUE;
435 return(rv);
436 }
437 else if (theExpression->type == FCALL)
438 { return(FunctionCallToConstraintRecord(theEnv,theExpression->value)); }
439
440 /*============================================*/
441 /* Convert a constant to a constraint record. */
442 /*============================================*/
443
444 rv = GetConstraintRecord(theEnv);
445 rv->anyAllowed = FALSE;
446
447 if (theExpression->type == FLOAT)
448 {
449 rv->floatRestriction = TRUE;
450 rv->floatsAllowed = TRUE;
451 }
452 else if (theExpression->type == INTEGER)
453 {
454 rv->integerRestriction = TRUE;
455 rv->integersAllowed = TRUE;
456 }
457 else if (theExpression->type == SYMBOL)
458 {
459 rv->symbolRestriction = TRUE;
460 rv->symbolsAllowed = TRUE;
461 }
462 else if (theExpression->type == STRING)
463 {
464 rv->stringRestriction = TRUE;
465 rv->stringsAllowed = TRUE;
466 }
467 else if (theExpression->type == INSTANCE_NAME)
468 {
469 rv->instanceNameRestriction = TRUE;
470 rv->instanceNamesAllowed = TRUE;
471 }
472 else if (theExpression->type == INSTANCE_ADDRESS)
473 { rv->instanceAddressesAllowed = TRUE; }
474
475 if (rv->floatsAllowed || rv->integersAllowed || rv->symbolsAllowed ||
476 rv->stringsAllowed || rv->instanceNamesAllowed)
477 { rv->restrictionList = GenConstant(theEnv,theExpression->type,theExpression->value); }
478
479 return(rv);
480 }
481
482 /*******************************************************/
483 /* FunctionCallToConstraintRecord: Converts a function */
484 /* call to a constraint record. For example, the + */
485 /* function when converted would be a constraint */
486 /* record with allowed types INTEGER and FLOAT. */
487 /*******************************************************/
FunctionCallToConstraintRecord(void * theEnv,void * theFunction)488 globle CONSTRAINT_RECORD *FunctionCallToConstraintRecord(
489 void *theEnv,
490 void *theFunction)
491 {
492 CONSTRAINT_RECORD *rv;
493
494 rv = GetConstraintRecord(theEnv);
495 rv->anyAllowed = FALSE;
496
497 switch ((char) ValueFunctionType(theFunction))
498 {
499 case 'a':
500 rv->externalAddressesAllowed = TRUE;
501 break;
502
503 case 'f':
504 case 'd':
505 rv->floatsAllowed = TRUE;
506 break;
507
508 case 'i':
509 case 'g':
510 case 'l':
511 rv->integersAllowed = TRUE;
512 break;
513
514 case 'j':
515 rv->instanceNamesAllowed = TRUE;
516 rv->symbolsAllowed = TRUE;
517 rv->stringsAllowed = TRUE;
518 break;
519
520 case 'k':
521 rv->symbolsAllowed = TRUE;
522 rv->stringsAllowed = TRUE;
523 break;
524
525 case 'm':
526 rv->singlefieldsAllowed = FALSE;
527 rv->multifieldsAllowed = TRUE;
528 break;
529
530 case 'n':
531 rv->floatsAllowed = TRUE;
532 rv->integersAllowed = TRUE;
533 break;
534
535 case 'o':
536 rv->instanceNamesAllowed = TRUE;
537 break;
538
539 case 's':
540 rv->stringsAllowed = TRUE;
541 break;
542
543 case 'u':
544 rv->anyAllowed = TRUE;
545 rv->multifieldsAllowed = TRUE;
546 break;
547
548 case 'w':
549 case 'c':
550 case 'b':
551 rv->symbolsAllowed = TRUE;
552 break;
553
554 case 'x':
555 rv->instanceAddressesAllowed = TRUE;
556 break;
557
558 case 'y':
559 rv->factAddressesAllowed = TRUE;
560 break;
561
562 case 'v':
563 rv->voidAllowed = TRUE;
564 break;
565 }
566
567 return(rv);
568 }
569
570 /*******************************************************/
571 /* ArgumentTypeToConstraintRecord: Converts one of the */
572 /* function argument types (used by DefineFunction2) */
573 /* to a constraint record. */
574 /*******************************************************/
ArgumentTypeToConstraintRecord(void * theEnv,int theRestriction)575 globle CONSTRAINT_RECORD *ArgumentTypeToConstraintRecord(
576 void *theEnv,
577 int theRestriction)
578 {
579 CONSTRAINT_RECORD *rv;
580
581 rv = GetConstraintRecord(theEnv);
582 rv->anyAllowed = FALSE;
583
584 switch (theRestriction)
585 {
586 case 'a':
587 rv->externalAddressesAllowed = TRUE;
588 break;
589
590 case 'e':
591 rv->symbolsAllowed = TRUE;
592 rv->instanceNamesAllowed = TRUE;
593 rv->instanceAddressesAllowed = TRUE;
594 break;
595
596 case 'd':
597 case 'f':
598 rv->floatsAllowed = TRUE;
599 break;
600
601 case 'g':
602 rv->integersAllowed = TRUE;
603 rv->floatsAllowed = TRUE;
604 rv->symbolsAllowed = TRUE;
605 break;
606
607 case 'h':
608 rv->factAddressesAllowed = TRUE;
609 rv->integersAllowed = TRUE;
610 rv->symbolsAllowed = TRUE;
611 rv->instanceNamesAllowed = TRUE;
612 rv->instanceAddressesAllowed = TRUE;
613 break;
614
615 case 'i':
616 case 'l':
617 rv->integersAllowed = TRUE;
618 break;
619
620 case 'j':
621 rv->symbolsAllowed = TRUE;
622 rv->stringsAllowed = TRUE;
623 rv->instanceNamesAllowed = TRUE;
624 break;
625
626 case 'k':
627 rv->symbolsAllowed = TRUE;
628 rv->stringsAllowed = TRUE;
629 break;
630
631 case 'm':
632 rv->singlefieldsAllowed = FALSE;
633 rv->multifieldsAllowed = TRUE;
634 break;
635
636 case 'n':
637 rv->floatsAllowed = TRUE;
638 rv->integersAllowed = TRUE;
639 break;
640
641 case 'o':
642 rv->instanceNamesAllowed = TRUE;
643 break;
644
645 case 'p':
646 rv->instanceNamesAllowed = TRUE;
647 rv->symbolsAllowed = TRUE;
648 break;
649
650 case 'q':
651 rv->symbolsAllowed = TRUE;
652 rv->stringsAllowed = TRUE;
653 rv->multifieldsAllowed = TRUE;
654 break;
655
656 case 's':
657 rv->stringsAllowed = TRUE;
658 break;
659
660 case 'w':
661 rv->symbolsAllowed = TRUE;
662 break;
663
664 case 'x':
665 rv->instanceAddressesAllowed = TRUE;
666 break;
667
668 case 'y':
669 rv->factAddressesAllowed = TRUE;
670 break;
671
672 case 'z':
673 rv->symbolsAllowed = TRUE;
674 rv->factAddressesAllowed = TRUE;
675 rv->integersAllowed = TRUE;
676 break;
677
678 case 'u':
679 rv->anyAllowed = TRUE;
680 rv->multifieldsAllowed = TRUE;
681 break;
682
683 case 'v':
684 rv->voidAllowed = TRUE;
685 break;
686 }
687
688 return(rv);
689 }
690
691
692
693
694