/** * \brief Frees the program. * * \param self Program. */ void limai_program_free ( LIMaiProgram* self) { int i; LIMaiExtension* extension; LIMaiExtension* extension_next; LIMaiEvent* event; LIMaiEvent* event_next; LIMaiMessage* message; LIMaiMessage* message_next; /* Invoke callbacks. */ if (self->callbacks != NULL) lical_callbacks_call (self->callbacks, "program-shutdown", lical_marshal_DATA); /* Free script. */ if (self->script != NULL) liscr_script_free (self->script); /* Free extensions. */ if (self->extensions != NULL) { for (extension = self->extensions ; extension != NULL ; extension = extension_next) { extension_next = extension->next; ((void (*)(void*)) extension->info->free) (extension->object); if (extension->module != NULL) lisys_module_free (extension->module); lisys_free (extension); } } /* Free components. */ if (self->components != NULL) { lisys_assert (self->components->size == 0); lialg_strdic_free (self->components); } /* Free the model manager. */ if (self->models != NULL) limdl_manager_free (self->models); /* Invoke callbacks. */ if (self->callbacks != NULL) lical_callbacks_call (self->callbacks, "program-free", lical_marshal_DATA); /* Free callbacks. */ if (self->callbacks != NULL) { lical_handle_releasev (self->calls, sizeof (self->calls) / sizeof (LICalHandle)); lical_callbacks_free (self->callbacks); } if (self->paths != NULL) lipth_paths_free (self->paths); /* Free messaging. */ if (self->message_mutex != NULL) lisys_mutex_free (self->message_mutex); for (i = 0 ; i < LIMAI_MESSAGE_QUEUE_MAX ; i++) { for (message = self->messages[i] ; message != NULL ; message = message_next) { message_next = message->next; limai_message_free (message); } } /* Free events. */ for (event = self->events_first ; event != NULL ; event = event_next) { event_next = event->next; limai_event_free (event); } lisys_free (self->launch_args); lisys_free (self->launch_name); lisys_free (self->args); lisys_free (self); }
/** * \brief Creates a new paths object. * * \param path Package root directory or NULL for auto-detect. * \param name Module name. * \return Paths or NULL. */ LIPthPaths* lipth_paths_new ( const char* path, const char* name) { char* tmp; LIPthPaths* self; /* Allocate self. */ self = lisys_calloc (1, sizeof (LIPthPaths)); if (self == NULL) return NULL; /* Allocate the file lookup table. */ self->files = lialg_strdic_new (); if (self->files == NULL) { lipth_paths_free (self); return NULL; } /* Set the module name. */ self->module_name = lisys_string_dup (name); if (self->module_name == NULL) { lipth_paths_free (self); return NULL; } /* Set the root directory. */ if (path != NULL) { self->root = lisys_string_dup (path); if (self->root == NULL) { lipth_paths_free (self); return NULL; } } else { self->root = lipth_paths_get_root (); if (self->root == NULL) { lipth_paths_free (self); return NULL; } } /* Get the data directory root. */ /* This is where modules and system scripts are located. If relative paths are enabled, the directory of the executable is searched for a data directory. Failing that, XDG data directories are searched for the game directory. As the last resort, the hardcoded data directory is used. */ #ifdef LI_RELATIVE_PATHS self->global_data = lisys_path_concat (self->root, "data", NULL); if (!private_validate_dir (&self->global_data)) #endif { self->global_data = lisys_paths_get_data_global ("lipsofsuna"); private_validate_dir (&self->global_data); if (self->global_data == NULL) { #ifdef LIDATADIR self->global_data = lisys_string_dup (LIDATADIR); if (!private_validate_dir (&self->global_data)) #endif { lisys_error_set (EINVAL, "cannot find the data directory"); lipth_paths_free (self); return NULL; } } } /* Get the data directory of the current module. */ /* This is where the data files of the module are installed. The directory functions as a fallback for both data and configuration files. */ self->module_data = lisys_path_concat (self->global_data, name, NULL); if (!private_validate_dir (&self->module_data)) { lisys_error_set (EINVAL, "cannot find the module data directory"); lipth_paths_free (self); return NULL; } /* Get the data save directory. */ /* This is where save files are written and where the user can copy any custom data files or mods. It's the first place where data files are looked for. */ tmp = lisys_paths_get_data_home (); if (tmp == NULL) { lipth_paths_free (self); return NULL; } self->module_data_save = lisys_path_concat (tmp, "lipsofsuna", name, NULL); lisys_free (tmp); if (self->module_data_save == NULL) { lipth_paths_free (self); return NULL; } /* Get the config directory. */ /* This is where configuration files are stored. It's separate from the save directory since in Linux that's the case. In Windows it's actually the save directory. */ tmp = lisys_paths_get_config_home (); if (tmp == NULL) { lipth_paths_free (self); return NULL; } self->module_config = lisys_path_concat (tmp, "lipsofsuna", name, NULL); lisys_free (tmp); if (self->module_config == NULL) { lipth_paths_free (self); return NULL; } /* Get the extension directory. */ /* This directory is reserved for potential third party extension libraries. The path is lib/extensions either in the relative path, XDG data path or the hardcoded extension directory. */ #ifdef LI_RELATIVE_PATHS self->global_exts = lisys_path_concat (self->global_data, "lib", "extensions", NULL); if (!private_validate_dir (&self->global_exts)) #endif { self->global_exts = lisys_paths_get_data_global ("lipsofsuna/lib/extensions"); #ifdef LIEXTSDIR if (!private_validate_dir (&self->global_exts)) { self->global_exts = lisys_string_dup (LIEXTSDIR); private_validate_dir (&self->global_exts); } #endif } /* Create the save directories. */ if (!private_create_save_path (self, self->module_data_save) || !private_create_save_path (self, self->module_config)) { lipth_paths_free (self); return NULL; } /* Add the base data directory. */ lipth_paths_add_path (self, ""); return self; }
/** * \brief Creates a new paths object. * * \param path Package root directory or NULL for auto-detect. * \param name Module name. * \return Paths or NULL. */ LIPthPaths* lipth_paths_new ( const char* path, const char* name) { char* tmp; LIPthPaths* self; LISysStat stat; self = lisys_calloc (1, sizeof (LIPthPaths)); if (self == NULL) return NULL; /* Set module name. */ self->module_name = lisys_string_dup (name); if (self->module_name == NULL) goto error; /* Set root directory. */ if (path != NULL) { self->root = lisys_string_dup (path); if (self->root == NULL) goto error; } else { self->root = lipth_paths_get_root (); if (self->root == NULL) goto error; } /* Get data directory. */ #ifdef LI_RELATIVE_PATHS self->global_data = lisys_path_concat (self->root, "data", NULL); if (self->global_data == NULL) goto error; #else self->global_data = LIDATADIR; #endif self->module_data = lisys_path_concat (self->global_data, name, NULL); if (self->module_data == NULL) goto error; /* Get data override directory. */ tmp = lisys_paths_get_data_home (); if (tmp == NULL) goto error; self->override_data = lisys_path_concat (tmp, "lipsofsuna", "data", name, NULL); if (self->override_data == NULL) { lisys_free (tmp); goto error; } /* Get save directory. */ self->global_state = lisys_path_concat (tmp, "lipsofsuna", "save", NULL); lisys_free (tmp); if (self->global_state == NULL) goto error; self->module_state = lisys_path_concat (self->global_state, name, NULL); if (self->module_state == NULL) goto error; /* Get extension directory. */ #ifdef LI_RELATIVE_PATHS self->global_exts = lisys_path_concat (self->global_data, "lib", "extensions", NULL); if (self->global_exts == NULL) goto error; #else self->global_exts = LIEXTSDIR; #endif /* Check for valid data directory. */ if (!lisys_filesystem_stat (self->module_data, &stat)) { lisys_error_set (EIO, "missing data directory `%s'", self->module_data); goto error; } if (stat.type != LISYS_STAT_DIRECTORY && stat.type != LISYS_STAT_LINK) { lisys_error_set (EIO, "invalid data directory `%s': not a directory", self->module_data); goto error; } return self; error: lipth_paths_free (self); return NULL; }