00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #define _CSTRNCHK_SOURCE_
00031
00032 #include <stdio.h>
00033 #define _STDIO_INCLUDED_
00034 #include <stdlib.h>
00035
00036 #include "setup.h"
00037
00038 #include "router.h"
00039 #include "multifld.h"
00040 #include "envrnmnt.h"
00041 #include "extnfunc.h"
00042 #include "cstrnutl.h"
00043 #if OBJECT_SYSTEM
00044 #include "inscom.h"
00045 #include "insfun.h"
00046 #include "classcom.h"
00047 #include "classexm.h"
00048 #endif
00049
00050 #include "cstrnchk.h"
00051
00052
00053
00054
00055
00056 static intBool CheckRangeAgainstCardinalityConstraint(void *,int,int,CONSTRAINT_RECORD *);
00057 static int CheckFunctionReturnType(int,CONSTRAINT_RECORD *);
00058 static intBool CheckTypeConstraint(int,CONSTRAINT_RECORD *);
00059 static intBool CheckRangeConstraint(void *,int,void *,CONSTRAINT_RECORD *);
00060 static void PrintRange(void *,char *,CONSTRAINT_RECORD *);
00061
00062
00063
00064
00065
00066
00067
00068 static int CheckFunctionReturnType(
00069 int functionReturnType,
00070 CONSTRAINT_RECORD *constraints)
00071 {
00072 if (constraints == NULL) return(TRUE);
00073
00074 if (constraints->anyAllowed) return(TRUE);
00075
00076 switch(functionReturnType)
00077 {
00078 case 'c':
00079 case 'w':
00080 case 'b':
00081 if (constraints->symbolsAllowed) return(TRUE);
00082 else return(FALSE);
00083
00084 case 's':
00085 if (constraints->stringsAllowed) return(TRUE);
00086 else return(FALSE);
00087
00088 case 'j':
00089 if ((constraints->symbolsAllowed) ||
00090 (constraints->stringsAllowed) ||
00091 (constraints->instanceNamesAllowed)) return(TRUE);
00092 else return(FALSE);
00093
00094 case 'k':
00095 if ((constraints->symbolsAllowed) || (constraints->stringsAllowed)) return(TRUE);
00096 else return(FALSE);
00097
00098 case 'd':
00099 case 'f':
00100 if (constraints->floatsAllowed) return(TRUE);
00101 else return(FALSE);
00102
00103 case 'i':
00104 case 'l':
00105 if (constraints->integersAllowed) return(TRUE);
00106 else return(FALSE);
00107
00108 case 'n':
00109 if ((constraints->integersAllowed) || (constraints->floatsAllowed)) return(TRUE);
00110 else return(FALSE);
00111
00112 case 'm':
00113 if (constraints->multifieldsAllowed) return(TRUE);
00114 else return(FALSE);
00115
00116 case 'a':
00117 if (constraints->externalAddressesAllowed) return(TRUE);
00118 else return(FALSE);
00119
00120 case 'x':
00121 if (constraints->instanceAddressesAllowed) return(TRUE);
00122 else return(FALSE);
00123
00124 case 'o':
00125 if (constraints->instanceNamesAllowed) return(TRUE);
00126 else return(FALSE);
00127
00128 case 'u':
00129 return(TRUE);
00130
00131 case 'v':
00132 if (constraints->voidAllowed) return(TRUE);
00133 }
00134
00135 return(TRUE);
00136 }
00137
00138
00139
00140
00141
00142
00143 static intBool CheckTypeConstraint(
00144 int type,
00145 CONSTRAINT_RECORD *constraints)
00146 {
00147 if (type == RVOID) return(FALSE);
00148
00149 if (constraints == NULL) return(TRUE);
00150
00151 if (constraints->anyAllowed == TRUE) return(TRUE);
00152
00153 if ((type == SYMBOL) && (constraints->symbolsAllowed != TRUE))
00154 { return(FALSE); }
00155
00156 if ((type == STRING) && (constraints->stringsAllowed != TRUE))
00157 { return(FALSE); }
00158
00159 if ((type == FLOAT) && (constraints->floatsAllowed != TRUE))
00160 { return(FALSE); }
00161
00162 if ((type == INTEGER) && (constraints->integersAllowed != TRUE))
00163 { return(FALSE); }
00164
00165 #if OBJECT_SYSTEM
00166 if ((type == INSTANCE_NAME) && (constraints->instanceNamesAllowed != TRUE))
00167 { return(FALSE); }
00168
00169 if ((type == INSTANCE_ADDRESS) && (constraints->instanceAddressesAllowed != TRUE))
00170 { return(FALSE); }
00171 #endif
00172
00173 if ((type == EXTERNAL_ADDRESS) && (constraints->externalAddressesAllowed != TRUE))
00174 { return(FALSE); }
00175
00176 if ((type == RVOID) && (constraints->voidAllowed != TRUE))
00177 { return(FALSE); }
00178
00179 if ((type == FACT_ADDRESS) && (constraints->factAddressesAllowed != TRUE))
00180 { return(FALSE); }
00181
00182 return(TRUE);
00183 }
00184
00185
00186
00187
00188
00189
00190 globle intBool CheckCardinalityConstraint(
00191 void *theEnv,
00192 long number,
00193 CONSTRAINT_RECORD *constraints)
00194 {
00195
00196
00197
00198
00199
00200 if (constraints == NULL) return(TRUE);
00201
00202
00203
00204
00205
00206
00207 if (constraints->minFields != NULL)
00208 {
00209 if (constraints->minFields->value != SymbolData(theEnv)->NegativeInfinity)
00210 {
00211 if (number < ValueToLong(constraints->minFields->value))
00212 { return(FALSE); }
00213 }
00214 }
00215
00216
00217
00218
00219
00220
00221 if (constraints->maxFields != NULL)
00222 {
00223 if (constraints->maxFields->value != SymbolData(theEnv)->PositiveInfinity)
00224 {
00225 if (number > ValueToLong(constraints->maxFields->value))
00226 { return(FALSE); }
00227 }
00228 }
00229
00230
00231
00232
00233
00234 return(TRUE);
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244 static intBool CheckRangeAgainstCardinalityConstraint(
00245 void *theEnv,
00246 int min,
00247 int max,
00248 CONSTRAINT_RECORD *constraints)
00249 {
00250
00251
00252
00253
00254
00255 if (constraints == NULL) return(TRUE);
00256
00257
00258
00259
00260
00261
00262
00263
00264 if (constraints->maxFields != NULL)
00265 {
00266 if (constraints->maxFields->value != SymbolData(theEnv)->PositiveInfinity)
00267 {
00268 if (min > ValueToLong(constraints->maxFields->value))
00269 { return(FALSE); }
00270 }
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 if ((constraints->minFields != NULL) && (max != -1))
00282 {
00283 if (constraints->minFields->value != SymbolData(theEnv)->NegativeInfinity)
00284 {
00285 if (max < ValueToLong(constraints->minFields->value))
00286 { return(FALSE); }
00287 }
00288 }
00289
00290
00291
00292
00293
00294
00295 return(TRUE);
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 globle intBool CheckAllowedValuesConstraint(
00305 int type,
00306 void *vPtr,
00307 CONSTRAINT_RECORD *constraints)
00308 {
00309 struct expr *tmpPtr;
00310
00311
00312
00313
00314
00315
00316 if (constraints == NULL) return(TRUE);
00317
00318
00319
00320
00321
00322
00323 switch (type)
00324 {
00325 case SYMBOL:
00326 if ((constraints->symbolRestriction == FALSE) &&
00327 (constraints->anyRestriction == FALSE))
00328 { return(TRUE); }
00329 break;
00330
00331 #if OBJECT_SYSTEM
00332 case INSTANCE_NAME:
00333 if ((constraints->instanceNameRestriction == FALSE) &&
00334 (constraints->anyRestriction == FALSE))
00335 { return(TRUE); }
00336 break;
00337 #endif
00338
00339 case STRING:
00340 if ((constraints->stringRestriction == FALSE) &&
00341 (constraints->anyRestriction == FALSE))
00342 { return(TRUE); }
00343 break;
00344
00345 case INTEGER:
00346 if ((constraints->integerRestriction == FALSE) &&
00347 (constraints->anyRestriction == FALSE))
00348 { return(TRUE); }
00349 break;
00350
00351 case FLOAT:
00352 if ((constraints->floatRestriction == FALSE) &&
00353 (constraints->anyRestriction == FALSE))
00354 { return(TRUE); }
00355 break;
00356
00357 default:
00358 return(TRUE);
00359 }
00360
00361
00362
00363
00364
00365
00366 for (tmpPtr = constraints->restrictionList;
00367 tmpPtr != NULL;
00368 tmpPtr = tmpPtr->nextArg)
00369 {
00370 if ((tmpPtr->type == type) && (tmpPtr->value == vPtr)) return(TRUE);
00371 }
00372
00373
00374
00375
00376
00377
00378 return(FALSE);
00379 }
00380
00381
00382
00383
00384
00385
00386
00387 globle intBool CheckAllowedClassesConstraint(
00388 void *theEnv,
00389 int type,
00390 void *vPtr,
00391 CONSTRAINT_RECORD *constraints)
00392 {
00393 #if OBJECT_SYSTEM
00394 struct expr *tmpPtr;
00395 INSTANCE_TYPE *ins;
00396 DEFCLASS *insClass, *cmpClass;
00397
00398
00399
00400
00401
00402
00403 if (constraints == NULL) return(TRUE);
00404
00405
00406
00407
00408
00409
00410 if (constraints->classList == NULL)
00411 { return(TRUE); }
00412
00413
00414
00415
00416
00417
00418 if ((type != INSTANCE_ADDRESS) && (type != INSTANCE_NAME))
00419 { return(TRUE); }
00420
00421
00422
00423
00424
00425
00426 if (type == INSTANCE_ADDRESS)
00427 { ins = (INSTANCE_TYPE *) vPtr; }
00428 else
00429 { ins = FindInstanceBySymbol(theEnv,(SYMBOL_HN *) vPtr); }
00430
00431 if (ins == NULL)
00432 { return(FALSE); }
00433
00434
00435
00436
00437
00438
00439 insClass = (DEFCLASS *) EnvGetInstanceClass(theEnv,ins);
00440 for (tmpPtr = constraints->classList;
00441 tmpPtr != NULL;
00442 tmpPtr = tmpPtr->nextArg)
00443 {
00444 cmpClass = (DEFCLASS *) EnvFindDefclass(theEnv,ValueToString(tmpPtr->value));
00445 if (cmpClass == NULL) continue;
00446 if (cmpClass == insClass) return(TRUE);
00447 if (EnvSubclassP(theEnv,insClass,cmpClass)) return(TRUE);
00448 }
00449
00450
00451
00452
00453
00454
00455 return(FALSE);
00456 #else
00457
00458 #if MAC_MCW || WIN_MCW || MAC_XCD
00459 #pragma unused(theEnv)
00460 #pragma unused(type)
00461 #pragma unused(vPtr)
00462 #pragma unused(constraints)
00463 #endif
00464
00465 return(TRUE);
00466 #endif
00467 }
00468
00469
00470
00471
00472
00473 static intBool CheckRangeConstraint(
00474 void *theEnv,
00475 int type,
00476 void *vPtr,
00477 CONSTRAINT_RECORD *constraints)
00478 {
00479 struct expr *minList, *maxList;
00480
00481
00482
00483
00484
00485
00486 if (constraints == NULL) return(TRUE);
00487
00488
00489
00490
00491
00492
00493 if ((type != INTEGER) && (type != FLOAT)) return(TRUE);
00494
00495
00496
00497
00498
00499
00500
00501
00502 minList = constraints->minValue;
00503 maxList = constraints->maxValue;
00504
00505 while (minList != NULL)
00506 {
00507 if (CompareNumbers(theEnv,type,vPtr,minList->type,minList->value) == LESS_THAN)
00508 {
00509 minList = minList->nextArg;
00510 maxList = maxList->nextArg;
00511 }
00512 else if (CompareNumbers(theEnv,type,vPtr,maxList->type,maxList->value) == GREATER_THAN)
00513 {
00514 minList = minList->nextArg;
00515 maxList = maxList->nextArg;
00516 }
00517 else
00518 { return(TRUE); }
00519 }
00520
00521
00522
00523
00524
00525
00526 return(FALSE);
00527 }
00528
00529
00530
00531
00532
00533 globle void ConstraintViolationErrorMessage(
00534 void *theEnv,
00535 char *theWhat,
00536 char *thePlace,
00537 int command,
00538 int thePattern,
00539 struct symbolHashNode *theSlot,
00540 int theField,
00541 int violationType,
00542 CONSTRAINT_RECORD *theConstraint,
00543 int printPrelude)
00544 {
00545
00546
00547
00548
00549
00550 if (printPrelude)
00551 {
00552
00553
00554
00555
00556
00557 if (violationType == FUNCTION_RETURN_TYPE_VIOLATION)
00558 {
00559 PrintErrorID(theEnv,"CSTRNCHK",1,TRUE);
00560 EnvPrintRouter(theEnv,WERROR,"The function return value ");
00561 }
00562 else if (theWhat != NULL)
00563 {
00564 PrintErrorID(theEnv,"CSTRNCHK",1,TRUE);
00565 EnvPrintRouter(theEnv,WERROR,theWhat);
00566 EnvPrintRouter(theEnv,WERROR," ");
00567 }
00568
00569
00570
00571
00572
00573
00574 if (thePlace != NULL)
00575 {
00576 EnvPrintRouter(theEnv,WERROR,"found in ");
00577 if (command) EnvPrintRouter(theEnv,WERROR,"the ");
00578 EnvPrintRouter(theEnv,WERROR,thePlace);
00579 if (command) EnvPrintRouter(theEnv,WERROR," command");
00580 }
00581
00582
00583
00584
00585
00586
00587 if (thePattern > 0)
00588 {
00589 EnvPrintRouter(theEnv,WERROR,"found in CE #");
00590 PrintLongInteger(theEnv,WERROR,(long int) thePattern);
00591 }
00592 }
00593
00594
00595
00596
00597
00598 if ((violationType == TYPE_VIOLATION) ||
00599 (violationType == FUNCTION_RETURN_TYPE_VIOLATION))
00600 { EnvPrintRouter(theEnv,WERROR,"\ndoes not match the allowed types"); }
00601 else if (violationType == RANGE_VIOLATION)
00602 {
00603 EnvPrintRouter(theEnv,WERROR,"\ndoes not fall in the allowed range ");
00604 PrintRange(theEnv,WERROR,theConstraint);
00605 }
00606 else if (violationType == ALLOWED_VALUES_VIOLATION)
00607 { EnvPrintRouter(theEnv,WERROR,"\ndoes not match the allowed values"); }
00608 else if (violationType == CARDINALITY_VIOLATION)
00609 { EnvPrintRouter(theEnv,WERROR,"\ndoes not satisfy the cardinality restrictions"); }
00610 else if (violationType == ALLOWED_CLASSES_VIOLATION)
00611 { EnvPrintRouter(theEnv,WERROR,"\ndoes not match the allowed classes"); }
00612
00613
00614
00615
00616
00617
00618 if (theSlot != NULL)
00619 {
00620 EnvPrintRouter(theEnv,WERROR," for slot ");
00621 EnvPrintRouter(theEnv,WERROR,ValueToString(theSlot));
00622 }
00623 else if (theField > 0)
00624 {
00625 EnvPrintRouter(theEnv,WERROR," for field #");
00626 PrintLongInteger(theEnv,WERROR,(long long) theField);
00627 }
00628
00629 EnvPrintRouter(theEnv,WERROR,".\n");
00630 }
00631
00632
00633
00634
00635
00636 static void PrintRange(
00637 void *theEnv,
00638 char *logicalName,
00639 CONSTRAINT_RECORD *theConstraint)
00640 {
00641 if (theConstraint->minValue->value == SymbolData(theEnv)->NegativeInfinity)
00642 { EnvPrintRouter(theEnv,logicalName,ValueToString(SymbolData(theEnv)->NegativeInfinity)); }
00643 else PrintExpression(theEnv,logicalName,theConstraint->minValue);
00644 EnvPrintRouter(theEnv,logicalName," to ");
00645 if (theConstraint->maxValue->value == SymbolData(theEnv)->PositiveInfinity)
00646 { EnvPrintRouter(theEnv,logicalName,ValueToString(SymbolData(theEnv)->PositiveInfinity)); }
00647 else PrintExpression(theEnv,logicalName,theConstraint->maxValue);
00648 }
00649
00650
00651
00652
00653
00654
00655 globle int ConstraintCheckDataObject(
00656 void *theEnv,
00657 DATA_OBJECT *theData,
00658 CONSTRAINT_RECORD *theConstraints)
00659 {
00660 long i;
00661 int rv;
00662 struct field *theMultifield;
00663
00664 if (theConstraints == NULL) return(NO_VIOLATION);
00665
00666 if (theData->type == MULTIFIELD)
00667 {
00668 if (CheckCardinalityConstraint(theEnv,(theData->end - theData->begin) + 1,
00669 theConstraints) == FALSE)
00670 { return(CARDINALITY_VIOLATION); }
00671
00672 theMultifield = ((struct multifield *) theData->value)->theFields;
00673 for (i = theData->begin; i <= theData->end; i++)
00674 {
00675 if ((rv = ConstraintCheckValue(theEnv,theMultifield[i].type,
00676 theMultifield[i].value,
00677 theConstraints)) != NO_VIOLATION)
00678 { return(rv); }
00679 }
00680
00681 return(NO_VIOLATION);
00682 }
00683
00684 if (CheckCardinalityConstraint(theEnv,1L,theConstraints) == FALSE)
00685 { return(CARDINALITY_VIOLATION); }
00686
00687 return(ConstraintCheckValue(theEnv,theData->type,theData->value,theConstraints));
00688 }
00689
00690
00691
00692
00693
00694 globle int ConstraintCheckValue(
00695 void *theEnv,
00696 int theType,
00697 void *theValue,
00698 CONSTRAINT_RECORD *theConstraints)
00699 {
00700 if (CheckTypeConstraint(theType,theConstraints) == FALSE)
00701 { return(TYPE_VIOLATION); }
00702
00703 else if (CheckAllowedValuesConstraint(theType,theValue,theConstraints) == FALSE)
00704 { return(ALLOWED_VALUES_VIOLATION); }
00705
00706 else if (CheckAllowedClassesConstraint(theEnv,theType,theValue,theConstraints) == FALSE)
00707 { return(ALLOWED_CLASSES_VIOLATION); }
00708
00709 else if (CheckRangeConstraint(theEnv,theType,theValue,theConstraints) == FALSE)
00710 { return(RANGE_VIOLATION); }
00711
00712 else if (theType == FCALL)
00713 {
00714 if (CheckFunctionReturnType((int) ValueFunctionType(theValue),theConstraints) == FALSE)
00715 { return(FUNCTION_RETURN_TYPE_VIOLATION); }
00716 }
00717
00718 return(NO_VIOLATION);
00719 }
00720
00721
00722
00723
00724
00725 globle int ConstraintCheckExpressionChain(
00726 void *theEnv,
00727 struct expr *theExpression,
00728 CONSTRAINT_RECORD *theConstraints)
00729 {
00730 struct expr *theExp;
00731 int min = 0, max = 0, vCode;
00732
00733
00734
00735
00736
00737
00738
00739 for (theExp = theExpression ; theExp != NULL ; theExp = theExp->nextArg)
00740 {
00741 if (ConstantType(theExp->type)) min++;
00742 else if (theExp->type == FCALL)
00743 {
00744 if ((ExpressionFunctionType(theExp) != 'm') &&
00745 (ExpressionFunctionType(theExp) != 'u')) min++;
00746 else max = -1;
00747 }
00748 else max = -1;
00749 }
00750
00751
00752
00753
00754
00755 if (max == 0) max = min;
00756 if (CheckRangeAgainstCardinalityConstraint(theEnv,min,max,theConstraints) == FALSE)
00757 { return(CARDINALITY_VIOLATION); }
00758
00759
00760
00761
00762
00763 for (theExp = theExpression ; theExp != NULL ; theExp = theExp->nextArg)
00764 {
00765 vCode = ConstraintCheckValue(theEnv,theExp->type,theExp->value,theConstraints);
00766 if (vCode != NO_VIOLATION)
00767 return(vCode);
00768 }
00769
00770 return(NO_VIOLATION);
00771 }
00772
00773 #if (! RUN_TIME) && (! BLOAD_ONLY)
00774
00775
00776
00777
00778
00779
00780 globle int ConstraintCheckExpression(
00781 void *theEnv,
00782 struct expr *theExpression,
00783 CONSTRAINT_RECORD *theConstraints)
00784 {
00785 int rv = NO_VIOLATION;
00786
00787 if (theConstraints == NULL) return(rv);
00788
00789 while (theExpression != NULL)
00790 {
00791 rv = ConstraintCheckValue(theEnv,theExpression->type,
00792 theExpression->value,
00793 theConstraints);
00794 if (rv != NO_VIOLATION) return(rv);
00795 rv = ConstraintCheckExpression(theEnv,theExpression->argList,theConstraints);
00796 if (rv != NO_VIOLATION) return(rv);
00797 theExpression = theExpression->nextArg;
00798 }
00799
00800 return(rv);
00801 }
00802
00803 #endif
00804
00805 #if (! RUN_TIME)
00806
00807
00808
00809
00810
00811 globle intBool UnmatchableConstraint(
00812 CONSTRAINT_RECORD *theConstraint)
00813 {
00814 if (theConstraint == NULL) return(FALSE);
00815
00816 if ((! theConstraint->anyAllowed) &&
00817 (! theConstraint->symbolsAllowed) &&
00818 (! theConstraint->stringsAllowed) &&
00819 (! theConstraint->floatsAllowed) &&
00820 (! theConstraint->integersAllowed) &&
00821 (! theConstraint->instanceNamesAllowed) &&
00822 (! theConstraint->instanceAddressesAllowed) &&
00823 (! theConstraint->multifieldsAllowed) &&
00824 (! theConstraint->externalAddressesAllowed) &&
00825 (! theConstraint->voidAllowed) &&
00826 (! theConstraint->factAddressesAllowed))
00827 { return(TRUE); }
00828
00829 return(FALSE);
00830 }
00831
00832 #endif
00833