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; }