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 #define _EXTNFUNC_SOURCE_
00030
00031 #include "setup.h"
00032
00033 #include <ctype.h>
00034 #include <stdlib.h>
00035
00036 #include "constant.h"
00037 #include "envrnmnt.h"
00038 #include "router.h"
00039 #include "memalloc.h"
00040 #include "evaluatn.h"
00041
00042 #include "extnfunc.h"
00043
00044
00045
00046
00047
00048 static void AddHashFunction(void *,struct FunctionDefinition *);
00049 static void InitializeFunctionHashTable(void *);
00050 static void DeallocateExternalFunctionData(void *);
00051 #if (! RUN_TIME)
00052 static int RemoveHashFunction(void *,struct FunctionDefinition *);
00053 #endif
00054
00055
00056
00057
00058
00059 globle void InitializeExternalFunctionData(
00060 void *theEnv)
00061 {
00062 AllocateEnvironmentData(theEnv,EXTERNAL_FUNCTION_DATA,sizeof(struct externalFunctionData),DeallocateExternalFunctionData);
00063 }
00064
00065
00066
00067
00068
00069 static void DeallocateExternalFunctionData(
00070 void *theEnv)
00071 {
00072 struct FunctionHash *fhPtr, *nextFHPtr;
00073 int i;
00074
00075 #if ! RUN_TIME
00076 struct FunctionDefinition *tmpPtr, *nextPtr;
00077
00078 tmpPtr = ExternalFunctionData(theEnv)->ListOfFunctions;
00079 while (tmpPtr != NULL)
00080 {
00081 nextPtr = tmpPtr->next;
00082 rtn_struct(theEnv,FunctionDefinition,tmpPtr);
00083 tmpPtr = nextPtr;
00084 }
00085 #endif
00086
00087 if (ExternalFunctionData(theEnv)->FunctionHashtable == NULL)
00088 { return; }
00089
00090 for (i = 0; i < SIZE_FUNCTION_HASH; i++)
00091 {
00092 fhPtr = ExternalFunctionData(theEnv)->FunctionHashtable[i];
00093 while (fhPtr != NULL)
00094 {
00095 nextFHPtr = fhPtr->next;
00096 rtn_struct(theEnv,FunctionHash,fhPtr);
00097 fhPtr = nextFHPtr;
00098 }
00099 }
00100
00101 genfree(theEnv,ExternalFunctionData(theEnv)->FunctionHashtable,
00102 (int) sizeof (struct FunctionHash *) * SIZE_FUNCTION_HASH);
00103 }
00104
00105 #if (! RUN_TIME)
00106
00107
00108
00109
00110
00111 #if ALLOW_ENVIRONMENT_GLOBALS
00112 globle int DefineFunction(
00113 char *name,
00114 int returnType,
00115 int (*pointer)(void),
00116 char *actualName)
00117 {
00118 void *theEnv;
00119
00120 theEnv = GetCurrentEnvironment();
00121
00122 return(DefineFunction3(theEnv,name,returnType,
00123 (int (*)(void *)) pointer,
00124 actualName,NULL,FALSE,NULL));
00125 }
00126 #endif
00127
00128
00129
00130
00131
00132 globle int EnvDefineFunction(
00133 void *theEnv,
00134 char *name,
00135 int returnType,
00136 int (*pointer)(void *),
00137 char *actualName)
00138 {
00139 return(DefineFunction3(theEnv,name,returnType,pointer,actualName,NULL,TRUE,NULL));
00140 }
00141
00142
00143
00144
00145
00146 globle int EnvDefineFunctionWithContext(
00147 void *theEnv,
00148 char *name,
00149 int returnType,
00150 int (*pointer)(void *),
00151 char *actualName,
00152 void *context)
00153 {
00154 return(DefineFunction3(theEnv,name,returnType,pointer,actualName,NULL,TRUE,context));
00155 }
00156
00157
00158
00159
00160
00161 #if ALLOW_ENVIRONMENT_GLOBALS
00162 globle int DefineFunction2(
00163 char *name,
00164 int returnType,
00165 int (*pointer)(void),
00166 char *actualName,
00167 char *restrictions)
00168 {
00169 void *theEnv;
00170
00171 theEnv = GetCurrentEnvironment();
00172
00173 return(DefineFunction3(theEnv,name,returnType,
00174 (int (*)(void *)) pointer,
00175 actualName,restrictions,FALSE,NULL));
00176 }
00177 #endif
00178
00179
00180
00181
00182
00183 globle int EnvDefineFunction2(
00184 void *theEnv,
00185 char *name,
00186 int returnType,
00187 int (*pointer)(void *),
00188 char *actualName,
00189 char *restrictions)
00190 {
00191 return(DefineFunction3(theEnv,name,returnType,pointer,actualName,restrictions,TRUE,NULL));
00192 }
00193
00194
00195
00196
00197
00198 globle int EnvDefineFunction2WithContext(
00199 void *theEnv,
00200 char *name,
00201 int returnType,
00202 int (*pointer)(void *),
00203 char *actualName,
00204 char *restrictions,
00205 void *context)
00206 {
00207 return(DefineFunction3(theEnv,name,returnType,pointer,actualName,restrictions,TRUE,context));
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 globle int DefineFunction3(
00236 void *theEnv,
00237 char *name,
00238 int returnType,
00239 int (*pointer)(void *),
00240 char *actualName,
00241 char *restrictions,
00242 intBool environmentAware,
00243 void *context)
00244 {
00245 struct FunctionDefinition *newFunction;
00246
00247 if ( (returnType != 'a') &&
00248 (returnType != 'b') &&
00249 (returnType != 'c') &&
00250 (returnType != 'd') &&
00251 (returnType != 'f') &&
00252 (returnType != 'g') &&
00253 (returnType != 'i') &&
00254 (returnType != 'j') &&
00255 (returnType != 'k') &&
00256 (returnType != 'l') &&
00257 (returnType != 'm') &&
00258 (returnType != 'n') &&
00259 #if OBJECT_SYSTEM
00260 (returnType != 'o') &&
00261 #endif
00262 (returnType != 's') &&
00263 (returnType != 'u') &&
00264 (returnType != 'v') &&
00265 #if OBJECT_SYSTEM
00266 (returnType != 'x') &&
00267 #endif
00268 (returnType != 'w') )
00269 { return(0); }
00270
00271 newFunction = FindFunction(theEnv,name);
00272 if (newFunction == NULL)
00273 {
00274 newFunction = get_struct(theEnv,FunctionDefinition);
00275 newFunction->callFunctionName = (SYMBOL_HN *) EnvAddSymbol(theEnv,name);
00276 IncrementSymbolCount(newFunction->callFunctionName);
00277 newFunction->next = GetFunctionList(theEnv);
00278 ExternalFunctionData(theEnv)->ListOfFunctions = newFunction;
00279 AddHashFunction(theEnv,newFunction);
00280 }
00281
00282 newFunction->returnValueType = (char) returnType;
00283 newFunction->functionPointer = (int (*)(void)) pointer;
00284 newFunction->actualFunctionName = actualName;
00285 if (restrictions != NULL)
00286 {
00287 if (((int) (strlen(restrictions)) < 2) ? TRUE :
00288 ((! isdigit(restrictions[0]) && (restrictions[0] != '*')) ||
00289 (! isdigit(restrictions[1]) && (restrictions[1] != '*'))))
00290 restrictions = NULL;
00291 }
00292 newFunction->restrictions = restrictions;
00293 newFunction->parser = NULL;
00294 newFunction->overloadable = TRUE;
00295 newFunction->sequenceuseok = TRUE;
00296 newFunction->environmentAware = (short) environmentAware;
00297 newFunction->usrData = NULL;
00298 newFunction->context = context;
00299
00300 return(1);
00301 }
00302
00303
00304
00305
00306
00307 globle int UndefineFunction(
00308 void *theEnv,
00309 char *functionName)
00310 {
00311 SYMBOL_HN *findValue;
00312 struct FunctionDefinition *fPtr, *lastPtr = NULL;
00313
00314 findValue = (SYMBOL_HN *) FindSymbolHN(theEnv,functionName);
00315
00316 for (fPtr = ExternalFunctionData(theEnv)->ListOfFunctions;
00317 fPtr != NULL;
00318 fPtr = fPtr->next)
00319 {
00320 if (fPtr->callFunctionName == findValue)
00321 {
00322 DecrementSymbolCount(theEnv,fPtr->callFunctionName);
00323 RemoveHashFunction(theEnv,fPtr);
00324
00325 if (lastPtr == NULL)
00326 { ExternalFunctionData(theEnv)->ListOfFunctions = fPtr->next; }
00327 else
00328 { lastPtr->next = fPtr->next; }
00329
00330 ClearUserDataList(theEnv,fPtr->usrData);
00331 rtn_struct(theEnv,FunctionDefinition,fPtr);
00332 return(TRUE);
00333 }
00334
00335 lastPtr = fPtr;
00336 }
00337
00338 return(FALSE);
00339 }
00340
00341
00342
00343
00344
00345 static int RemoveHashFunction(
00346 void *theEnv,
00347 struct FunctionDefinition *fdPtr)
00348 {
00349 struct FunctionHash *fhPtr, *lastPtr = NULL;
00350 unsigned hashValue;
00351
00352 hashValue = HashSymbol(ValueToString(fdPtr->callFunctionName),SIZE_FUNCTION_HASH);
00353
00354 for (fhPtr = ExternalFunctionData(theEnv)->FunctionHashtable[hashValue];
00355 fhPtr != NULL;
00356 fhPtr = fhPtr->next)
00357 {
00358 if (fhPtr->fdPtr == fdPtr)
00359 {
00360 if (lastPtr == NULL)
00361 { ExternalFunctionData(theEnv)->FunctionHashtable[hashValue] = fhPtr->next; }
00362 else
00363 { lastPtr->next = fhPtr->next; }
00364
00365 rtn_struct(theEnv,FunctionHash,fhPtr);
00366 return(TRUE);
00367 }
00368
00369 lastPtr = fhPtr;
00370 }
00371
00372 return(FALSE);
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 globle int AddFunctionParser(
00385 void *theEnv,
00386 char *functionName,
00387 struct expr *(*fpPtr)(void *,struct expr *,char *))
00388 {
00389 struct FunctionDefinition *fdPtr;
00390
00391 fdPtr = FindFunction(theEnv,functionName);
00392 if (fdPtr == NULL)
00393 {
00394 EnvPrintRouter(theEnv,WERROR,"Function parsers can only be added for existing functions.\n");
00395 return(0);
00396 }
00397 fdPtr->restrictions = NULL;
00398 fdPtr->parser = fpPtr;
00399 fdPtr->overloadable = FALSE;
00400
00401 return(1);
00402 }
00403
00404
00405
00406
00407
00408 globle int RemoveFunctionParser(
00409 void *theEnv,
00410 char *functionName)
00411 {
00412 struct FunctionDefinition *fdPtr;
00413
00414 fdPtr = FindFunction(theEnv,functionName);
00415 if (fdPtr == NULL)
00416 {
00417 EnvPrintRouter(theEnv,WERROR,"Function parsers can only be removed from existing functions.\n");
00418 return(0);
00419 }
00420
00421 fdPtr->parser = NULL;
00422
00423 return(1);
00424 }
00425
00426
00427
00428
00429
00430 globle int FuncSeqOvlFlags(
00431 void *theEnv,
00432 char *functionName,
00433 int seqp,
00434 int ovlp)
00435 {
00436 struct FunctionDefinition *fdPtr;
00437
00438 fdPtr = FindFunction(theEnv,functionName);
00439 if (fdPtr == NULL)
00440 {
00441 EnvPrintRouter(theEnv,WERROR,"Only existing functions can be marked as using sequence expansion arguments/overloadable or not.\n");
00442 return(FALSE);
00443 }
00444 fdPtr->sequenceuseok = (short) (seqp ? TRUE : FALSE);
00445 fdPtr->overloadable = (short) (ovlp ? TRUE : FALSE);
00446 return(TRUE);
00447 }
00448
00449 #endif
00450
00451
00452
00453
00454
00455 globle char *GetArgumentTypeName(
00456 int theRestriction)
00457 {
00458 switch ((char) theRestriction)
00459 {
00460 case 'a':
00461 return("external address");
00462
00463 case 'e':
00464 return("instance address, instance name, or symbol");
00465
00466 case 'd':
00467 case 'f':
00468 return("float");
00469
00470 case 'g':
00471 return("integer, float, or symbol");
00472
00473 case 'h':
00474 return("instance address, instance name, fact address, integer, or symbol");
00475
00476 case 'j':
00477 return("symbol, string, or instance name");
00478
00479 case 'k':
00480 return("symbol or string");
00481
00482 case 'i':
00483 case 'l':
00484 return("integer");
00485
00486 case 'm':
00487 return("multifield");
00488
00489 case 'n':
00490 return("integer or float");
00491
00492 case 'o':
00493 return("instance name");
00494
00495 case 'p':
00496 return("instance name or symbol");
00497
00498 case 'q':
00499 return("multifield, symbol, or string");
00500
00501 case 's':
00502 return("string");
00503
00504 case 'w':
00505 return("symbol");
00506
00507 case 'x':
00508 return("instance address");
00509
00510 case 'y':
00511 return("fact-address");
00512
00513 case 'z':
00514 return("fact-address, integer, or symbol");
00515
00516 case 'u':
00517 return("non-void return value");
00518 }
00519
00520 return("unknown argument type");
00521 }
00522
00523
00524
00525
00526
00527 globle int GetNthRestriction(
00528 struct FunctionDefinition *theFunction,
00529 int position)
00530 {
00531 int defaultRestriction = (int) 'u';
00532 size_t theLength;
00533 int i = 2;
00534
00535
00536
00537
00538
00539
00540
00541 if (theFunction == NULL) return(defaultRestriction);
00542
00543 if (theFunction->restrictions == NULL) return(defaultRestriction);
00544
00545
00546
00547
00548
00549
00550
00551 theLength = strlen(theFunction->restrictions);
00552
00553 if (theLength < 3) return(defaultRestriction);
00554
00555
00556
00557
00558
00559 defaultRestriction = (int) theFunction->restrictions[i];
00560
00561 if (defaultRestriction == '*') defaultRestriction = (int) 'u';
00562
00563
00564
00565
00566
00567
00568 if (theLength < (size_t) (position + 3)) return(defaultRestriction);
00569
00570
00571
00572
00573
00574 return((int) theFunction->restrictions[position + 2]);
00575 }
00576
00577
00578
00579
00580 globle struct FunctionDefinition *GetFunctionList(
00581 void *theEnv)
00582 {
00583 return(ExternalFunctionData(theEnv)->ListOfFunctions);
00584 }
00585
00586
00587
00588
00589
00590 globle void InstallFunctionList(
00591 void *theEnv,
00592 struct FunctionDefinition *value)
00593 {
00594 int i;
00595 struct FunctionHash *fhPtr, *nextPtr;
00596
00597 if (ExternalFunctionData(theEnv)->FunctionHashtable != NULL)
00598 {
00599 for (i = 0; i < SIZE_FUNCTION_HASH; i++)
00600 {
00601 fhPtr = ExternalFunctionData(theEnv)->FunctionHashtable[i];
00602 while (fhPtr != NULL)
00603 {
00604 nextPtr = fhPtr->next;
00605 rtn_struct(theEnv,FunctionHash,fhPtr);
00606 fhPtr = nextPtr;
00607 }
00608 ExternalFunctionData(theEnv)->FunctionHashtable[i] = NULL;
00609 }
00610 }
00611
00612 ExternalFunctionData(theEnv)->ListOfFunctions = value;
00613
00614 while (value != NULL)
00615 {
00616 AddHashFunction(theEnv,value);
00617 value = value->next;
00618 }
00619 }
00620
00621
00622
00623
00624
00625
00626 globle struct FunctionDefinition *FindFunction(
00627 void *theEnv,
00628 char *functionName)
00629 {
00630 struct FunctionHash *fhPtr;
00631 unsigned hashValue;
00632 SYMBOL_HN *findValue;
00633
00634 if (ExternalFunctionData(theEnv)->FunctionHashtable == NULL) return(NULL);
00635
00636 hashValue = HashSymbol(functionName,SIZE_FUNCTION_HASH);
00637
00638 findValue = (SYMBOL_HN *) FindSymbolHN(theEnv,functionName);
00639
00640 for (fhPtr = ExternalFunctionData(theEnv)->FunctionHashtable[hashValue];
00641 fhPtr != NULL;
00642 fhPtr = fhPtr->next)
00643 {
00644 if (fhPtr->fdPtr->callFunctionName == findValue)
00645 { return(fhPtr->fdPtr); }
00646 }
00647
00648 return(NULL);
00649 }
00650
00651
00652
00653
00654
00655 static void InitializeFunctionHashTable(
00656 void *theEnv)
00657 {
00658 int i;
00659
00660 ExternalFunctionData(theEnv)->FunctionHashtable = (struct FunctionHash **)
00661 gm2(theEnv,(int) sizeof (struct FunctionHash *) *
00662 SIZE_FUNCTION_HASH);
00663
00664 for (i = 0; i < SIZE_FUNCTION_HASH; i++) ExternalFunctionData(theEnv)->FunctionHashtable[i] = NULL;
00665 }
00666
00667
00668
00669
00670 static void AddHashFunction(
00671 void *theEnv,
00672 struct FunctionDefinition *fdPtr)
00673 {
00674 struct FunctionHash *newhash, *temp;
00675 unsigned hashValue;
00676
00677 if (ExternalFunctionData(theEnv)->FunctionHashtable == NULL) InitializeFunctionHashTable(theEnv);
00678
00679 newhash = get_struct(theEnv,FunctionHash);
00680 newhash->fdPtr = fdPtr;
00681
00682 hashValue = HashSymbol(fdPtr->callFunctionName->contents,SIZE_FUNCTION_HASH);
00683
00684 temp = ExternalFunctionData(theEnv)->FunctionHashtable[hashValue];
00685 ExternalFunctionData(theEnv)->FunctionHashtable[hashValue] = newhash;
00686 newhash->next = temp;
00687 }
00688
00689
00690
00691
00692
00693 globle int GetMinimumArgs(
00694 struct FunctionDefinition *theFunction)
00695 {
00696 char theChar[2], *restrictions;
00697
00698 restrictions = theFunction->restrictions;
00699 if (restrictions == NULL) return(-1);
00700
00701 theChar[0] = restrictions[0];
00702 theChar[1] = '\0';
00703
00704 if (isdigit(theChar[0]))
00705 { return atoi(theChar); }
00706 else if (theChar[0] == '*')
00707 { return(-1); }
00708
00709 return(-1);
00710 }
00711
00712
00713
00714
00715
00716 globle int GetMaximumArgs(
00717 struct FunctionDefinition *theFunction)
00718 {
00719 char theChar[2], *restrictions;
00720
00721 restrictions = theFunction->restrictions;
00722 if (restrictions == NULL) return(-1);
00723 if (restrictions[0] == '\0') return(-1);
00724
00725 theChar[0] = restrictions[1];
00726 theChar[1] = '\0';
00727
00728 if (isdigit(theChar[0]))
00729 { return atoi(theChar); }
00730 else if (theChar[0] == '*')
00731 { return(-1); }
00732
00733 return(-1);
00734 }