📄 insfile.c
字号:
2) A flag indicating whether to
save local (current module only)
or visible instances
LOCAL_SAVE or VISIBLE_SAVE
3) A list of expressions containing
the names of classes for which
instances are to be saved
4) A flag indicating if the subclasses
of specified classes shoudl also
be processed
RETURNS : The number of instances saved
SIDE EFFECTS : Instances saved to file
NOTES : None
*******************************************************/
globle long EnvSaveInstances(
void *theEnv,
char *file,
int saveCode,
EXPRESSION *classExpressionList,
intBool inheritFlag)
{
FILE *sfile = NULL;
int oldPEC,oldATS,oldIAN;
DATA_OBJECT *classList;
long instanceCount;
classList = ProcessSaveClassList(theEnv,"save-instances",classExpressionList,
saveCode,inheritFlag);
if ((classList == NULL) && (classExpressionList != NULL))
return(0L);
SaveOrMarkInstances(theEnv,(void *) sfile,saveCode,classList,
inheritFlag,TRUE,NULL);
if ((sfile = GenOpen(theEnv,file,"w")) == NULL)
{
OpenErrorMessage(theEnv,"save-instances",file);
ReturnSaveClassList(theEnv,classList);
SetEvaluationError(theEnv,TRUE);
return(0L);
}
oldPEC = PrintUtilityData(theEnv)->PreserveEscapedCharacters;
PrintUtilityData(theEnv)->PreserveEscapedCharacters = TRUE;
oldATS = PrintUtilityData(theEnv)->AddressesToStrings;
PrintUtilityData(theEnv)->AddressesToStrings = TRUE;
oldIAN = PrintUtilityData(theEnv)->InstanceAddressesToNames;
PrintUtilityData(theEnv)->InstanceAddressesToNames = TRUE;
SetFastSave(theEnv,sfile);
instanceCount = SaveOrMarkInstances(theEnv,(void *) sfile,saveCode,classList,
inheritFlag,TRUE,SaveSingleInstanceText);
GenClose(theEnv,sfile);
SetFastSave(theEnv,NULL);
PrintUtilityData(theEnv)->PreserveEscapedCharacters = oldPEC;
PrintUtilityData(theEnv)->AddressesToStrings = oldATS;
PrintUtilityData(theEnv)->InstanceAddressesToNames = oldIAN;
ReturnSaveClassList(theEnv,classList);
return(instanceCount);
}
#if BSAVE_INSTANCES
/****************************************************************************
NAME : BinarySaveInstancesCommand
DESCRIPTION : H/L interface for saving
current instances to a binary file
INPUTS : None
RETURNS : The number of instances saved
SIDE EFFECTS : Instances saved (in binary format) to named file
NOTES : H/L Syntax :
(bsave-instances <file> [local|visible [[inherit] <class>+]])
*****************************************************************************/
globle long BinarySaveInstancesCommand(
void *theEnv)
{
return(InstancesSaveCommandParser(theEnv,"bsave-instances",EnvBinarySaveInstances));
}
/*******************************************************
NAME : EnvBinarySaveInstances
DESCRIPTION : Saves current instances to binary file
INPUTS : 1) The name of the output file
2) A flag indicating whether to
save local (current module only)
or visible instances
LOCAL_SAVE or VISIBLE_SAVE
3) A list of expressions containing
the names of classes for which
instances are to be saved
4) A flag indicating if the subclasses
of specified classes shoudl also
be processed
RETURNS : The number of instances saved
SIDE EFFECTS : Instances saved to file
NOTES : None
*******************************************************/
globle long EnvBinarySaveInstances(
void *theEnv,
char *file,
int saveCode,
EXPRESSION *classExpressionList,
intBool inheritFlag)
{
DATA_OBJECT *classList;
FILE *bsaveFP;
long instanceCount;
classList = ProcessSaveClassList(theEnv,"bsave-instances",classExpressionList,
saveCode,inheritFlag);
if ((classList == NULL) && (classExpressionList != NULL))
return(0L);
InstanceFileData(theEnv)->BinaryInstanceFileSize = 0L;
InitAtomicValueNeededFlags(theEnv);
instanceCount = SaveOrMarkInstances(theEnv,NULL,saveCode,classList,inheritFlag,
FALSE,MarkSingleInstance);
if ((bsaveFP = GenOpen(theEnv,file,"wb")) == NULL)
{
OpenErrorMessage(theEnv,"bsave-instances",file);
ReturnSaveClassList(theEnv,classList);
SetEvaluationError(theEnv,TRUE);
return(0L);
}
WriteBinaryHeader(theEnv,bsaveFP);
WriteNeededAtomicValues(theEnv,bsaveFP);
fwrite((void *) &InstanceFileData(theEnv)->BinaryInstanceFileSize,sizeof(unsigned long),1,bsaveFP);
fwrite((void *) &instanceCount,sizeof(long),1,bsaveFP);
SetAtomicValueIndices(theEnv,FALSE);
SaveOrMarkInstances(theEnv,(void *) bsaveFP,saveCode,classList,
inheritFlag,FALSE,SaveSingleInstanceBinary);
RestoreAtomicValueBuckets(theEnv);
GenClose(theEnv,bsaveFP);
ReturnSaveClassList(theEnv,classList);
return(instanceCount);
}
#endif
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/******************************************************
NAME : InstancesSaveCommandParser
DESCRIPTION : Argument parser for save-instances
and bsave-instances
INPUTS : 1) The name of the calling function
2) A pointer to the support
function to call for the save/bsave
RETURNS : The number of instances saved
SIDE EFFECTS : Instances saved/bsaved
NOTES : None
******************************************************/
static long InstancesSaveCommandParser(
void *theEnv,
char *functionName,
long (*saveFunction)(void *,char *,int,EXPRESSION *,intBool))
{
char *fileFound;
DATA_OBJECT temp;
int argCount,saveCode = LOCAL_SAVE;
EXPRESSION *classList = NULL;
intBool inheritFlag = FALSE;
if (EnvArgTypeCheck(theEnv,functionName,1,SYMBOL_OR_STRING,&temp) == FALSE)
return(0L);
fileFound = DOToString(temp);
argCount = EnvRtnArgCount(theEnv);
if (argCount > 1)
{
if (EnvArgTypeCheck(theEnv,functionName,2,SYMBOL,&temp) == FALSE)
{
ExpectedTypeError1(theEnv,functionName,2,"symbol \"local\" or \"visible\"");
SetEvaluationError(theEnv,TRUE);
return(0L);
}
if (strcmp(DOToString(temp),"local") == 0)
saveCode = LOCAL_SAVE;
else if (strcmp(DOToString(temp),"visible") == 0)
saveCode = VISIBLE_SAVE;
else
{
ExpectedTypeError1(theEnv,functionName,2,"symbol \"local\" or \"visible\"");
SetEvaluationError(theEnv,TRUE);
return(0L);
}
classList = GetFirstArgument()->nextArg->nextArg;
/* ===========================
Check for "inherit" keyword
Must be at least one class
name following
=========================== */
if ((classList != NULL) ? (classList->nextArg != NULL) : FALSE)
{
if ((classList->type != SYMBOL) ? FALSE :
(strcmp(ValueToString(classList->value),"inherit") == 0))
{
inheritFlag = TRUE;
classList = classList->nextArg;
}
}
}
return((*saveFunction)(theEnv,fileFound,saveCode,classList,inheritFlag));
}
/****************************************************
NAME : ProcessSaveClassList
DESCRIPTION : Evaluates a list of class name
expressions and stores them in a
data object list
INPUTS : 1) The name of the calling function
2) The class expression list
3) A flag indicating if only local
or all visible instances are
being saved
4) A flag indicating if inheritance
relationships should be checked
between classes
RETURNS : The evaluated class pointer data
objects - NULL on errors
SIDE EFFECTS : Data objects allocated and
classes validated
NOTES : None
****************************************************/
static DATA_OBJECT *ProcessSaveClassList(
void *theEnv,
char *functionName,
EXPRESSION *classExps,
int saveCode,
intBool inheritFlag)
{
DATA_OBJECT *head = NULL,*prv,*newItem,tmp;
DEFCLASS *theDefclass;
struct defmodule *currentModule;
int argIndex = inheritFlag ? 4 : 3;
currentModule = ((struct defmodule *) EnvGetCurrentModule(theEnv));
while (classExps != NULL)
{
if (EvaluateExpression(theEnv,classExps,&tmp))
goto ProcessClassListError;
if (tmp.type != SYMBOL)
goto ProcessClassListError;
if (saveCode == LOCAL_SAVE)
theDefclass = LookupDefclassAnywhere(theEnv,currentModule,DOToString(tmp));
else
theDefclass = LookupDefclassInScope(theEnv,DOToString(tmp));
if (theDefclass == NULL)
goto ProcessClassListError;
else if (theDefclass->abstract && (inheritFlag == FALSE))
goto ProcessClassListError;
prv = newItem = head;
while (newItem != NULL)
{
if (newItem->value == (void *) theDefclass)
goto ProcessClassListError;
else if (inheritFlag)
{
if (HasSuperclass((DEFCLASS *) newItem->value,theDefclass) ||
HasSuperclass(theDefclass,(DEFCLASS *) newItem->value))
goto ProcessClassListError;
}
prv = newItem;
newItem = newItem->next;
}
newItem = get_struct(theEnv,dataObject);
newItem->type = DEFCLASS_PTR;
newItem->value = (void *) theDefclass;
newItem->next = NULL;
if (prv == NULL)
head = newItem;
else
prv->next = newItem;
argIndex++;
classExps = classExps->nextArg;
}
return(head);
ProcessClassListError:
ExpectedTypeError1(theEnv,functionName,argIndex,
(char *) (inheritFlag ? "valid class name" : "valid concrete class name"));
ReturnSaveClassList(theEnv,head);
SetEvaluationError(theEnv,TRUE);
return(NULL);
}
/****************************************************
NAME : ReturnSaveClassList
DESCRIPTION : Deallocates the class data object
list created by ProcessSaveClassList
INPUTS : The class data object list
RETURNS : Nothing useful
SIDE EFFECTS : Class data object returned
NOTES : None
****************************************************/
static void ReturnSaveClassList(
void *theEnv,
DATA_OBJECT *classList)
{
DATA_OBJECT *tmp;
while (classList != NULL)
{
tmp = classList;
classList = classList->next;
rtn_struct(theEnv,dataObject,tmp);
}
}
/***************************************************
NAME : SaveOrMarkInstances
DESCRIPTION : Iterates through all specified
instances either marking needed
atoms or writing instances in
binary/text format
INPUTS : 1) NULL (for marking),
logical name (for text saves)
file pointer (for binary saves)
2) A cope flag indicating LOCAL
or VISIBLE saves only
3) A list of data objects
containing the names of classes
of instances to be saved
4) A flag indicating whether to
include subclasses of arg #3
5) A flag indicating if the
iteration can be interrupted
or not
6) The access function to mark
or save an instance (can be NULL
if only counting instances)
RETURNS : The number of instances saved
SIDE EFFECTS : Instances amrked or saved
NOTES : None
***************************************************/
static long SaveOrMarkInstances(
void *theEnv,
void *theOutput,
int saveCode,
DATA_OBJECT *classList,
intBool inheritFlag,
intBool interruptOK,
void (*saveInstanceFunc)(void *,void *,INSTANCE_TYPE *))
{
struct defmodule *currentModule;
int traversalID;
DATA_OBJECT *tmp;
INSTANCE_TYPE *ins;
long instanceCount = 0L;
currentModule = ((struct defmodule *) EnvGetCurrentModule(theEnv));
if (classList != NULL)
{
traversalID = GetTraversalID(theEnv);
if (traversalID != -1)
{
for (tmp = classList ;
(! ((tmp == NULL) || (EvaluationData(theEnv)->HaltExecution && interruptOK))) ;
tmp = tmp->next)
instanceCount += SaveOrMarkInstancesOfClass(theEnv,theOutput,currentModule,saveCode,
(DEFCLASS *) tmp->value,inheritFlag,
traversalID,saveInstanceFunc);
ReleaseTraversalID(theEnv);
}
}
else
{
for (ins = (INSTANCE_TYPE *) GetNextInstanceInScope(theEnv,NULL) ;
(ins != NULL) && (EvaluationData(theEnv)->HaltExecution != TRUE) ;
ins = (INSTANCE_TYPE *) GetNextInstanceInScope(theEnv,(void *) ins))
{
if ((saveCode == VISIBLE_SAVE) ? TRUE :
(ins->cls->header.whichModule->theModule == currentModule))
{
if (saveInstanceFunc != NULL)
(*saveInstanceFunc)(theEnv,theOutput,ins);
instanceCount++;
}
}
}
return(instanceCount);
}
/***************************************************
NAME : SaveOrMarkInstancesOfClass
DESCRIPTION : Saves off the direct (and indirect)
instance of the specified class
INPUTS : 1) The logical name of the output
(or file pointer for binary
output)
2) The current module
3) A flag indicating local
or visible saves
4) The defclass
5) A flag indicating whether to
save subclass instances or not
6) A traversal id for marking
visited classes
7) A pointer to the instance
manipulation function to call
(can be NULL for only counting
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -