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
00031 #define _PRCDRFUN_SOURCE_
00032
00033 #include <stdio.h>
00034 #define _STDIO_INCLUDED_
00035
00036 #include "setup.h"
00037
00038 #include "argacces.h"
00039 #include "constrnt.h"
00040 #include "cstrnchk.h"
00041 #include "cstrnops.h"
00042 #include "envrnmnt.h"
00043 #include "exprnpsr.h"
00044 #include "memalloc.h"
00045 #include "multifld.h"
00046 #include "prcdrpsr.h"
00047 #include "router.h"
00048 #include "scanner.h"
00049 #include "utility.h"
00050
00051 #include "prcdrfun.h"
00052
00053 #if DEFGLOBAL_CONSTRUCT
00054 #include "globldef.h"
00055 #endif
00056
00057
00058
00059
00060
00061 static void DeallocateProceduralFunctionData(void *);
00062
00063
00064
00065
00066
00067 globle void ProceduralFunctionDefinitions(
00068 void *theEnv)
00069 {
00070 AllocateEnvironmentData(theEnv,PRCDRFUN_DATA,sizeof(struct procedureFunctionData),DeallocateProceduralFunctionData);
00071
00072 #if ! RUN_TIME
00073 EnvDefineFunction2(theEnv,"if", 'u', PTIEF IfFunction, "IfFunction", NULL);
00074 EnvDefineFunction2(theEnv,"while", 'u', PTIEF WhileFunction, "WhileFunction", NULL);
00075 EnvDefineFunction2(theEnv,"loop-for-count",'u', PTIEF LoopForCountFunction, "LoopForCountFunction", NULL);
00076 EnvDefineFunction2(theEnv,"(get-loop-count)",'g', PTIEF GetLoopCount, "GetLoopCount", NULL);
00077 EnvDefineFunction2(theEnv,"bind", 'u', PTIEF BindFunction, "BindFunction", NULL);
00078 EnvDefineFunction2(theEnv,"progn", 'u', PTIEF PrognFunction, "PrognFunction", NULL);
00079 EnvDefineFunction2(theEnv,"return", 'u', PTIEF ReturnFunction, "ReturnFunction",NULL);
00080 EnvDefineFunction2(theEnv,"break", 'v', PTIEF BreakFunction, "BreakFunction",NULL);
00081 EnvDefineFunction2(theEnv,"switch", 'u', PTIEF SwitchFunction, "SwitchFunction",NULL);
00082
00083 ProceduralFunctionParsers(theEnv);
00084
00085 FuncSeqOvlFlags(theEnv,"progn",FALSE,FALSE);
00086 FuncSeqOvlFlags(theEnv,"if",FALSE,FALSE);
00087 FuncSeqOvlFlags(theEnv,"while",FALSE,FALSE);
00088 FuncSeqOvlFlags(theEnv,"loop-for-count",FALSE,FALSE);
00089 FuncSeqOvlFlags(theEnv,"return",FALSE,FALSE);
00090 FuncSeqOvlFlags(theEnv,"switch",FALSE,FALSE);
00091 #endif
00092
00093 EnvAddResetFunction(theEnv,"bind",FlushBindList,0);
00094 EnvAddClearFunction(theEnv,"bind",FlushBindList,0);
00095 }
00096
00097
00098
00099
00100
00101 static void DeallocateProceduralFunctionData(
00102 void *theEnv)
00103 {
00104 DATA_OBJECT_PTR nextPtr, garbagePtr;
00105
00106 garbagePtr = ProcedureFunctionData(theEnv)->BindList;
00107
00108 while (garbagePtr != NULL)
00109 {
00110 nextPtr = garbagePtr->next;
00111 rtn_struct(theEnv,dataObject,garbagePtr);
00112 garbagePtr = nextPtr;
00113 }
00114 }
00115
00116
00117
00118
00119
00120 globle void WhileFunction(
00121 void *theEnv,
00122 DATA_OBJECT_PTR returnValue)
00123 {
00124 DATA_OBJECT theResult;
00125
00126
00127
00128
00129
00130
00131 EvaluationData(theEnv)->CurrentEvaluationDepth++;
00132 EnvRtnUnknown(theEnv,1,&theResult);
00133 while (((theResult.value != EnvFalseSymbol(theEnv)) ||
00134 (theResult.type != SYMBOL)) &&
00135 (EvaluationData(theEnv)->HaltExecution != TRUE))
00136 {
00137 if ((ProcedureFunctionData(theEnv)->BreakFlag == TRUE) || (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE))
00138 break;
00139 EnvRtnUnknown(theEnv,2,&theResult);
00140 EvaluationData(theEnv)->CurrentEvaluationDepth--;
00141 if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
00142 { PropagateReturnValue(theEnv,&theResult); }
00143 PeriodicCleanup(theEnv,FALSE,TRUE);
00144 EvaluationData(theEnv)->CurrentEvaluationDepth++;
00145 if ((ProcedureFunctionData(theEnv)->BreakFlag == TRUE) || (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE))
00146 break;
00147 EnvRtnUnknown(theEnv,1,&theResult);
00148 }
00149 EvaluationData(theEnv)->CurrentEvaluationDepth--;
00150
00151
00152
00153
00154
00155
00156
00157
00158 ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
00159
00160
00161
00162
00163
00164
00165 if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
00166 {
00167 returnValue->type = theResult.type;
00168 returnValue->value = theResult.value;
00169 returnValue->begin = theResult.begin;
00170 returnValue->end = theResult.end;
00171 }
00172 else
00173 {
00174 returnValue->type = SYMBOL;
00175 returnValue->value = EnvFalseSymbol(theEnv);
00176 }
00177 }
00178
00179
00180
00181
00182
00183 globle void LoopForCountFunction(
00184 void *theEnv,
00185 DATA_OBJECT_PTR loopResult)
00186 {
00187 DATA_OBJECT arg_ptr;
00188 long long iterationEnd;
00189 LOOP_COUNTER_STACK *tmpCounter;
00190
00191 tmpCounter = get_struct(theEnv,loopCounterStack);
00192 tmpCounter->loopCounter = 0L;
00193 tmpCounter->nxt = ProcedureFunctionData(theEnv)->LoopCounterStack;
00194 ProcedureFunctionData(theEnv)->LoopCounterStack = tmpCounter;
00195 if (EnvArgTypeCheck(theEnv,"loop-for-count",1,INTEGER,&arg_ptr) == FALSE)
00196 {
00197 loopResult->type = SYMBOL;
00198 loopResult->value = EnvFalseSymbol(theEnv);
00199 ProcedureFunctionData(theEnv)->LoopCounterStack = tmpCounter->nxt;
00200 rtn_struct(theEnv,loopCounterStack,tmpCounter);
00201 return;
00202 }
00203 tmpCounter->loopCounter = DOToLong(arg_ptr);
00204 if (EnvArgTypeCheck(theEnv,"loop-for-count",2,INTEGER,&arg_ptr) == FALSE)
00205 {
00206 loopResult->type = SYMBOL;
00207 loopResult->value = EnvFalseSymbol(theEnv);
00208 ProcedureFunctionData(theEnv)->LoopCounterStack = tmpCounter->nxt;
00209 rtn_struct(theEnv,loopCounterStack,tmpCounter);
00210 return;
00211 }
00212 iterationEnd = DOToLong(arg_ptr);
00213 while ((tmpCounter->loopCounter <= iterationEnd) &&
00214 (EvaluationData(theEnv)->HaltExecution != TRUE))
00215 {
00216 if ((ProcedureFunctionData(theEnv)->BreakFlag == TRUE) || (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE))
00217 break;
00218 EvaluationData(theEnv)->CurrentEvaluationDepth++;
00219 EnvRtnUnknown(theEnv,3,&arg_ptr);
00220 EvaluationData(theEnv)->CurrentEvaluationDepth--;
00221 if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
00222 { PropagateReturnValue(theEnv,&arg_ptr); }
00223 PeriodicCleanup(theEnv,FALSE,TRUE);
00224 if ((ProcedureFunctionData(theEnv)->BreakFlag == TRUE) || (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE))
00225 break;
00226 tmpCounter->loopCounter++;
00227 }
00228
00229 ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
00230 if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
00231 {
00232 loopResult->type = arg_ptr.type;
00233 loopResult->value = arg_ptr.value;
00234 loopResult->begin = arg_ptr.begin;
00235 loopResult->end = arg_ptr.end;
00236 }
00237 else
00238 {
00239 loopResult->type = SYMBOL;
00240 loopResult->value = EnvFalseSymbol(theEnv);
00241 }
00242 ProcedureFunctionData(theEnv)->LoopCounterStack = tmpCounter->nxt;
00243 rtn_struct(theEnv,loopCounterStack,tmpCounter);
00244 }
00245
00246
00247
00248
00249 globle long long GetLoopCount(
00250 void *theEnv)
00251 {
00252 int depth;
00253 LOOP_COUNTER_STACK *tmpCounter;
00254
00255 depth = ValueToInteger(GetFirstArgument()->value);
00256 tmpCounter = ProcedureFunctionData(theEnv)->LoopCounterStack;
00257 while (depth > 0)
00258 {
00259 tmpCounter = tmpCounter->nxt;
00260 depth--;
00261 }
00262 return(tmpCounter->loopCounter);
00263 }
00264
00265
00266
00267
00268
00269 globle void IfFunction(
00270 void *theEnv,
00271 DATA_OBJECT_PTR returnValue)
00272 {
00273 int numArgs;
00274 struct expr *theExpr;
00275
00276
00277
00278
00279
00280 if ((EvaluationData(theEnv)->CurrentExpression->argList == NULL) ||
00281 (EvaluationData(theEnv)->CurrentExpression->argList->nextArg == NULL))
00282 {
00283 EnvArgRangeCheck(theEnv,"if",2,3);
00284 returnValue->type = SYMBOL;
00285 returnValue->value = EnvFalseSymbol(theEnv);
00286 return;
00287 }
00288
00289 if (EvaluationData(theEnv)->CurrentExpression->argList->nextArg->nextArg == NULL)
00290 { numArgs = 2; }
00291 else if (EvaluationData(theEnv)->CurrentExpression->argList->nextArg->nextArg->nextArg == NULL)
00292 { numArgs = 3; }
00293 else
00294 {
00295 EnvArgRangeCheck(theEnv,"if",2,3);
00296 returnValue->type = SYMBOL;
00297 returnValue->value = EnvFalseSymbol(theEnv);
00298 return;
00299 }
00300
00301
00302
00303
00304
00305 EvaluateExpression(theEnv,EvaluationData(theEnv)->CurrentExpression->argList,returnValue);
00306
00307 if ((ProcedureFunctionData(theEnv)->BreakFlag == TRUE) || (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE))
00308 {
00309 returnValue->type = SYMBOL;
00310 returnValue->value = EnvFalseSymbol(theEnv);
00311 return;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 if ((returnValue->value == EnvFalseSymbol(theEnv)) &&
00321 (returnValue->type == SYMBOL) &&
00322 (numArgs == 3))
00323 {
00324 theExpr = EvaluationData(theEnv)->CurrentExpression->argList->nextArg->nextArg;
00325 switch (theExpr->type)
00326 {
00327 case INTEGER:
00328 case FLOAT:
00329 case SYMBOL:
00330 case STRING:
00331 #if OBJECT_SYSTEM
00332 case INSTANCE_NAME:
00333 case INSTANCE_ADDRESS:
00334 #endif
00335 case EXTERNAL_ADDRESS:
00336 returnValue->type = theExpr->type;
00337 returnValue->value = theExpr->value;
00338 break;
00339
00340 default:
00341 EvaluateExpression(theEnv,theExpr,returnValue);
00342 break;
00343 }
00344 return;
00345 }
00346
00347
00348
00349
00350
00351
00352 else if ((returnValue->value != EnvFalseSymbol(theEnv)) ||
00353 (returnValue->type != SYMBOL))
00354 {
00355 theExpr = EvaluationData(theEnv)->CurrentExpression->argList->nextArg;
00356 switch (theExpr->type)
00357 {
00358 case INTEGER:
00359 case FLOAT:
00360 case SYMBOL:
00361 case STRING:
00362 #if OBJECT_SYSTEM
00363 case INSTANCE_NAME:
00364 case INSTANCE_ADDRESS:
00365 #endif
00366 case EXTERNAL_ADDRESS:
00367 returnValue->type = theExpr->type;
00368 returnValue->value = theExpr->value;
00369 break;
00370
00371 default:
00372 EvaluateExpression(theEnv,theExpr,returnValue);
00373 break;
00374 }
00375 return;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 returnValue->type = SYMBOL;
00385 returnValue->value = EnvFalseSymbol(theEnv);
00386 return;
00387 }
00388
00389
00390
00391
00392
00393 globle void BindFunction(
00394 void *theEnv,
00395 DATA_OBJECT_PTR returnValue)
00396 {
00397 DATA_OBJECT *theBind, *lastBind;
00398 int found = FALSE,
00399 unbindVar = FALSE;
00400 SYMBOL_HN *variableName = NULL;
00401 #if DEFGLOBAL_CONSTRUCT
00402 struct defglobal *theGlobal = NULL;
00403 #endif
00404
00405
00406
00407
00408
00409 #if DEFGLOBAL_CONSTRUCT
00410 if (GetFirstArgument()->type == DEFGLOBAL_PTR)
00411 { theGlobal = (struct defglobal *) GetFirstArgument()->value; }
00412 else
00413 #endif
00414 {
00415 EvaluateExpression(theEnv,GetFirstArgument(),returnValue);
00416 variableName = (SYMBOL_HN *) DOPToPointer(returnValue);
00417 }
00418
00419
00420
00421
00422
00423 if (GetFirstArgument()->nextArg == NULL)
00424 { unbindVar = TRUE; }
00425 else if (GetFirstArgument()->nextArg->nextArg == NULL)
00426 { EvaluateExpression(theEnv,GetFirstArgument()->nextArg,returnValue); }
00427 else
00428 { StoreInMultifield(theEnv,returnValue,GetFirstArgument()->nextArg,TRUE); }
00429
00430
00431
00432
00433
00434 #if DEFGLOBAL_CONSTRUCT
00435 if (theGlobal != NULL)
00436 {
00437 QSetDefglobalValue(theEnv,theGlobal,returnValue,unbindVar);
00438 return;
00439 }
00440 #endif
00441
00442
00443
00444
00445
00446 theBind = ProcedureFunctionData(theEnv)->BindList;
00447 lastBind = NULL;
00448
00449 while ((theBind != NULL) && (found == FALSE))
00450 {
00451 if (theBind->supplementalInfo == (void *) variableName)
00452 { found = TRUE; }
00453 else
00454 {
00455 lastBind = theBind;
00456 theBind = theBind->next;
00457 }
00458 }
00459
00460
00461
00462
00463
00464
00465
00466 if (found == FALSE)
00467 {
00468 if (unbindVar == FALSE)
00469 {
00470 theBind = get_struct(theEnv,dataObject);
00471 theBind->supplementalInfo = (void *) variableName;
00472 IncrementSymbolCount(variableName);
00473 theBind->next = NULL;
00474 if (lastBind == NULL)
00475 { ProcedureFunctionData(theEnv)->BindList = theBind; }
00476 else
00477 { lastBind->next = theBind; }
00478 }
00479 else
00480 {
00481 returnValue->type = SYMBOL;
00482 returnValue->value = EnvFalseSymbol(theEnv);
00483 return;
00484 }
00485 }
00486 else
00487 { ValueDeinstall(theEnv,theBind); }
00488
00489
00490
00491
00492
00493 if (unbindVar == FALSE)
00494 {
00495 theBind->type = returnValue->type;
00496 theBind->value = returnValue->value;
00497 theBind->begin = returnValue->begin;
00498 theBind->end = returnValue->end;
00499 ValueInstall(theEnv,returnValue);
00500 }
00501 else
00502 {
00503 if (lastBind == NULL) ProcedureFunctionData(theEnv)->BindList = theBind->next;
00504 else lastBind->next = theBind->next;
00505 DecrementSymbolCount(theEnv,(struct symbolHashNode *) theBind->supplementalInfo);
00506 rtn_struct(theEnv,dataObject,theBind);
00507 returnValue->type = SYMBOL;
00508 returnValue->value = EnvFalseSymbol(theEnv);
00509 }
00510 }
00511
00512
00513
00514
00515
00516 globle intBool GetBoundVariable(
00517 void *theEnv,
00518 DATA_OBJECT_PTR vPtr,
00519 SYMBOL_HN *varName)
00520 {
00521 DATA_OBJECT_PTR bindPtr;
00522
00523 for (bindPtr = ProcedureFunctionData(theEnv)->BindList; bindPtr != NULL; bindPtr = bindPtr->next)
00524 {
00525 if (bindPtr->supplementalInfo == (void *) varName)
00526 {
00527 vPtr->type = bindPtr->type;
00528 vPtr->value = bindPtr->value;
00529 vPtr->begin = bindPtr->begin;
00530 vPtr->end = bindPtr->end;
00531 return(TRUE);
00532 }
00533 }
00534
00535 return(FALSE);
00536 }
00537
00538
00539
00540
00541
00542 globle void FlushBindList(
00543 void *theEnv)
00544 {
00545 ReturnValues(theEnv,ProcedureFunctionData(theEnv)->BindList,TRUE);
00546 ProcedureFunctionData(theEnv)->BindList = NULL;
00547 }
00548
00549
00550
00551
00552
00553 globle void PrognFunction(
00554 void *theEnv,
00555 DATA_OBJECT_PTR returnValue)
00556 {
00557 struct expr *argPtr;
00558
00559 argPtr = EvaluationData(theEnv)->CurrentExpression->argList;
00560
00561 if (argPtr == NULL)
00562 {
00563 returnValue->type = SYMBOL;
00564 returnValue->value = EnvFalseSymbol(theEnv);
00565 return;
00566 }
00567
00568 while ((argPtr != NULL) && (GetHaltExecution(theEnv) != TRUE))
00569 {
00570 EvaluateExpression(theEnv,argPtr,returnValue);
00571
00572 if ((ProcedureFunctionData(theEnv)->BreakFlag == TRUE) || (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE))
00573 break;
00574 argPtr = argPtr->nextArg;
00575 }
00576
00577 if (GetHaltExecution(theEnv) == TRUE)
00578 {
00579 returnValue->type = SYMBOL;
00580 returnValue->value = EnvFalseSymbol(theEnv);
00581 return;
00582 }
00583
00584 return;
00585 }
00586
00587
00588
00589
00590 globle void ReturnFunction(
00591 void *theEnv,
00592 DATA_OBJECT_PTR result)
00593 {
00594 if (EnvRtnArgCount(theEnv) == 0)
00595 {
00596 result->type = RVOID;
00597 result->value = EnvFalseSymbol(theEnv);
00598 }
00599 else
00600 EnvRtnUnknown(theEnv,1,result);
00601 ProcedureFunctionData(theEnv)->ReturnFlag = TRUE;
00602 }
00603
00604
00605
00606
00607 globle void BreakFunction(
00608 void *theEnv)
00609 {
00610 ProcedureFunctionData(theEnv)->BreakFlag = TRUE;
00611 }
00612
00613
00614
00615
00616 globle void SwitchFunction(
00617 void *theEnv,
00618 DATA_OBJECT_PTR result)
00619 {
00620 DATA_OBJECT switch_val,case_val;
00621 EXPRESSION *theExp;
00622
00623 result->type = SYMBOL;
00624 result->value = EnvFalseSymbol(theEnv);
00625
00626
00627
00628
00629 EvaluateExpression(theEnv,GetFirstArgument(),&switch_val);
00630 if (EvaluationData(theEnv)->EvaluationError)
00631 return;
00632 for (theExp = GetFirstArgument()->nextArg ; theExp != NULL ; theExp = theExp->nextArg->nextArg)
00633 {
00634
00635
00636
00637 if (theExp->type == RVOID)
00638 {
00639 EvaluateExpression(theEnv,theExp->nextArg,result);
00640 return;
00641 }
00642
00643
00644
00645
00646 EvaluateExpression(theEnv,theExp,&case_val);
00647 if (EvaluationData(theEnv)->EvaluationError)
00648 return;
00649 if (switch_val.type == case_val.type)
00650 {
00651 if ((case_val.type == MULTIFIELD) ? MultifieldDOsEqual(&switch_val,&case_val) :
00652 (switch_val.value == case_val.value))
00653 {
00654 EvaluateExpression(theEnv,theExp->nextArg,result);
00655 return;
00656 }
00657 }
00658 }
00659 }
00660
00661
00662
00663
00664