globle void *FindImportedConstruct( void *theEnv, EXEC_STATUS, char *constructName, struct defmodule *matchModule, char *findName, int *count, int searchCurrent, struct defmodule *notYetDefinedInModule) { void *rv; struct moduleItem *theModuleItem; /*=============================================*/ /* Set the number of references found to zero. */ /*=============================================*/ *count = 0; /*===============================*/ /* The :: should not be included */ /* in the construct's name. */ /*===============================*/ if (FindModuleSeparator(findName)) return(NULL); /*=============================================*/ /* Remember the current module since we'll be */ /* changing it during the search and will want */ /* to restore it once the search is completed. */ /*=============================================*/ SaveCurrentModule(theEnv,execStatus); /*==========================================*/ /* Find the module related access functions */ /* for the construct type being sought. */ /*==========================================*/ if ((theModuleItem = FindModuleItem(theEnv,execStatus,constructName)) == NULL) { RestoreCurrentModule(theEnv,execStatus); return(NULL); } /*===========================================*/ /* If the construct type doesn't have a find */ /* function, then we can't look for it. */ /*===========================================*/ if (theModuleItem->findFunction == NULL) { RestoreCurrentModule(theEnv,execStatus); return(NULL); } /*==================================*/ /* Initialize the search by marking */ /* all modules as unvisited. */ /*==================================*/ MarkModulesAsUnvisited(theEnv,execStatus); /*===========================*/ /* Search for the construct. */ /*===========================*/ rv = SearchImportedConstructModules(theEnv,execStatus,(SYMBOL_HN *) EnvAddSymbol(theEnv,execStatus,constructName), matchModule,theModuleItem, (SYMBOL_HN *) EnvAddSymbol(theEnv,execStatus,findName),count, searchCurrent,notYetDefinedInModule); /*=============================*/ /* Restore the current module. */ /*=============================*/ RestoreCurrentModule(theEnv,execStatus); /*====================================*/ /* Return a pointer to the construct. */ /*====================================*/ return(rv); }
globle int EnvSave( void *theEnv, const char *fileName) { struct callFunctionItem *saveFunction; FILE *filePtr; struct defmodule *defmodulePtr; intBool updated = FALSE; intBool unvisited = TRUE; /*=====================*/ /* Open the save file. */ /*=====================*/ if ((filePtr = GenOpen(theEnv,fileName,"w")) == NULL) { return(FALSE); } /*===========================*/ /* Bypass the router system. */ /*===========================*/ SetFastSave(theEnv,filePtr); /*================================*/ /* Mark all modules as unvisited. */ /*================================*/ MarkModulesAsUnvisited(theEnv); /*===============================================*/ /* Save the constructs. Repeatedly loop over the */ /* modules until each module has been save. */ /*===============================================*/ while (unvisited) { unvisited = FALSE; updated = FALSE; for (defmodulePtr = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL); defmodulePtr != NULL; defmodulePtr = (struct defmodule *) EnvGetNextDefmodule(theEnv,defmodulePtr)) { /*=================================================================*/ /* We only want to save a module if all of the modules it imports */ /* from have already been saved. Since there can't be circular */ /* dependencies in imported modules, this should save the modules */ /* that don't import anything first and then work back from those. */ /*=================================================================*/ if (defmodulePtr->visitedFlag) { /* Module has already been saved. */ } else if (AllImportedModulesVisited(theEnv,defmodulePtr)) { for (saveFunction = ConstructData(theEnv)->ListOfSaveFunctions; saveFunction != NULL; saveFunction = saveFunction->next) { ((* (void (*)(void *,void *,char *)) saveFunction->func))(theEnv,defmodulePtr,(char *) filePtr); } updated = TRUE; defmodulePtr->visitedFlag = TRUE; } else { unvisited = TRUE; } } /*=====================================================================*/ /* At least one module should be saved in every pass. If all have been */ /* visited/saved, then both flags will be FALSE. If all remaining */ /* unvisited/unsaved modules were visited/saved, then unvisited will */ /* be FALSE and updated will be TRUE. If some, but not all, remaining */ /* unvisited/unsaved modules are visited/saved, then unvisited will */ /* be TRUE and updated will be TRUE. This leaves the case where there */ /* are remaining unvisited/unsaved modules, but none were */ /* visited/saved: unvisited is TRUE and updated is FALSE. */ /*=====================================================================*/ if (unvisited && (! updated)) { SystemError(theEnv,"CONSTRCT",2); break; } } /*======================*/ /* Close the save file. */ /*======================*/ GenClose(theEnv,filePtr); /*===========================*/ /* Remove the router bypass. */ /*===========================*/ SetFastSave(theEnv,NULL); /*=========================*/ /* Return TRUE to indicate */ /* successful completion. */ /*=========================*/ return(TRUE); }
bool Save( Environment *theEnv, const char *fileName) { struct saveCallFunctionItem *saveFunction; FILE *filePtr; Defmodule *defmodulePtr; bool updated = false; bool unvisited = true; /*=====================================*/ /* If embedded, clear the error flags. */ /*=====================================*/ if (EvaluationData(theEnv)->CurrentExpression == NULL) { ResetErrorFlags(theEnv); } /*=====================*/ /* Open the save file. */ /*=====================*/ if ((filePtr = GenOpen(theEnv,fileName,"w")) == NULL) { return false; } /*===========================*/ /* Bypass the router system. */ /*===========================*/ SetFastSave(theEnv,filePtr); /*================================*/ /* Mark all modules as unvisited. */ /*================================*/ MarkModulesAsUnvisited(theEnv); /*===============================================*/ /* Save the constructs. Repeatedly loop over the */ /* modules until each module has been save. */ /*===============================================*/ while (unvisited) { unvisited = false; updated = false; for (defmodulePtr = GetNextDefmodule(theEnv,NULL); defmodulePtr != NULL; defmodulePtr = GetNextDefmodule(theEnv,defmodulePtr)) { /*=================================================================*/ /* We only want to save a module if all of the modules it imports */ /* from have already been saved. Since there can't be circular */ /* dependencies in imported modules, this should save the modules */ /* that don't import anything first and then work back from those. */ /*=================================================================*/ if (defmodulePtr->visitedFlag) { /* Module has already been saved. */ } else if (AllImportedModulesVisited(theEnv,defmodulePtr)) { for (saveFunction = ConstructData(theEnv)->ListOfSaveFunctions; saveFunction != NULL; saveFunction = saveFunction->next) { (*saveFunction->func)(theEnv,defmodulePtr,(char *) filePtr,saveFunction->context); } updated = true; defmodulePtr->visitedFlag = true; } else { unvisited = true; } } /*=====================================================================*/ /* At least one module should be saved in every pass. If all have been */ /* visited/saved, then both flags will be false. If all remaining */ /* unvisited/unsaved modules were visited/saved, then unvisited will */ /* be false and updated will be true. If some, but not all, remaining */ /* unvisited/unsaved modules are visited/saved, then unvisited will */ /* be true and updated will be true. This leaves the case where there */ /* are remaining unvisited/unsaved modules, but none were */ /* visited/saved: unvisited is true and updated is false. */ /*=====================================================================*/ if (unvisited && (! updated)) { SystemError(theEnv,"CONSTRCT",2); break; } } /*======================*/ /* Close the save file. */ /*======================*/ GenClose(theEnv,filePtr); /*===========================*/ /* Remove the router bypass. */ /*===========================*/ SetFastSave(theEnv,NULL); /*=========================*/ /* Return true to indicate */ /* successful completion. */ /*=========================*/ return true; }