388 lines
9.8 KiB
C
388 lines
9.8 KiB
C
/*
|
|
* Copyright (c) 1997-2006 Motoyuki Kasahara
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "build-pre.h"
|
|
#include "eb.h"
|
|
#include "error.h"
|
|
#include "appendix.h"
|
|
#include "build-post.h"
|
|
|
|
/*
|
|
* Appendix ID counter.
|
|
*/
|
|
static EB_Book_Code appendix_counter = 0;
|
|
|
|
|
|
/*
|
|
* Unexported functions.
|
|
*/
|
|
static EB_Error_Code eb_load_appendix_catalog(EB_Appendix *appendix);
|
|
|
|
|
|
/*
|
|
* Initialize alternation text cache in `appendix'.
|
|
*/
|
|
void
|
|
eb_initialize_alt_caches(EB_Appendix *appendix)
|
|
{
|
|
EB_Alternation_Cache *p;
|
|
int i;
|
|
|
|
LOG(("in: eb_initialize_alt_caches(appendix=%d)", (int)appendix->code));
|
|
|
|
for (i = 0, p = appendix->narrow_cache;
|
|
i < EB_MAX_ALTERNATION_CACHE; i++, p++)
|
|
p->character_number = -1;
|
|
for (i = 0, p = appendix->wide_cache;
|
|
i < EB_MAX_ALTERNATION_CACHE; i++, p++)
|
|
p->character_number = -1;
|
|
|
|
LOG(("out: eb_initialize_alt_caches()"));
|
|
}
|
|
|
|
|
|
/*
|
|
* Finalize alternation text cache in `appendix'.
|
|
*/
|
|
void
|
|
eb_finalize_alt_caches(EB_Appendix *appendix)
|
|
{
|
|
LOG(("in+out: eb_finalize_alt_caches(appendix=%d)", (int)appendix->code));
|
|
|
|
/* nothing to be done */
|
|
}
|
|
|
|
|
|
/*
|
|
* Initialize `appendix'.
|
|
*/
|
|
void
|
|
eb_initialize_appendix(EB_Appendix *appendix)
|
|
{
|
|
LOG(("in: eb_initialize_appendix()"));
|
|
|
|
appendix->code = EB_BOOK_NONE;
|
|
appendix->path = NULL;
|
|
appendix->path_length = 0;
|
|
appendix->disc_code = EB_DISC_INVALID;
|
|
appendix->subbook_count = 0;
|
|
appendix->subbooks = NULL;
|
|
appendix->subbook_current = NULL;
|
|
eb_initialize_alt_caches(appendix);
|
|
|
|
LOG(("out: eb_initialize_appendix()"));
|
|
}
|
|
|
|
|
|
/*
|
|
* Finalize `appendix'.
|
|
*/
|
|
void
|
|
eb_finalize_appendix(EB_Appendix *appendix)
|
|
{
|
|
LOG(("in: eb_finalize_appendix(appendix=%d)", (int)appendix->code));
|
|
|
|
appendix->code = EB_BOOK_NONE;
|
|
|
|
if (appendix->path != NULL) {
|
|
free(appendix->path);
|
|
appendix->path = NULL;
|
|
}
|
|
appendix->path_length = 0;
|
|
|
|
appendix->disc_code = EB_DISC_INVALID;
|
|
|
|
if (appendix->subbooks != NULL) {
|
|
eb_finalize_appendix_subbooks(appendix);
|
|
free(appendix->subbooks);
|
|
appendix->subbooks = NULL;
|
|
appendix->subbook_count = 0;
|
|
}
|
|
appendix->subbook_current = NULL;
|
|
eb_finalize_alt_caches(appendix);
|
|
|
|
LOG(("out: eb_finalize_appendix()"));
|
|
}
|
|
|
|
|
|
/*
|
|
* Bind `appendix' to `path'.
|
|
*/
|
|
EB_Error_Code
|
|
eb_bind_appendix(EB_Appendix *appendix, const char *path)
|
|
{
|
|
EB_Error_Code error_code;
|
|
char temporary_path[EB_MAX_PATH_LENGTH + 1];
|
|
|
|
LOG(("in: eb_bind_appendix(path=%s)", path));
|
|
|
|
/*
|
|
* Reset structure members in the appendix.
|
|
*/
|
|
if (appendix->path != NULL) {
|
|
eb_finalize_appendix(appendix);
|
|
eb_initialize_appendix(appendix);
|
|
}
|
|
|
|
/*
|
|
* Assign a book code.
|
|
*/
|
|
appendix->code = appendix_counter++;
|
|
|
|
/*
|
|
* Set path of the appendix.
|
|
* The length of the file name "path/subdir/subsubdir/file.;1" must
|
|
* be EB_MAX_PATH_LENGTH maximum.
|
|
*/
|
|
if (EB_MAX_PATH_LENGTH < strlen(path)) {
|
|
error_code = EB_ERR_TOO_LONG_FILE_NAME;
|
|
goto failed;
|
|
}
|
|
strcpy(temporary_path, path);
|
|
error_code = eb_canonicalize_path_name(temporary_path);
|
|
if (error_code != EB_SUCCESS)
|
|
goto failed;
|
|
appendix->path_length = strlen(temporary_path);
|
|
|
|
if (EB_MAX_PATH_LENGTH
|
|
< appendix->path_length + 1 + EB_MAX_RELATIVE_PATH_LENGTH) {
|
|
error_code = EB_ERR_TOO_LONG_FILE_NAME;
|
|
goto failed;
|
|
}
|
|
|
|
appendix->path = (char *)malloc(appendix->path_length + 1);
|
|
if (appendix->path == NULL) {
|
|
error_code = EB_ERR_MEMORY_EXHAUSTED;
|
|
goto failed;
|
|
}
|
|
strcpy(appendix->path, temporary_path);
|
|
|
|
/*
|
|
* Read information from the catalog file.
|
|
*/
|
|
error_code = eb_load_appendix_catalog(appendix);
|
|
if (error_code != EB_SUCCESS)
|
|
goto failed;
|
|
|
|
LOG(("out: eb_bind_appendix(appendix=%d) = %s", (int)appendix->code,
|
|
eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
eb_finalize_appendix(appendix);
|
|
LOG(("out: eb_bind_appendix() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
/*
|
|
* Read information from the `CATALOG(S)' file in `appendix'.
|
|
* Return EB_SUCCESS, if it succeeds, error-code ohtherwise.
|
|
*/
|
|
static EB_Error_Code
|
|
eb_load_appendix_catalog(EB_Appendix *appendix)
|
|
{
|
|
EB_Error_Code error_code;
|
|
char buffer[EB_SIZE_PAGE];
|
|
char catalog_file_name[EB_MAX_FILE_NAME_LENGTH + 1];
|
|
char catalog_path_name[EB_MAX_PATH_LENGTH + 1];
|
|
char *space;
|
|
EB_Appendix_Subbook *subbook;
|
|
size_t catalog_size;
|
|
size_t title_size;
|
|
Zio zio;
|
|
Zio_Code zio_code;
|
|
int i;
|
|
|
|
LOG(("in: eb_load_appendix_catalog(appendix=%d)", (int)appendix->code));
|
|
|
|
zio_initialize(&zio);
|
|
|
|
/*
|
|
* Find a catalog file.
|
|
*/
|
|
if (eb_find_file_name(appendix->path, "catalog", catalog_file_name)
|
|
== EB_SUCCESS) {
|
|
appendix->disc_code = EB_DISC_EB;
|
|
catalog_size = EB_SIZE_EB_CATALOG;
|
|
title_size = EB_MAX_EB_TITLE_LENGTH;
|
|
} else if (eb_find_file_name(appendix->path, "catalogs", catalog_file_name)
|
|
== EB_SUCCESS) {
|
|
appendix->disc_code = EB_DISC_EPWING;
|
|
catalog_size = EB_SIZE_EPWING_CATALOG;
|
|
title_size = EB_MAX_EPWING_TITLE_LENGTH;
|
|
} else {
|
|
error_code = EB_ERR_FAIL_OPEN_CATAPP;
|
|
goto failed;
|
|
}
|
|
|
|
eb_compose_path_name(appendix->path, catalog_file_name, catalog_path_name);
|
|
eb_path_name_zio_code(catalog_path_name, ZIO_PLAIN, &zio_code);
|
|
|
|
/*
|
|
* Open the catalog file.
|
|
*/
|
|
if (zio_open(&zio, catalog_path_name, zio_code) < 0) {
|
|
error_code = EB_ERR_FAIL_OPEN_CATAPP;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Get the number of subbooks in the appendix.
|
|
*/
|
|
if (zio_read(&zio, buffer, 16) != 16) {
|
|
error_code = EB_ERR_FAIL_READ_CATAPP;
|
|
goto failed;
|
|
}
|
|
appendix->subbook_count = eb_uint2(buffer);
|
|
if (EB_MAX_SUBBOOKS < appendix->subbook_count)
|
|
appendix->subbook_count = EB_MAX_SUBBOOKS;
|
|
if (appendix->subbook_count == 0) {
|
|
error_code = EB_ERR_UNEXP_CATAPP;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Allocate memories for subbook entries.
|
|
*/
|
|
appendix->subbooks = (EB_Appendix_Subbook *)
|
|
malloc(sizeof(EB_Appendix_Subbook) * appendix->subbook_count);
|
|
if (appendix->subbooks == NULL) {
|
|
error_code = EB_ERR_MEMORY_EXHAUSTED;
|
|
goto failed;
|
|
}
|
|
eb_initialize_appendix_subbooks(appendix);
|
|
|
|
/*
|
|
* Read subbook information.
|
|
*/
|
|
for (i = 0, subbook = appendix->subbooks; i < appendix->subbook_count;
|
|
i++, subbook++) {
|
|
/*
|
|
* Read data from the catalog file.
|
|
*/
|
|
if (zio_read(&zio, buffer, catalog_size) != catalog_size) {
|
|
error_code = EB_ERR_FAIL_READ_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Set a directory name of the subbook.
|
|
*/
|
|
strncpy(subbook->directory_name, buffer + 2 + title_size,
|
|
EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->directory_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
space = strchr(subbook->directory_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
eb_fix_directory_name(appendix->path, subbook->directory_name);
|
|
}
|
|
|
|
/*
|
|
* Close the catalog file.
|
|
*/
|
|
zio_close(&zio);
|
|
zio_finalize(&zio);
|
|
LOG(("out: eb_load_appendix_catalog() = %s", eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
zio_close(&zio);
|
|
zio_finalize(&zio);
|
|
if (appendix->subbooks != NULL) {
|
|
free(appendix->subbooks);
|
|
appendix->subbooks = NULL;
|
|
}
|
|
LOG(("out: eb_load_appendix_catalog() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
/*
|
|
* Examine whether `appendix' is bound or not.
|
|
*/
|
|
int
|
|
eb_is_appendix_bound(EB_Appendix *appendix)
|
|
{
|
|
int is_bound;
|
|
|
|
LOG(("in: eb_is_appendix_bound(appendix=%d)", (int)appendix->code));
|
|
|
|
is_bound = (appendix->path != NULL);
|
|
|
|
LOG(("out: eb_is_appendix_bound() = %d", is_bound));
|
|
|
|
return is_bound;
|
|
}
|
|
|
|
|
|
/*
|
|
* Get the bound path of `appendix'.
|
|
*/
|
|
EB_Error_Code
|
|
eb_appendix_path(EB_Appendix *appendix, char *path)
|
|
{
|
|
EB_Error_Code error_code;
|
|
|
|
LOG(("in: eb_appendix_path(appendix=%d)", (int)appendix->code));
|
|
|
|
/*
|
|
* Check for the current status.
|
|
*/
|
|
if (appendix->path == NULL) {
|
|
error_code = EB_ERR_UNBOUND_APP;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Copy the path to `path'.
|
|
*/
|
|
strcpy(path, appendix->path);
|
|
|
|
LOG(("out: eb_appendix_path(path=%s) = %s",
|
|
path, eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
*path = '\0';
|
|
LOG(("out: eb_appendix_path() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|