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 #define _BLOAD_SOURCE_
00026
00027 #include "setup.h"
00028
00029 #include "argacces.h"
00030 #include "bsave.h"
00031 #include "constrct.h"
00032 #include "cstrnbin.h"
00033 #include "envrnmnt.h"
00034 #include "exprnpsr.h"
00035 #include "memalloc.h"
00036 #include "router.h"
00037 #include "utility.h"
00038
00039 #include "bload.h"
00040
00041 #if (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE)
00042
00043
00044
00045
00046
00047 static struct FunctionDefinition **ReadNeededFunctions(void *,long *,int *);
00048 static struct FunctionDefinition *FastFindFunction(void *,char *,struct FunctionDefinition *);
00049 static int ClearBload(void *);
00050 static void AbortBload(void *);
00051 static int BloadOutOfMemoryFunction(void *,size_t);
00052 static void DeallocateBloadData(void *);
00053
00054
00055
00056
00057
00058 globle void InitializeBloadData(
00059 void *theEnv)
00060 {
00061 AllocateEnvironmentData(theEnv,BLOAD_DATA,sizeof(struct bloadData),NULL);
00062 AddEnvironmentCleanupFunction(theEnv,"bload",DeallocateBloadData,-1500);
00063
00064 BloadData(theEnv)->BinaryPrefixID = "\1\2\3\4CLIPS";
00065 BloadData(theEnv)->BinaryVersionID = "V6.30";
00066 }
00067
00068
00069
00070
00071
00072 static void DeallocateBloadData(
00073 void *theEnv)
00074 {
00075 DeallocateCallList(theEnv,BloadData(theEnv)->BeforeBloadFunctions);
00076 DeallocateCallList(theEnv,BloadData(theEnv)->AfterBloadFunctions);
00077 DeallocateCallList(theEnv,BloadData(theEnv)->ClearBloadReadyFunctions);
00078 DeallocateCallList(theEnv,BloadData(theEnv)->AbortBloadFunctions);
00079 }
00080
00081
00082
00083
00084
00085 globle int EnvBload(
00086 void *theEnv,
00087 char *fileName)
00088 {
00089 long numberOfFunctions;
00090 unsigned long space;
00091 int error;
00092 char IDbuffer[20];
00093 char constructBuffer[CONSTRUCT_HEADER_SIZE];
00094 struct BinaryItem *biPtr;
00095 struct callFunctionItem *bfPtr;
00096
00097
00098
00099
00100
00101 if (GenOpenReadBinary(theEnv,"bload",fileName) == 0) return(FALSE);
00102
00103
00104
00105
00106
00107 GenReadBinary(theEnv,IDbuffer,(unsigned long) strlen(BloadData(theEnv)->BinaryPrefixID) + 1);
00108 if (strcmp(IDbuffer,BloadData(theEnv)->BinaryPrefixID) != 0)
00109 {
00110 PrintErrorID(theEnv,"BLOAD",2,FALSE);
00111 EnvPrintRouter(theEnv,WERROR,"File ");
00112 EnvPrintRouter(theEnv,WERROR,fileName);
00113 EnvPrintRouter(theEnv,WERROR," is not a binary construct file.\n");
00114 GenCloseBinary(theEnv);
00115 return(FALSE);
00116 }
00117
00118
00119
00120
00121
00122
00123 GenReadBinary(theEnv,IDbuffer,(unsigned long) strlen(BloadData(theEnv)->BinaryVersionID) + 1);
00124 if (strcmp(IDbuffer,BloadData(theEnv)->BinaryVersionID) != 0)
00125 {
00126 PrintErrorID(theEnv,"BLOAD",3,FALSE);
00127 EnvPrintRouter(theEnv,WERROR,"File ");
00128 EnvPrintRouter(theEnv,WERROR,fileName);
00129 EnvPrintRouter(theEnv,WERROR," is an incompatible binary construct file.\n");
00130 GenCloseBinary(theEnv);
00131 return(FALSE);
00132 }
00133
00134
00135
00136
00137
00138 if (BloadData(theEnv)->BloadActive)
00139 {
00140 if (ClearBload(theEnv) == FALSE)
00141 {
00142 GenCloseBinary(theEnv);
00143 return(FALSE);
00144 }
00145 }
00146
00147
00148
00149
00150
00151
00152 if (ClearReady(theEnv) == FALSE)
00153 {
00154 GenCloseBinary(theEnv);
00155 EnvPrintRouter(theEnv,WERROR,"The ");
00156 EnvPrintRouter(theEnv,WERROR,APPLICATION_NAME);
00157 EnvPrintRouter(theEnv,WERROR," environment could not be cleared.\n");
00158 EnvPrintRouter(theEnv,WERROR,"Binary load cannot continue.\n");
00159 return(FALSE);
00160 }
00161
00162
00163
00164
00165
00166
00167 for (bfPtr = BloadData(theEnv)->BeforeBloadFunctions;
00168 bfPtr != NULL;
00169 bfPtr = bfPtr->next)
00170 {
00171 if (bfPtr->environmentAware)
00172 { (*bfPtr->func)(theEnv); }
00173 else
00174 { (* (void (*)(void)) bfPtr->func)(); }
00175 }
00176
00177
00178
00179
00180
00181 BloadData(theEnv)->FunctionArray = ReadNeededFunctions(theEnv,&numberOfFunctions,&error);
00182 if (error)
00183 {
00184 GenCloseBinary(theEnv);
00185 AbortBload(theEnv);
00186 return(FALSE);
00187 }
00188
00189
00190
00191
00192
00193 ReadNeededAtomicValues(theEnv);
00194
00195
00196
00197
00198
00199
00200 AllocateExpressions(theEnv);
00201
00202
00203
00204
00205
00206
00207 for (GenReadBinary(theEnv,constructBuffer,(unsigned long) CONSTRUCT_HEADER_SIZE);
00208 strncmp(constructBuffer,BloadData(theEnv)->BinaryPrefixID,CONSTRUCT_HEADER_SIZE) != 0;
00209 GenReadBinary(theEnv,constructBuffer,(unsigned long) CONSTRUCT_HEADER_SIZE))
00210 {
00211 intBool found;
00212
00213
00214
00215
00216
00217
00218
00219 found = FALSE;
00220 for (biPtr = BsaveData(theEnv)->ListOfBinaryItems;
00221 biPtr != NULL;
00222 biPtr = biPtr->next)
00223 {
00224 if (strncmp(biPtr->name,constructBuffer,CONSTRUCT_HEADER_SIZE) == 0)
00225 {
00226 if (biPtr->bloadStorageFunction != NULL)
00227 {
00228 (*biPtr->bloadStorageFunction)(theEnv);
00229 found = TRUE;
00230 }
00231 break;
00232 }
00233 }
00234
00235
00236
00237
00238
00239
00240
00241 if (! found)
00242 {
00243 GenReadBinary(theEnv,&space,(unsigned long) sizeof(unsigned long));
00244 GetSeekCurBinary(theEnv,(long) space);
00245 if (space != 0)
00246 {
00247 EnvPrintRouter(theEnv,WDIALOG,"\nSkipping ");
00248 EnvPrintRouter(theEnv,WDIALOG,constructBuffer);
00249 EnvPrintRouter(theEnv,WDIALOG," constructs because of unavailibility\n");
00250 }
00251 }
00252 }
00253
00254
00255
00256
00257
00258 RefreshExpressions(theEnv);
00259
00260
00261
00262
00263
00264 ReadNeededConstraints(theEnv);
00265
00266
00267
00268
00269
00270 for (GenReadBinary(theEnv,constructBuffer,(unsigned long) CONSTRUCT_HEADER_SIZE);
00271 strncmp(constructBuffer,BloadData(theEnv)->BinaryPrefixID,CONSTRUCT_HEADER_SIZE) != 0;
00272 GenReadBinary(theEnv,constructBuffer,(unsigned long) CONSTRUCT_HEADER_SIZE))
00273 {
00274 intBool found;
00275
00276
00277
00278
00279
00280
00281
00282 found = FALSE;
00283 for (biPtr = BsaveData(theEnv)->ListOfBinaryItems;
00284 biPtr != NULL;
00285 biPtr = biPtr->next)
00286 {
00287 if (strncmp(biPtr->name,constructBuffer,CONSTRUCT_HEADER_SIZE) == 0)
00288 {
00289 if (biPtr->bloadFunction != NULL)
00290 {
00291 (*biPtr->bloadFunction)(theEnv);
00292 found = TRUE;
00293 }
00294 break;
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303 if (! found)
00304 {
00305 GenReadBinary(theEnv,&space,(unsigned long) sizeof(unsigned long));
00306 GetSeekCurBinary(theEnv,(long) space);
00307 }
00308 }
00309
00310
00311
00312
00313
00314 GenCloseBinary(theEnv);
00315
00316
00317
00318
00319
00320
00321 if (BloadData(theEnv)->FunctionArray != NULL)
00322 {
00323 genfree(theEnv,(void *) BloadData(theEnv)->FunctionArray,
00324 sizeof(struct FunctionDefinition *) * numberOfFunctions);
00325 }
00326 FreeAtomicValueStorage(theEnv);
00327
00328
00329
00330
00331
00332
00333 for (bfPtr = BloadData(theEnv)->AfterBloadFunctions;
00334 bfPtr != NULL;
00335 bfPtr = bfPtr->next)
00336 {
00337 if (bfPtr->environmentAware)
00338 { (*bfPtr->func)(theEnv); }
00339 else
00340 { (* (void (*)(void)) bfPtr->func)(); }
00341 }
00342
00343
00344
00345
00346
00347
00348 BloadData(theEnv)->BloadActive = TRUE;
00349 EnvAddClearFunction(theEnv,"bload",(void (*)(void *)) ClearBload,10000);
00350
00351
00352
00353
00354
00355
00356 return(TRUE);
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 globle void BloadandRefresh(
00376 void *theEnv,
00377 long objcnt,
00378 size_t objsz,
00379 void (*objupdate)(void *,void *,long))
00380 {
00381 register long i,bi;
00382 char *buf;
00383 long objsmaxread,objsread;
00384 size_t space;
00385 int (*oldOutOfMemoryFunction)(void *,size_t);
00386
00387 if (objcnt == 0L) return;
00388
00389 oldOutOfMemoryFunction = EnvSetOutOfMemoryFunction(theEnv,BloadOutOfMemoryFunction);
00390 objsmaxread = objcnt;
00391 do
00392 {
00393 space = objsmaxread * objsz;
00394 buf = (char *) genalloc(theEnv,space);
00395 if (buf == NULL)
00396 {
00397 if ((objsmaxread / 2) == 0)
00398 {
00399 if ((*oldOutOfMemoryFunction)(theEnv,space) == TRUE)
00400 {
00401 EnvSetOutOfMemoryFunction(theEnv,oldOutOfMemoryFunction);
00402 return;
00403 }
00404 }
00405 else
00406 objsmaxread /= 2;
00407 }
00408 }
00409 while (buf == NULL);
00410
00411 EnvSetOutOfMemoryFunction(theEnv,oldOutOfMemoryFunction);
00412
00413 i = 0L;
00414 do
00415 {
00416 objsread = (objsmaxread > (objcnt - i)) ? (objcnt - i) : objsmaxread;
00417 GenReadBinary(theEnv,(void *) buf,objsread * objsz);
00418 for (bi = 0L ; bi < objsread ; bi++ , i++)
00419 (*objupdate)(theEnv,buf + objsz * bi,i);
00420 }
00421 while (i < objcnt);
00422 genfree(theEnv,(void *) buf,space);
00423 }
00424
00425
00426
00427
00428
00429 static struct FunctionDefinition **ReadNeededFunctions(
00430 void *theEnv,
00431 long int *numberOfFunctions,
00432 int *error)
00433 {
00434 char *functionNames, *namePtr;
00435 unsigned long int space;
00436 size_t temp;
00437 long i;
00438 struct FunctionDefinition **newFunctionArray, *functionPtr;
00439 int functionsNotFound = 0;
00440
00441
00442
00443
00444
00445
00446 GenReadBinary(theEnv,numberOfFunctions,(unsigned long) sizeof(long int));
00447 GenReadBinary(theEnv,&space,(unsigned long) sizeof(unsigned long int));
00448 if (*numberOfFunctions == 0)
00449 {
00450 *error = FALSE;
00451 return(NULL);
00452 }
00453
00454
00455
00456
00457
00458 functionNames = (char *) genalloc(theEnv,space);
00459 GenReadBinary(theEnv,(void *) functionNames,space);
00460
00461
00462
00463
00464
00465 temp = (unsigned long) sizeof(struct FunctionDefinition *) * *numberOfFunctions;
00466 newFunctionArray = (struct FunctionDefinition **) genalloc(theEnv,temp);
00467 namePtr = functionNames;
00468 functionPtr = NULL;
00469 for (i = 0; i < *numberOfFunctions; i++)
00470 {
00471 if ((functionPtr = FastFindFunction(theEnv,namePtr,functionPtr)) == NULL)
00472 {
00473 if (! functionsNotFound)
00474 {
00475 PrintErrorID(theEnv,"BLOAD",6,FALSE);
00476 EnvPrintRouter(theEnv,WERROR,"The following undefined functions are ");
00477 EnvPrintRouter(theEnv,WERROR,"referenced by this binary image:\n");
00478 }
00479
00480 EnvPrintRouter(theEnv,WERROR," ");
00481 EnvPrintRouter(theEnv,WERROR,namePtr);
00482 EnvPrintRouter(theEnv,WERROR,"\n");
00483 functionsNotFound = 1;
00484 }
00485
00486 newFunctionArray[i] = functionPtr;
00487 namePtr += strlen(namePtr) + 1;
00488 }
00489
00490
00491
00492
00493
00494 genfree(theEnv,(void *) functionNames,space);
00495
00496
00497
00498
00499
00500
00501 if (functionsNotFound)
00502 {
00503 genfree(theEnv,(void *) newFunctionArray,temp);
00504 newFunctionArray = NULL;
00505 }
00506
00507
00508
00509
00510
00511
00512 *error = functionsNotFound;
00513 return(newFunctionArray);
00514 }
00515
00516
00517
00518
00519
00520 static struct FunctionDefinition *FastFindFunction(
00521 void *theEnv,
00522 char *functionName,
00523 struct FunctionDefinition *lastFunction)
00524 {
00525 struct FunctionDefinition *theList, *theFunction;
00526
00527
00528
00529
00530
00531 theList = GetFunctionList(theEnv);
00532 if (theList == NULL) { return(NULL); }
00533
00534
00535
00536
00537
00538
00539 if (lastFunction != NULL)
00540 { theFunction = lastFunction->next; }
00541 else
00542 { theFunction = theList; }
00543
00544
00545
00546
00547
00548
00549 while (strcmp(functionName,ValueToString(theFunction->callFunctionName)) != 0)
00550 {
00551 theFunction = theFunction->next;
00552 if (theFunction == lastFunction) return(NULL);
00553 if (theFunction == NULL) theFunction = theList;
00554 }
00555
00556
00557
00558
00559
00560
00561 return(theFunction);
00562 }
00563
00564
00565
00566
00567
00568
00569 globle intBool Bloaded(
00570 void *theEnv)
00571 {
00572 return(BloadData(theEnv)->BloadActive);
00573 }
00574
00575
00576
00577
00578
00579 static int ClearBload(
00580 void *theEnv)
00581 {
00582 struct BinaryItem *biPtr;
00583 struct callFunctionItem *bfPtr;
00584 int ready,error;
00585
00586
00587
00588
00589
00590 error = FALSE;
00591 for (bfPtr = BloadData(theEnv)->ClearBloadReadyFunctions;
00592 bfPtr != NULL;
00593 bfPtr = bfPtr->next)
00594 {
00595 if (bfPtr->environmentAware)
00596 { ready = (* ((int (*)(void *)) bfPtr->func))(theEnv); }
00597 else
00598 { ready = (* ((int (*)(void)) bfPtr->func))(); }
00599
00600 if (ready == FALSE)
00601 {
00602 if (! error)
00603 {
00604 PrintErrorID(theEnv,"BLOAD",5,FALSE);
00605 EnvPrintRouter(theEnv,WERROR,
00606 "Some constructs are still in use by the current binary image:\n");
00607 }
00608 EnvPrintRouter(theEnv,WERROR," ");
00609 EnvPrintRouter(theEnv,WERROR,bfPtr->name);
00610 EnvPrintRouter(theEnv,WERROR,"\n");
00611 error = TRUE;
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620
00621 if (error == TRUE)
00622 {
00623 EnvPrintRouter(theEnv,WERROR,"Binary clear cannot continue.\n");
00624 return(FALSE);
00625 }
00626
00627
00628
00629
00630
00631 for (biPtr = BsaveData(theEnv)->ListOfBinaryItems;
00632 biPtr != NULL;
00633 biPtr = biPtr->next)
00634 { if (biPtr->clearFunction != NULL) (*biPtr->clearFunction)(theEnv); }
00635
00636
00637
00638
00639
00640 ClearBloadedExpressions(theEnv);
00641
00642
00643
00644
00645
00646 ClearBloadedConstraints(theEnv);
00647
00648
00649
00650
00651
00652 BloadData(theEnv)->BloadActive = FALSE;
00653 EnvRemoveClearFunction(theEnv,"bload");
00654
00655
00656
00657
00658
00659
00660 return(TRUE);
00661 }
00662
00663
00664
00665
00666
00667 static void AbortBload(
00668 void *theEnv)
00669 {
00670 struct callFunctionItem *bfPtr;
00671
00672 for (bfPtr = BloadData(theEnv)->AbortBloadFunctions;
00673 bfPtr != NULL;
00674 bfPtr = bfPtr->next)
00675 {
00676 if (bfPtr->environmentAware)
00677 { (*bfPtr->func)(theEnv); }
00678 else
00679 { (* (void (*)(void)) bfPtr->func)(); }
00680 }
00681 }
00682
00683
00684
00685
00686
00687
00688 globle void AddBeforeBloadFunction(
00689 void *theEnv,
00690 char *name,
00691 void (*func)(void *),
00692 int priority)
00693 {
00694 BloadData(theEnv)->BeforeBloadFunctions =
00695 AddFunctionToCallList(theEnv,name,priority,func,BloadData(theEnv)->BeforeBloadFunctions,TRUE);
00696 }
00697
00698
00699
00700
00701
00702
00703 globle void AddAfterBloadFunction(
00704 void *theEnv,
00705 char *name,
00706 void (*func)(void *),
00707 int priority)
00708 {
00709 BloadData(theEnv)->AfterBloadFunctions =
00710 AddFunctionToCallList(theEnv,name,priority,func,BloadData(theEnv)->AfterBloadFunctions,TRUE);
00711 }
00712
00713
00714
00715
00716
00717
00718 globle void AddClearBloadReadyFunction(
00719 void *theEnv,
00720 char *name,
00721 int (*func)(void *),
00722 int priority)
00723 {
00724 BloadData(theEnv)->ClearBloadReadyFunctions =
00725 AddFunctionToCallList(theEnv,name,priority,
00726 (void (*)(void *)) func,
00727 BloadData(theEnv)->ClearBloadReadyFunctions,TRUE);
00728 }
00729
00730
00731
00732
00733
00734
00735 globle void AddAbortBloadFunction(
00736 void *theEnv,
00737 char *name,
00738 void (*func)(void *),
00739 int priority)
00740 {
00741 BloadData(theEnv)->AbortBloadFunctions = AddFunctionToCallList(theEnv,name,priority,func,BloadData(theEnv)->AbortBloadFunctions,TRUE);
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 #if WIN_BTC
00757 #pragma argsused
00758 #endif
00759 static int BloadOutOfMemoryFunction(
00760 void *theEnv,
00761 size_t size)
00762 {
00763 #if MAC_MCW || WIN_MCW || MAC_XCD
00764 #pragma unused(size,theEnv)
00765 #endif
00766 return(TRUE);
00767 }
00768
00769
00770
00771
00772
00773
00774 globle void CannotLoadWithBloadMessage(
00775 void *theEnv,
00776 char *constructName)
00777 {
00778 PrintErrorID(theEnv,"BLOAD",1,TRUE);
00779 EnvPrintRouter(theEnv,WERROR,"Cannot load ");
00780 EnvPrintRouter(theEnv,WERROR,constructName);
00781 EnvPrintRouter(theEnv,WERROR," construct with binary load in effect.\n");
00782 }
00783
00784 #endif
00785
00786
00787
00788
00789
00790 globle int BloadCommand(
00791 void *theEnv)
00792 {
00793 #if (! RUN_TIME) && (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE)
00794 char *fileName;
00795
00796 if (EnvArgCountCheck(theEnv,"bload",EXACTLY,1) == -1) return(FALSE);
00797 fileName = GetFileName(theEnv,"bload",1);
00798 if (fileName != NULL) return(EnvBload(theEnv,fileName));
00799 #else
00800 #if MAC_MCW || WIN_MCW || MAC_XCD
00801 #pragma unused(theEnv)
00802 #endif
00803 #endif
00804 return(FALSE);
00805 }