static char rcsid[] = "@(#)$Id: unidata.c,v 1.31 2006/04/09 07:37:07 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.31 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "headers.h"
#include "mmaputil.h"
#include "s_me.h"
#include "unidata.h"
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
DEBUG_VAR(Debug,__FILE__,"charset");
static unsigned char * us_str P_((char *str));
static unsigned char * us_str(str)
char *str;
{
return (unsigned char *)str;
}
#ifdef MMAP
#include <sys/mman.h>
#ifndef MAP_FAILED
#define MAP_FAILED (void *)(-1)
#endif
#endif
#define TEXT_MAGIC "ELMME+\n"
/* TEXT_MAGIC is 8 bytes (including \0) */
struct unidata_header_1 {
uint8 text_magic[sizeof TEXT_MAGIC];
uint16 magic;
uint16 header_size;
uint16 page_size;
uint16 cell_size;
uint16 decomp_cell_size;
uint16 list_pagecount;
uint16 udata_pagecount;
uint16 decomp_header_pagecount;
uint16 decomp_storage_pagecount;
uint16 comp_list_pagecount;
};
/* Values for flags -field on struct char_cell_1 -structure */
#define FLAGS_have_upper 0x0001 /* upper -field is valid */
#define FLAGS_have_lower 0x0002 /* lower -field is valid */
#define FLAGS_have_title 0x0004 /* title -field is valid */
#define FLAGS_have_decimal 0x0008 /* decimal -field is valid */
#define FLAGS_have_decomp 0x0010 /* decomp -filed is valid */
struct char_cell_1 {
uint16 chartype; /* Field 2 -- General Category */
uint16 class; /* Field 3 -- Canonical Combining Classes */
uint16 direction; /* Field 4 -- Bidirectional Category */
/* Field 9 -- mirrored */
uint16 decomp; /* Field 5 -- Character Decomposition */
uint16 decimal; /* Field 6 -- Decimal digit value */
/* Field 7 -- Digit value -- not implemented (yet?) */
/* Field 8 -- Numeric value -- not implemented (yet?) */
uint16 flags;
uint16 upper; /* Field 12 -- Upper case equivalent */
uint16 lower; /* Field 12 -- Lower case equivalent */
uint16 title; /* FIeld 12 -- Title case equivalent */
};
static struct char_cell_1 unassigned_cell_buffer = {
CHARTYPE_Cn, 0, 0, 0, 0, 0, 0, 0
};
struct decomp_cell_1 {
uint16 next_comp; /* next decomp_cell_1 with same first char */
uint16 value; /* backpointer to character */
uint16 storage; /* pointer/index to decomp storage */
uint8 type_byte;
uint8 len_byte; /* length of decomposed data on storage */
};
static struct decomp_cell_1 unassigned_decomp_buffer = {
0, 0, 0, 0
};
#define UNIDATA_magic 0xFB00
enum unidata_format { unidata_bad = 0, unidata_format_1 = UNIDATA_magic };
struct unidata_format_1 {
int byte_swapped;
int mmapped;
struct unidata_header_1 *header;
size_t header_length;
uint16 *vector;
size_t vector_length;
off_t vector_offset;
int vector_count;
struct char_cell_1 *cells;
size_t cells_length;
off_t cells_offset;
int cells_count;
struct decomp_cell_1 *decomp_cells;
size_t decomp_cells_length;
off_t decomp_cells_offset;
int decomp_cells_count;
uint16 *decomp_storage;
size_t decomp_storage_length;
off_t decomp_storage_offset;
int decomp_storage_count;
uint16 *comp_vector;
size_t comp_vector_length;
off_t comp_vector_offset;
int comp_vector_count;
};
/* This macro requires ANSI C preprocessor */
#if __STDC__
#define SYSCALL(x) { int ret_=x; int err_=errno;\
if (ret_ == -1) \
DPRINT(Debug,1,(&Debug,"unidata: syscall %s failed: errno=%d (%s)\n", \
#x,err_,error_description(err_))); }
#else
#define SYSCALL(x) x
#endif
static void free_unidata_1 P_((struct unidata_format_1 *v));
static void free_unidata_1(v)
struct unidata_format_1 *v;
{
if (!v->mmapped) { /* malloced */
if (v->header_length)
free(v->header);
if (v->vector_length)
free(v->vector);
if (v->cells_length)
free(v->cells);
if (v->decomp_cells_length)
free(v->decomp_cells);
if (v->decomp_storage_length)
free(v->decomp_storage);
if (v->comp_vector_length)
free(v->comp_vector);
} else {
#ifdef MMAP
if (v->header_length)
SYSCALL(munmap((void *)v->header,v->header_length));
if (v->vector_length)
SYSCALL(munmap((void *)v->vector,v->vector_length));
if (v->cells_length)
SYSCALL(munmap((void *)v->cells,v->cells_length));
if (v->decomp_cells_length)
SYSCALL(munmap((void *)v->decomp_cells,v->decomp_cells_length));
if (v->decomp_storage_length)
SYSCALL(munmap((void *)v->decomp_storage,
v->decomp_storage_length));
if (v->comp_vector_length)
SYSCALL(munmap((void *)v->comp_vector,v->comp_vector_length));
#else
panic("UNIDATA PANIC",__FILE__,__LINE__,"free_unidata_1",
"unidata: Internal error -- mmap not available",0);
#endif
v->mmapped = 0;
}
v->header = NULL;
v->vector = NULL;
v->cells = NULL;
v->decomp_cells = NULL;
v->decomp_storage = NULL;
v->comp_vector = NULL;
v->header_length = 0;
v->vector_length = 0;
v->cells_length = 0;
v->decomp_cells_length = 0;
v->decomp_storage_length = 0;
v->comp_vector_length = 0;
}
#define MAX_VECTOR 0x10000
/* Allocate maximun needed space */
static void malloc_unidata_1 P_((struct unidata_format_1 *v));
static void malloc_unidata_1(v)
struct unidata_format_1 *v;
{
#ifdef MMAP
uint16 pagesize = getpagesize();
#else
uint16 pagesize = 512;
#endif
uint16 header_pages, vector_pages, cells_pages;
uint16 decomp_cells_pages, decomp_storage_pages, comp_vector_pages;
v->byte_swapped = 0; /* generated -- not swapped */
v->mmapped = 0; /* malloced -- not mapped */
v->header_length = sizeof (struct unidata_header_1);
v->header = safe_malloc(v->header_length);
header_pages = pages(v->header_length,pagesize);
v->vector_length = MAX_VECTOR * sizeof (uint16);
v->vector = safe_malloc(v->vector_length);
vector_pages = pages(v->vector_length,pagesize);
v->vector_count = 0;
v->vector_offset = pagesize * (off_t) header_pages;
v->cells_length = MAX_VECTOR * sizeof (struct char_cell_1);
v->cells = safe_malloc(v->cells_length);
cells_pages = pages(v->cells_length,pagesize);
v->cells_count = 0;
v->cells_offset = v->vector_offset + pagesize * (off_t) vector_pages;
/* cells_offset need to be recalculated when real need is known */
v->decomp_cells_length = MAX_VECTOR * sizeof (struct decomp_cell_1);
v->decomp_cells = safe_malloc(v->decomp_cells_length);
decomp_cells_pages = pages(v->decomp_cells_length,pagesize);
v->decomp_cells_count = 0;
v->decomp_cells_offset = v->cells_offset +
pagesize * (off_t) decomp_cells_pages;
/* decomp_cells_offset need to be recalculated when real need is known */
v->decomp_storage_length = MAX_VECTOR * sizeof (uint16);
v->decomp_storage = safe_malloc(v->decomp_storage_length);
decomp_storage_pages = pages(v->decomp_storage_length,pagesize);
v->decomp_storage_count = 0;
v->decomp_storage_offset = v->decomp_cells_offset +
pagesize * (off_t) decomp_storage_pages;
/* decomp_storage_offset need to be recalculated when real need is known */
v->comp_vector_length = MAX_VECTOR * sizeof (uint16);
v->comp_vector = safe_malloc(v->comp_vector_length);
comp_vector_pages = pages(v->comp_vector_length,pagesize);
v->comp_vector_count = 0;
v->comp_vector_offset = v->decomp_storage_offset +
pagesize * (off_t) comp_vector_pages;
/* comp_vector_offset need to be recalculated when real need is known */
strfcpy((char *)v->header->text_magic,
TEXT_MAGIC,sizeof v->header->text_magic);
v->header->magic = unidata_format_1;
v->header->header_size = sizeof (struct unidata_header_1);
v->header->page_size = pagesize;
v->header->cell_size = sizeof (struct char_cell_1);
v->header->decomp_cell_size = sizeof (struct decomp_cell_1);
v->header->list_pagecount = vector_pages;
v->header->udata_pagecount = cells_pages;
v->header->decomp_header_pagecount = decomp_cells_pages;
v->header->decomp_storage_pagecount = decomp_storage_pages;
v->header->comp_list_pagecount = comp_vector_pages;
}
#define READ_VALUE(x,byte_swapped) (byte_swapped ? SWAP(x) : x)
static void dump_header P_((struct unidata_format_1 *v,
int byte_swapped,
CONST char *filename));
static int write_unidata_1 P_((struct unidata_format_1 *v, int fd,
CONST char *filename));
static int write_unidata_1(v, fd, filename)
struct unidata_format_1 *v;
int fd;
CONST char *filename;
{
uint16 pagesize = READ_VALUE(v->header->page_size,v->byte_swapped);
uint16 comp_vector_pages = READ_VALUE(v->header->comp_list_pagecount,
v->byte_swapped);
if (!write_range(fd,0,v->header_length,(unsigned char*)v->header)) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: write_range failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
if (!write_range(fd,v->vector_offset,v->vector_length,
(unsigned char *)(v->vector))) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: write_range failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
if (!write_range(fd,v->cells_offset,v->cells_length,
(unsigned char *)(v->cells))) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: write_range failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
if (!write_range(fd,v->decomp_cells_offset,v->decomp_cells_length,
(unsigned char *)(v->decomp_cells))) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: write_range failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
if (!write_range(fd,v->decomp_storage_offset,v->decomp_storage_length,
(unsigned char *)(v->decomp_storage))) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: write_range failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
if (!write_range(fd,v->comp_vector_offset,v->comp_vector_length,
(unsigned char *)(v->comp_vector))) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: write_range failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
if (v->comp_vector_length < comp_vector_pages * (size_t) pagesize) {
/* Be sure that file is big enough */
if (!write_range(fd,
v->comp_vector_offset +
comp_vector_pages * (off_t) pagesize -1,
1, us_str(" "))) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: write_range failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
}
dump_header(v,v->byte_swapped,filename);
return 1;
}
static void dump_header (v,byte_swapped,filename)
struct unidata_format_1 *v;
int byte_swapped;
CONST char *filename;
{
if (v->header) {
DPRINT(Debug,40,(&Debug,"============ Header dump: %-15s =======\n",
filename));
DPRINT(Debug,40,(&Debug,"BYTE SWAPPED = %d\n",byte_swapped));
DPRINT(Debug,40,(&Debug,
"magic %04X header_size %04X page_size %04X\n",
READ_VALUE(v->header->magic,v->byte_swapped),
READ_VALUE(v->header->header_size,v->byte_swapped),
READ_VALUE(v->header->page_size,v->byte_swapped)));
DPRINT(Debug,40,(&Debug,
"cell_size %04X decomp_cell_size %04X\n",
READ_VALUE(v->header->cell_size,v->byte_swapped),
READ_VALUE(v->header->decomp_cell_size,v->byte_swapped)));
DPRINT(Debug,40,(&Debug,
"list_pagecount %04X udata_pagecount %04X\n",
READ_VALUE(v->header->list_pagecount,v->byte_swapped),
READ_VALUE(v->header->udata_pagecount,v->byte_swapped)));
DPRINT(Debug,40,(&Debug,
"decomp_header_pagecount %04X decomp_storage_pagecount %04X\n",
READ_VALUE(v->header->decomp_header_pagecount,v->byte_swapped),
READ_VALUE(v->header->decomp_storage_pagecount,v->byte_swapped)));
DPRINT(Debug,40,(&Debug,
"comp_list_pagecount %04X\n",
READ_VALUE(v->header->comp_list_pagecount,v->byte_swapped)));
DPRINT(Debug,40,(&Debug,"============ End dump: %-15s =======\n",
filename));
}
}
static int calculate_sizes P_((struct unidata_format_1 *v,
CONST char *filename));
static int calculate_sizes (v,filename)
struct unidata_format_1 *v;
CONST char *filename;
{
uint16 pagesize = READ_VALUE(v->header->page_size,v->byte_swapped);
uint16 header_pages, vector_pages, cells_pages;
uint16 decomp_cells_pages, decomp_storage_pages, comp_vector_pages;
if (READ_VALUE(v->header->header_size,v->byte_swapped) !=
sizeof (struct unidata_header_1) ||
READ_VALUE(v->header->cell_size,v->byte_swapped) !=
sizeof (struct char_cell_1) ||
READ_VALUE(v->header->decomp_cell_size,v->byte_swapped)
!= sizeof (struct decomp_cell_1)) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile,
"Mapfile %.30s is corrupted"),
filename);
DPRINT(Debug,1,(&Debug,"calculate_sizes failed #1 -- sizeof check\n"));
return 0;
}
header_pages = pages(v->header_length,pagesize);
v->vector_offset = pagesize * (off_t) header_pages;
vector_pages = READ_VALUE(v->header->list_pagecount,v->byte_swapped);
v->cells_offset = v->vector_offset + pagesize * (off_t) vector_pages;
cells_pages = READ_VALUE(v->header->udata_pagecount,v->byte_swapped);
v->decomp_cells_offset = v->cells_offset + pagesize * (off_t) cells_pages;
decomp_cells_pages = READ_VALUE(v->header->decomp_header_pagecount,
v->byte_swapped);
v->decomp_storage_offset = v->decomp_cells_offset +
pagesize * (off_t) decomp_cells_pages;
decomp_storage_pages = READ_VALUE(v->header->decomp_storage_pagecount,
v->byte_swapped);
v->comp_vector_offset = v->decomp_storage_offset +
pagesize * (off_t) decomp_storage_pages;
comp_vector_pages = READ_VALUE(v->header->comp_list_pagecount,
v->byte_swapped);
v->vector_length = pagesize * (off_t) vector_pages;
/* May give too big value */
v->vector_count = v->vector_length / sizeof (uint16);
v->cells_length = pagesize * (off_t) cells_pages;
/* May give too big value */
v->cells_count = v->cells_length / sizeof (struct char_cell_1);
v->decomp_cells_length = pagesize * (off_t) decomp_cells_pages;
/* May give too big value */
v->decomp_cells_count = v->decomp_cells_length /
sizeof (struct decomp_cell_1);
v->decomp_storage_length = pagesize * (off_t) decomp_storage_pages;
/* May give too big value */
v->decomp_storage_count = v->decomp_storage_length / sizeof (uint16);
v->comp_vector_length = pagesize * (off_t) comp_vector_pages;
/* May give too big value */
v->comp_vector_count = v->comp_vector_length / sizeof (uint16);
return 1;
}
static void debug_output P_((struct unidata_format_1 *v,
int status, int pagesize, char *str,
CONST char *filename));
static void debug_output(v,status,pagesize,str,filename)
struct unidata_format_1 *v;
int status;
int pagesize;
char *str;
CONST char *filename;
{
DPRINT(Debug,1,(&Debug,
"%s: %s: status=%d, vector_count=%d, cells_count=%d, pagesize=%d\n",
filename,str,status,v->vector_count,v->cells_count, pagesize));
DPRINT(Debug,1,(&Debug,
"%s: %s: header_length=%d, vector_length=%d, cells_length=%d\n",
filename,str,v->header_length,v->vector_length,v->cells_length));
DPRINT(Debug,1,(&Debug,
"%s: %s: decomp_cells_count=%d, decomp_storage_count=%d, comp_vector_count=%d\n",
filename,str,v->decomp_cells_count,v->decomp_storage_count,
v->comp_vector_count));
DPRINT(Debug,1,(&Debug,
"%s: %s: decomp_cells_length=%d, decomp_storage_length=%d, comp_vector_length=%d\n",
filename,str,v->decomp_cells_length,v->decomp_storage_length,
v->comp_vector_length));
if (v->header) {
DPRINT(Debug,5,(&Debug,
"%s: %s: swapped=%d, page_size=%d, vector_pages=%d, cells_pages=%d\n",
filename,str,v->byte_swapped,
READ_VALUE(v->header->page_size,
v->byte_swapped),
READ_VALUE(v->header->list_pagecount,
v->byte_swapped),
READ_VALUE(v->header->udata_pagecount,
v->byte_swapped)));
DPRINT(Debug,5,(&Debug,
"%s: %s: decomp_cells_pages=%d, decomp_storage_pages=%d, comp_vector_pages=%d\n",
filename,str,
READ_VALUE(v->header->decomp_header_pagecount,
v->byte_swapped),
READ_VALUE(v->header->decomp_storage_pagecount,
v->byte_swapped),
READ_VALUE(v->header->comp_list_pagecount,
v->byte_swapped)));
}
}
static int read_unidata_1 P_((struct unidata_format_1 *v, int fd,
int byte_swapped, CONST char *filename));
static int read_unidata_1(v, fd, byte_swapped, filename)
struct unidata_format_1 *v;
int fd;
int byte_swapped;
CONST char *filename;
{
int status = 0;
uint16 pagesize = 0;
v->byte_swapped = byte_swapped;
v->mmapped = 0;
v->header_length = sizeof (struct unidata_header_1);
v->header = safe_malloc(v->header_length);
if (!read_range(fd,0,v->header_length,(unsigned char*)v->header)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
status = 0;
goto fail_1;
}
pagesize = READ_VALUE(v->header->page_size,v->byte_swapped);
dump_header(v,byte_swapped,filename);
if (!calculate_sizes(v,filename)) {
status = 0;
goto fail_1;
}
v->vector = safe_malloc(v->vector_length);
if (!read_range(fd,v->vector_offset,v->vector_length,
(unsigned char *)(v->vector))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
status = 0;
goto fail_2;
}
v->cells = safe_malloc(v->cells_length);
if (!read_range(fd,v->cells_offset,v->cells_length,
(unsigned char *)(v->cells))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
status = 0;
goto fail_3;
}
v->decomp_cells = safe_malloc(v->decomp_cells_length);
if (!read_range(fd,v->decomp_cells_offset,v->decomp_cells_length,
(unsigned char *)(v->decomp_cells))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
status = 0;
goto fail_4;
}
v->decomp_storage = safe_malloc(v->decomp_storage_length);
if (!read_range(fd,v->decomp_storage_offset,v->decomp_storage_length,
(unsigned char *)(v->decomp_storage))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
status = 0;
goto fail_5;
}
v->comp_vector = safe_malloc(v->comp_vector_length);
if (!read_range(fd,v->comp_vector_offset,v->comp_vector_length,
(unsigned char *)(v->comp_vector))) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
status = 0;
goto fail_6;
}
status = 1;
if (!status) {
fail_6:
free(v->comp_vector);
v->comp_vector = NULL;
v->comp_vector_length = 0;
fail_5:
free(v->decomp_storage);
v->decomp_storage = NULL;
v->decomp_storage_length = 0;
fail_4:
free(v->decomp_cells);
v->decomp_cells = NULL;
v->decomp_cells_length = 0;
fail_3:
free(v->cells);
v->cells = NULL;
v->cells_length = 0;
fail_2:
free(v->vector);
v->vector = NULL;
v->vector_length = 0;
fail_1:
free(v->header);
v->header = NULL;
v->header_length = 0;
}
debug_output(v,status,pagesize,"read",filename);
return status;
}
static int mmap_unidata_1 P_((struct unidata_format_1 *v, int fd,
int byte_swapped, CONST char *filename));
static int mmap_unidata_1(v, fd, byte_swapped, filename)
struct unidata_format_1 *v;
int fd;
int byte_swapped;
CONST char *filename;
{
int status = 0;
#ifdef MMAP
uint16 real_pagesize = getpagesize();
uint16 pagesize = 0;
void * result;
v->byte_swapped = byte_swapped;
v->mmapped = 1;
v->header_length = sizeof (struct unidata_header_1);
result = mmap(0,v->header_length,PROT_READ,MAP_SHARED,fd,0);
if (result == MAP_FAILED) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap,
"Failed to mmap %.50s: %30s"),
filename, error_description(err));
v->header = NULL;
v->header_length = 0;
status = 0;
goto fail_1;
}
v->header = result;
pagesize = READ_VALUE(v->header->page_size,v->byte_swapped);
if (pagesize < real_pagesize || pagesize % real_pagesize != 0) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeIncompatiblePagesize,
"Pagesize of %.50s (%d) incompatible with system pagesize (%d)"),
filename, pagesize,real_pagesize);
status = 0;
goto fail_2;
}
dump_header(v,byte_swapped,filename);
if (!calculate_sizes(v,filename)) {
status = 0;
goto fail_2;
}
result = mmap(0,v->vector_length,PROT_READ,MAP_SHARED,fd,
v->vector_offset);
if (result == MAP_FAILED) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap,
"Failed to mmap %.50s: %30s"),
filename, error_description(err));
v->vector = NULL;
v->vector_length = 0;
status = 0;
goto fail_2;
}
v->vector = result;
result = mmap(0,v->cells_length,PROT_READ,MAP_SHARED,fd,
v->cells_offset);
if (result == MAP_FAILED) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap,
"Failed to mmap %.50s: %30s"),
filename, error_description(err));
v->cells = NULL;
v->cells_length = 0;
status = 0;
goto fail_3;
}
v->cells = result;
result = mmap(0,v->decomp_cells_length,PROT_READ,MAP_SHARED,fd,
v->decomp_cells_offset);
if (result == MAP_FAILED) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap,
"Failed to mmap %.50s: %30s"),
filename, error_description(err));
v->decomp_cells = NULL;
v->decomp_cells_length = 0;
status = 0;
goto fail_4;
}
v->decomp_cells = result;
result = mmap(0,v->decomp_storage_length,PROT_READ,MAP_SHARED,fd,
v->decomp_storage_offset);
if (result == MAP_FAILED) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap,
"Failed to mmap %.50s: %30s"),
filename, error_description(err));
v->decomp_storage = NULL;
v->decomp_storage_length = 0;
status = 0;
goto fail_5;
}
v->decomp_storage = result;
result = mmap(0,v->comp_vector_length,PROT_READ,MAP_SHARED,fd,
v->comp_vector_offset);
if (result == MAP_FAILED) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap,
"Failed to mmap %.50s: %30s"),
filename, error_description(err));
v->cells = NULL;
v->cells_length = 0;
status = 0;
goto fail_6;
}
v->comp_vector = result;
status = 1;
if (!status) {
fail_6:
SYSCALL(munmap((void *)v->decomp_storage,v->decomp_storage_length));
v->decomp_storage = NULL;
v->decomp_storage_length = 0;
fail_5:
SYSCALL(munmap((void *)v->decomp_cells,v->decomp_cells_length));
v->decomp_cells = NULL;
v->decomp_cells_length = 0;
fail_4:
SYSCALL(munmap((void *)v->cells,v->cells_length));
v->cells = NULL;
v->cells_length = 0;
fail_3:
SYSCALL(munmap((void *)v->vector,v->vector_length));
v->vector = NULL;
v->vector_length = 0;
fail_2:
SYSCALL(munmap((void *)v->header,v->header_length));
v->header = NULL;
v->header_length = 0;
}
fail_1:
debug_output(v,status,pagesize,"mmap",filename);
#endif
return status;
}
static void trim_unidata_1 P_((struct unidata_format_1 *v));
static void trim_unidata_1(v)
struct unidata_format_1 *v;
{
/* If malloced, truncate according of usage */
if (!v->mmapped && !v->byte_swapped) {
uint16 pagesize = v->header->page_size;
int n = v->vector_count;
if (n < 1) n = 1;
v->vector_length = n * sizeof (uint16);
v->header->list_pagecount = pages(v->vector_length,pagesize);
v->vector = safe_realloc(v->vector,v->vector_length);
n = v->cells_count;
if (n < 1) n = 1;
v->cells_length = n * sizeof (struct unidata_header_1);
v->header->udata_pagecount = pages(v->cells_length,pagesize);
v->cells_offset = v->vector_offset +
pagesize * (off_t) (v->header->list_pagecount);
v->cells = safe_realloc(v->cells,v->cells_length);
n = v->decomp_cells_count;
if (n < 1) n = 1;
v->decomp_cells_length = n * sizeof (struct decomp_cell_1);
v->header->decomp_header_pagecount = pages(v->decomp_cells_length,
pagesize);
v->decomp_cells_offset = v->cells_offset +
pagesize * (off_t) (v->header->udata_pagecount);
v->decomp_cells = safe_realloc(v->decomp_cells,
v->decomp_cells_length);
n = v->decomp_storage_count;
if (n < 1) n = 1;
v->decomp_storage_length = n * sizeof (uint16);
v->header->decomp_storage_pagecount = pages(v->decomp_storage_length,
pagesize);
v->decomp_storage_offset = v->decomp_cells_offset +
pagesize * (off_t) (v->header->decomp_header_pagecount);
v->decomp_storage = safe_realloc(v->decomp_storage,
v->decomp_storage_length);
n = v->comp_vector_count;
if (n < 1) n = 1;
v->comp_vector_length = n * sizeof (uint16);
v->header->comp_list_pagecount = pages(v->comp_vector_length,
pagesize);
v->comp_vector_offset = v->decomp_storage_offset +
pagesize * (off_t) (v->header->decomp_storage_pagecount);
v->comp_vector = safe_realloc(v->comp_vector,
v->comp_vector_length);
}
/* zero fill unused area */
if (v->vector_count * sizeof (uint16) < v->vector_length) {
/* bzero is defined on hdrs/defs.h
* notice pointer arithmetic
*/
bzero((void *)(v->vector + v->vector_count),
v->vector_length - v->vector_count * sizeof (uint16));
}
if (v->cells_count * sizeof (struct unidata_header_1) < v->cells_length) {
/* bzero is defined on hdrs/defs.h
* notice pointer arithmetic
*/
bzero((void *)(v->cells + v->cells_count),
v->cells_length -
v->cells_count * sizeof (struct unidata_header_1));
}
if (v->decomp_cells_count * sizeof (struct decomp_cell_1) <
v->decomp_cells_length) {
/* bzero is defined on hdrs/defs.h
* notice pointer arithmetic
*/
bzero((void *)(v->decomp_cells + v->decomp_cells_count),
v->decomp_cells_length -
v->decomp_cells_count * sizeof (struct decomp_cell_1));
}
if (v->decomp_storage_count * sizeof (uint16) <
v->decomp_storage_length) {
/* bzero is defined on hdrs/defs.h
* notice pointer arithmetic
*/
bzero((void *)(v->decomp_storage + v->decomp_storage_count),
v->decomp_storage_length -
v->decomp_storage_count * sizeof (uint16));
}
if (v->comp_vector_count * sizeof (uint16) <
v->comp_vector_length) {
/* bzero is defined on hdrs/defs.h
* notice pointer arithmetic
*/
bzero((void *)(v->comp_vector + v->comp_vector_count),
v->comp_vector_length -
v->comp_vector_count * sizeof (uint16));
}
}
struct unidata_mapped_data {
enum unidata_format format;
union {
struct unidata_format_1 f1;
} v;
};
void free_unidata(v)
struct unidata_mapped_data * v;
{
switch(v->format) {
case unidata_format_1: free_unidata_1(&(v->v.f1));
break;
}
v->format = unidata_bad;
free(v);
}
int write_unidata(v,filename)
struct unidata_mapped_data *v;
CONST char *filename;
{
char *tmpname;
int fd, err;
int status = 0;
if (0 != access(filename,WRITE_ACCESS)) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: access failed: errno=%d (%s)\n", \
err,error_description(err)));
if (err != ENOENT) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
filename, error_description(err));
return 0;
}
}
tmpname = safe_strdup(filename);
tmpname = strmcat(tmpname,".N");
err = can_open(tmpname,"w");
if (err) {
DPRINT(Debug,1,(&Debug,
"unidata: can_open failed: code=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmpname, error_description(err));
status = 0;
goto fail;
}
fd = open(tmpname,O_WRONLY|O_CREAT|O_EXCL,0644);
if (-1 == fd) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: open failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmpname, error_description(err));
status = 0;
goto fail;
}
switch(v->format) {
case unidata_format_1:
status = write_unidata_1(&(v->v.f1),fd,tmpname);
break;
}
if (-1 == close(fd)) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"unidata: close failed: errno=%d (%s)\n", \
err,error_description(err)));
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable,
"File %.50s is not writeable: %s"),
tmpname, error_description(err));
status = 0;
goto fail;
}
if (status) {
if (-1 == rename(tmpname,filename)) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed,
"Failed to rename temporary file to %.50s: %.30s"),
filename, error_description(err));
status = 0;
goto fail;
}
}
fail:
if (tmpname)
free(tmpname);
return status;
}
int get_unidata(ptr,filename)
struct unidata_mapped_data **ptr;
CONST char *filename;
{
struct unidata_mapped_data * res = *ptr;
int status = 0;
int fd, err;
uint8 text_magic[sizeof TEXT_MAGIC];
uint16 magic;
int n;
err = can_open(filename,"r");
if (err) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
return 0;
}
fd = open(filename,O_RDONLY);
if (-1 == fd) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable,
"File %.50s is unreadable: %s"),
filename, error_description(err));
return 0;
}
n = read(fd,text_magic, sizeof text_magic);
if (n != 8) { /* text_magic is assumed to be 8 bytes or
there is error
*/
lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile,
"Mapfile %.30s is corrupted"),
filename);
close(fd);
DPRINT(Debug,1,(&Debug,"get_unidata failed #1 -- text_magic read\n"));
return 0;
}
if (0 != memcmp(text_magic,TEXT_MAGIC,8)) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile,
"Mapfile %.30s is corrupted"),
filename);
close(fd);
DPRINT(Debug,1,(&Debug,
"get_unidata failed #1 -- text_magic is wrong: %.8s\n",
text_magic));
return 0;
}
n = read(fd,(void *)&magic, sizeof magic);
if (n != 2) { /* magic is assumed to be 2 bytes or
* there is 'Configure' error...
*/
lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile,
"Mapfile %.30s is corrupted"),
filename);
close(fd);
DPRINT(Debug,1,(&Debug,"get_unidata failed #1 -- magic read\n"));
return 0;
}
if (res)
free_unidata(res);
res = NULL;
res = safe_malloc(sizeof (struct unidata_mapped_data));
res->format = unidata_bad;
if (unidata_format_1 == magic) {
res->format = unidata_format_1;
if (!mmap_unidata_1(&(res->v.f1),fd,0,filename) &&
!read_unidata_1(&(res->v.f1),fd,0,filename)) {
status = 0;
} else
status = 1;
} else if (unidata_format_1 == SWAP(magic)) {
res->format = unidata_format_1;
if (!mmap_unidata_1(&(res->v.f1),fd,1,filename) &&
!read_unidata_1(&(res->v.f1),fd,1,filename)) {
status = 0;
} else
status = 1;
} else {
lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile,
"Mapfile %.30s is corrupted"),
filename);
DPRINT(Debug,1,(&Debug, "get_unidata failed #2 -- magic check\n"));
status = 0;
}
if (!status) {
if (res)
free(res);
res = NULL;
}
close(fd);
*ptr = res;
return status;
}
struct codes {
int code;
char * name;
};
static int lookup_code P_((struct codes *codes, char buffer[]));
static int lookup_code(codes,buffer)
struct codes *codes;
char buffer[];
{
int ptr;
for (ptr = 0; codes[ptr].name; ptr++)
if (0 == strcmp(codes[ptr].name,buffer))
break;
return ptr;
}
static int lookup_from_code P_((struct codes *codes, int code));
static int lookup_from_code(codes,code)
struct codes *codes;
int code;
{
int ptr;
for (ptr = 0; codes[ptr].name; ptr++)
if (codes[ptr].code == code)
break;
return ptr;
}
static struct codes categories[] = {
/* Mark */
{ CHARTYPE_Mn, "Mn" }, /* Mark, Non-Spacing */
{ CHARTYPE_Mc, "Mc" }, /* Mark, Spacing Combining */
{ CHARTYPE_Me, "Me" }, /* Mark, Enclosing */
/* Number */
{ CHARTYPE_Nd, "Nd" }, /* Number, Decimal Digit */
{ CHARTYPE_Nl, "Nl" }, /* Number, Letter */
{ CHARTYPE_No, "No" }, /* Number, Other */
/* Separator */
{ CHARTYPE_Zs, "Zs" }, /* Separator, Space */
{ CHARTYPE_Zl, "Zl" }, /* Separator, Line */
{ CHARTYPE_Zp, "Zp" }, /* Separator, Paragraph */
/* Other */
{ CHARTYPE_Cc, "Cc" }, /* Other, Control */
{ CHARTYPE_Cf, "Cf" }, /* Other, Format */
{ CHARTYPE_Cs, "Cs" }, /* Other, Surrogate */
{ CHARTYPE_Co, "Co" }, /* Other, Private Use */
{ CHARTYPE_Cn, "Cn" }, /* Other, Not Assigned */
/* Letter */
{ CHARTYPE_Lu, "Lu" }, /* Letter, Uppercase */
{ CHARTYPE_Ll, "Ll" }, /* Letter, Lowercase */
{ CHARTYPE_Lt, "Lt" }, /* Letter, Titlecase */
{ CHARTYPE_Lm, "Lm" }, /* Letter, Modifier */
{ CHARTYPE_Lo, "Lo" }, /* Letter, Other */
/* Punctuation */
{ CHARTYPE_Pc, "Pc" }, /* Punctuation, Connector */
{ CHARTYPE_Pd, "Pd" }, /* Punctuation, Dash */
{ CHARTYPE_Ps, "Ps" }, /* Punctuation, Open */
{ CHARTYPE_Pe, "Pe" }, /* Punctuation, Close */
{ CHARTYPE_Po, "Po" }, /* Punctuation, Other */
/* Symbol */
{ CHARTYPE_Sm, "Sm" }, /* Symbol, Math */
{ CHARTYPE_Sc, "Sc" }, /* Symbol, Currency */
{ CHARTYPE_Sk, "Sk" }, /* Symbol, Modifier */
{ CHARTYPE_So, "So" }, /* Symbol, Other */
{ 0, NULL }
};
static struct codes bidir_categories[] = {
/* Strong types */
{ DIRECTION_L, "L" }, /* Left-Right */
{ DIRECTION_R, "R" }, /* Right-Left */
/* Weak types */
{ DIRECTION_EN, "EN" }, /* European Number */
{ DIRECTION_ES, "ES" }, /* European Number Separator */
{ DIRECTION_ET, "ET" }, /* European Number Terminator */
{ DIRECTION_AN, "AN" }, /* Arabic Number */
{ DIRECTION_CS, "CS" }, /* Common Number Separator */
/* Separators */
{ DIRECTION_B, "B" }, /* Block Separator */
{ DIRECTION_S, "S" }, /* Segment Separator */
/* Neutrals */
{ DIRECTION_WS, "WS" }, /* Whitespace */
{ DIRECTION_ON, "ON" }, /* Other Neutrals */
/* Not Assigned */
{ 0, "" }, /* Not assigned */
{ 0, NULL }
};
static struct codes mirrored[] = {
{ 0, "N" },
{ DIRECTION_mirrored, "Y" },
{ 0, NULL }
};
static struct codes decomp_compat[] = {
{ DECOMP_font, "<font>" },
/* A font variant (e.g. a blackletter form). */
{ DECOMP_noBreak, "<noBreak>" },
/* A no-break version of a space or hyphen. */
{ DECOMP_initial, "<initial>" },
/* An initial presentation form (Arabic). */
{ DECOMP_medial, "<medial>" },
/* A medial presentation form (Arabic). */
{ DECOMP_final, "<final>" },
/* A final presentation form (Arabic). */
{ DECOMP_isolated, "<isolated>" },
/* An isolated presentation form (Arabic). */
{ DECOMP_circle, "<circle>" }, /* An encircled form. */
{ DECOMP_super, "<super>" }, /* A superscript form. */
{ DECOMP_sub, "<sub>" }, /* A subscript form. */
{ DECOMP_vertical, "<vertical>" },
/* A vertical layout presentation form. */
{ DECOMP_wide, "<wide>" },
/* A wide (or zenkaku) compatibility character. */
{ DECOMP_narrow, "<narrow>" },
/* A narrow (or hankaku) compatibility character. */
{ DECOMP_small, "<small>" },
/* A small variant form (CNS compatibility). */
{ DECOMP_square, "<square>" },
/* A CJK squared font variant. */
{ DECOMP_compat, "<compat>" },
/* Otherwise unspecified compatibility character.*/
{ DECOMP_fraction, "<fraction>" }, /* ??? */
{ 0, NULL }
};
static int write_unidata_text_1 P_((struct unidata_format_1 *v,
FILE *f));
static int write_unidata_text_1(v, f)
struct unidata_format_1 *v;
FILE *f;
{
int status = 0;
int code;
for (code = 0; code <= 0xFFFF; code++) {
if (code < v -> vector_count) {
uint16 ptr = v->vector[code];
if (ptr < v -> cells_count) {
struct char_cell_1 *C = &(v->cells[ptr]);
uint16 chartype = READ_VALUE(C->chartype,v->byte_swapped);
uint16 class = READ_VALUE(C->class,v->byte_swapped);
uint16 direction = READ_VALUE(C->direction,v->byte_swapped);
uint16 decomp = READ_VALUE(C->decomp,v->byte_swapped);
uint16 decimal = READ_VALUE(C->decimal,v->byte_swapped);
uint16 flags = READ_VALUE(C->flags,v->byte_swapped);
uint16 upper = READ_VALUE(C->upper,v->byte_swapped);
uint16 lower = READ_VALUE(C->lower,v->byte_swapped);
uint16 title = READ_VALUE(C->title,v->byte_swapped);
uint16 mirror_code = 0xF000 & direction;
int ptr;
direction -= mirror_code;
/* Field 0 Code value in 4-digit hexadecimal format */
fprintf(f,"%04X;",code);
/* Field 1 Unicode 2.0 Character Name */
fprintf(f,"Character %04X;",code);
/* Field 2 General Category */
ptr = lookup_from_code(categories,chartype);
if (categories[ptr].name)
fprintf(f,"%s;",categories[ptr].name);
else {
fprintf(f,"%X;",chartype);
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X), chartype=%d (%04X)\n",
code,code,chartype,chartype));
}
/* Field 3 Canonical Combining Classes */
fprintf(f,"%d;",class);
/* Field 4 Bidirectional Category */
ptr = lookup_from_code(bidir_categories,direction);
if (bidir_categories[ptr].name)
fprintf(f,"%s;",bidir_categories[ptr].name);
else {
fprintf(f,"%X;",direction);
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X), direction=%d (%04X)\n",
code,code,direction,direction));
}
/* Field 6 Character Decomposition */
if (flags & FLAGS_have_decomp) {
if (decomp < v->decomp_cells_count) {
struct decomp_cell_1 *D = &(v->decomp_cells[decomp]);
uint16 storage = READ_VALUE(D->storage,
v->byte_swapped);
uint16 value = READ_VALUE(D->value,
v->byte_swapped);
uint8 type_byte = D->type_byte;
uint8 len_byte = D->len_byte;
if (value != code) {
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X), value=%d (%04X)\n",
code,code,value,value));
}
if (type_byte) {
ptr = lookup_from_code(decomp_compat,type_byte);
if (decomp_compat[ptr].name)
fprintf(f,"%s ",decomp_compat[ptr].name);
else {
fprintf(f,"<%X> ",type_byte);
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X), type_byte=%d (%02X)\n",
code,code,type_byte,type_byte));
}
}
if (len_byte) {
if (storage + len_byte <=
v -> decomp_storage_count) {
int i;
for (i = 0; i < len_byte; i++) {
fprintf(f,"%04X",
v->decomp_storage[storage+i]);
if (i < len_byte-1)
fprintf(f," ");
}
} else {
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X) (decomp)storage=%d (%04X) len_byte=%d (%02X)\n",
code,code,storage,storage,
len_byte,len_byte));
}
} else {
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X) zero length decomposition\n",
code,code));
}
fprintf(f,";");
} else {
fprintf(f,"<%04X>;",decomp);
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X), decomp(cell)=%d (%04X)\n",
code,code,decomp,decomp));
}
} else
fprintf(f,";");
/* Read field 6 Decimal digit value */
if (flags & FLAGS_have_decimal) {
fprintf(f,"%d;",decimal);
} else
fprintf(f,";");
/* Field 7 Digit value */
fprintf(f,";");
/* Field 8 Numeric value */
fprintf(f,";");
/* Field 9 */
ptr = lookup_from_code(mirrored,mirror_code);
if (mirrored[ptr].name)
fprintf(f,"%s;",mirrored[ptr].name);
else {
fprintf(f,"%X;",mirror_code);
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X), mirror_code=%d (%04X)\n",
code,code,mirror_code,mirror_code));
}
/* Field 10 Unicode 1.0 Name */
fprintf(f,";");
/* Field 11 10646 Comment field */
fprintf(f,";");
/* Field 12 Upper case equivalent mapping */
if (flags & FLAGS_have_upper) {
fprintf(f,"%04X;",upper);
} else
fprintf(f,";");
/* Field 13 Lower case equivalent mapping */
if (flags & FLAGS_have_lower) {
fprintf(f,"%04X;",lower);
} else
fprintf(f,";");
/* Field 14 Title case equivalent mapping */
if (flags & FLAGS_have_title) {
fprintf(f,"%04X\n",title);
} else
fprintf(f,"\n");
} else {
DPRINT(Debug,1,(&Debug,
"unidata: bad unidata, code=%d (%04X), (cell)ptr=%d (%04X)\n",
code,code,ptr,ptr));
}
}
}
return status;
}
int write_unidata_text(v,f)
struct unidata_mapped_data *v;
FILE *f;
{
int status = 0;
switch(v->format) {
case unidata_format_1:
status = write_unidata_text_1(&(v->v.f1),f);
break;
}
return status;
}
static int read_field P_((FILE *fp, int *c, char * buffer, int size,
FILE *logfile));
static int read_field (fp,c,buffer,size,logfile)
FILE *fp;
int *c;
char * buffer;
int size;
FILE *logfile;
{
int ptr;
for (ptr = 0, *c = fgetc(fp);
ptr < size -1;
*c = fgetc(fp), ptr++) {
if (';' == *c || EOF == *c || '\n' == *c)
break;
if (logfile) {
putc(*c,logfile);
}
buffer[ptr] = *c;
}
buffer[ptr] = '\0';
if (logfile && EOF != *c) {
putc(*c,logfile);
}
return ptr;
}
static void format_error P_((FILE *logfile,CONST char *filename,
int *line_number,char *buffer, int c));
static void format_error(logfile,filename,line_number,buffer, c)
FILE *logfile;
CONST char *filename;
int *line_number;
char *buffer;
int c;
{
lib_error(CATGETS(elm_msg_cat, MeSet, MeFormatError,
"Format error on %.50s, line %d: %s"),
filename,*line_number,buffer);
if (logfile) {
fprintf(logfile,"<-- [ERROR]\n");
fprintf(logfile,catgets(elm_msg_cat, MeSet, MeFormatError,
"Format error on %.50s, line %d: %s"),
filename,*line_number,buffer);
putc('\n',logfile);
if ('\n' != c)
fprintf(logfile,"%05d: ",*line_number);
}
}
static int read_line P_((FILE *fp, struct char_cell_1 *buffer,
uint16 *code, char *name_buffer,
int name_buffer_size, int *line_number,
CONST char *filename, FILE *logfile,
char * composition_buffer,
int composition_buffer_size));
static int read_line(fp,buffer,code,name_buffer,name_buffer_size,
line_number, filename, logfile, composition_buffer,
composition_buffer_size)
FILE *fp;
struct char_cell_1 *buffer;
uint16 *code;
char *name_buffer;
int name_buffer_size;
int *line_number;
CONST char *filename;
FILE *logfile;
char *composition_buffer;
int composition_buffer_size;
{
char number_buffer[5], *endptr;
char category_buffer[3];
char combining_buffer[4];
char bidir_category_buffer[3];
char decimal_buffer[5];
char digit_buffer[10];
char numeric_buffer[10];
char mirror_buffer[2];
char unicode10_buffer[70];
char comment_buffer[100];
char upper_buffer[5];
char lower_buffer[5];
char title_buffer[5];
int c = '\0',ptr;
int status = 0;
long l;
/* Format: 0000;<control>;Cc;0;ON;;;;;N;NULL;;;; */
if (logfile) {
fprintf(logfile,"%05d: ",*line_number);
}
/* Read field 0 Code value in 4-digit hexadecimal format */
ptr = read_field(fp,&c,number_buffer,sizeof number_buffer,logfile);
/* EOF on beginning is OK */
if (0 == ptr && EOF == c)
goto fail;
buffer->flags = 0;
if (EOF == c)
goto got_eof;
if (4 != ptr || c != ';') {
format_error(logfile,filename,line_number,number_buffer,c);
goto fail;
}
*code = l = strtol(number_buffer,&endptr,16);
if ('\0' != *endptr || *code != l) {
format_error(logfile,filename,line_number,number_buffer,c);
goto fail;
}
/* Read field 1 Unicode 2.0 Character Name */
ptr = read_field(fp,&c,name_buffer,name_buffer_size,logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,number_buffer,c);
goto fail;
}
/* Read field 2 General Category */
ptr = read_field(fp,&c,category_buffer,sizeof category_buffer,logfile);
if (EOF == c)
goto got_eof;
if (2 != ptr || c != ';') {
format_error(logfile,filename,line_number,category_buffer,c);
goto fail;
}
ptr = lookup_code(categories,category_buffer);
if (!categories[ptr].name) {
format_error(logfile,filename,line_number,category_buffer,c);
goto fail;
}
buffer->chartype = categories[ptr].code;
/* Read field 3 Canonical Combining Classes */
ptr = read_field(fp,&c,combining_buffer,sizeof combining_buffer,logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,combining_buffer,c);
goto fail;
}
buffer->class = strtol(combining_buffer,&endptr,10);
if ('\0' != *endptr) {
format_error(logfile,filename,line_number,combining_buffer,c);
goto fail;
}
/* Read field 4 Bidirectional Category */
ptr = read_field(fp,&c,bidir_category_buffer,sizeof bidir_category_buffer,
logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,bidir_category_buffer,c);
goto fail;
}
ptr = lookup_code(bidir_categories,bidir_category_buffer);
if (!bidir_categories[ptr].name) {
format_error(logfile,filename,line_number,bidir_category_buffer,c);
goto fail;
}
buffer->direction = bidir_categories[ptr].code;
/* Read field 5 Character Decomposition */
ptr = read_field(fp,&c,composition_buffer,composition_buffer_size,
logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,composition_buffer,c);
goto fail;
}
/* Read field 6 Decimal digit value */
ptr = read_field(fp,&c,decimal_buffer,sizeof decimal_buffer,
logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,decimal_buffer,c);
goto fail;
}
if (0 != ptr) {
buffer->decimal = strtol(decimal_buffer,&endptr,10);
if ('\0' != *endptr) {
format_error(logfile,filename,line_number,decimal_buffer,c);
goto fail;
}
buffer->flags |= FLAGS_have_decimal;
}
/* Read field 7 Digit value */
ptr = read_field(fp,&c,digit_buffer,sizeof digit_buffer,
logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,digit_buffer,c);
goto fail;
}
/* Digit value IGNORED */
/* NOTE: For superscript numbers there should be 'Digit value'
* but not 'Decimal digit value', But seems that there
* is bug on UNIDATA2.TXT, and therefore values is given
* also on 'Decimal gigit value'. For example:
*
2070;SUPERSCRIPT ZERO;No;0;EN;<super> 0030;0;0;0;N;SUPERSCRIPT DIGIT ZERO;;;;
*
* Because of this, fields 'Digit value' and 'Decimal
* digit value' are identical.
*/
/* Read field 8 Numeric value */
ptr = read_field(fp,&c,numeric_buffer,sizeof numeric_buffer,logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,numeric_buffer,c);
goto fail;
}
/* Numeric value IGNORED */
/* Read field 9 */
ptr = read_field(fp,&c,mirror_buffer,sizeof mirror_buffer,logfile);
if (EOF == c)
goto got_eof;
if (1 != ptr || c != ';') {
format_error(logfile,filename,line_number,mirror_buffer,c);
goto fail;
}
ptr = lookup_code(mirrored,mirror_buffer);
if (!mirrored[ptr].name) {
format_error(logfile,filename,line_number,mirror_buffer,c);
goto fail;
}
buffer->direction |= mirrored[ptr].code;
/* Read field 10 Unicode 1.0 Name */
ptr = read_field(fp,&c,unicode10_buffer,sizeof unicode10_buffer,
logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,unicode10_buffer,c);
goto fail;
}
/* Unicode 1.0 Name IGNORED */
/* Read field 11 10646 Comment field */
ptr = read_field(fp,&c,comment_buffer,sizeof comment_buffer, logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,comment_buffer,c);
goto fail;
}
/* 10646 Comment field IGNORED */
/* Read field 12 Upper case equivalent mapping */
ptr = read_field(fp,&c,upper_buffer,sizeof upper_buffer, logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,upper_buffer,c);
goto fail;
}
if (0 != ptr) {
if (4 != ptr) {
format_error(logfile,filename,line_number,upper_buffer,c);
goto fail;
}
buffer->upper = strtol(upper_buffer,&endptr,16);
if ('\0' != *endptr) {
format_error(logfile,filename,line_number,upper_buffer,c);
goto fail;
}
buffer->flags |= FLAGS_have_upper;
}
/* Read field 13 Lower case equivalent mapping */
ptr = read_field(fp,&c,lower_buffer,sizeof lower_buffer, logfile);
if (EOF == c)
goto got_eof;
if (c != ';') {
format_error(logfile,filename,line_number,lower_buffer,c);
goto fail;
}
if (0 != ptr) {
if (4 != ptr) {
format_error(logfile,filename,line_number,lower_buffer,c);
goto fail;
}
buffer->lower = strtol(lower_buffer,&endptr,16);
if ('\0' != *endptr) {
format_error(logfile,filename,line_number,lower_buffer,c);
goto fail;
}
buffer->flags |= FLAGS_have_lower;
}
/* Read field 14 Title case equivalent mapping */
ptr = read_field(fp,&c,title_buffer,sizeof title_buffer, logfile);
if (EOF == c)
goto got_eof;
if (c != '\n') {
format_error(logfile,filename,line_number,title_buffer,c);
goto fail;
}
if (0 != ptr) {
if (4 != ptr) {
format_error(logfile,filename,line_number,title_buffer,c);
goto fail;
}
buffer->title = strtol(title_buffer,&endptr,16);
if ('\0' != *endptr) {
format_error(logfile,filename,line_number,title_buffer,c);
goto fail;
}
buffer->flags |= FLAGS_have_title;
}
status = 1;
got_eof:
if (EOF == c) {
int err = errno;
status = 0;
if (ferror(fp)) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeGotError,
"Unexpected error on %.50s, line %d: %.30s"),
filename,*line_number,error_description(err));
if (logfile) {
fprintf(logfile,"<-- [ERROR]\n");
fprintf(logfile,catgets(elm_msg_cat, MeSet, MeGotError,
"Unexpected error on %.50s, line %d: %.30s"),
filename,*line_number,error_description(err));
putc('\n',logfile);
}
} else {
lib_error(CATGETS(elm_msg_cat, MeSet, MeGotEOF,
"Unexpected end of %.50s, line %d"),
filename,*line_number);
if (logfile) {
fprintf(logfile,"<-- [ERROR]\n");
fprintf(logfile,catgets(elm_msg_cat, MeSet, MeGotEOF,
"Unexpected end of %.50s, line %d"),
filename,*line_number);
putc('\n',logfile);
}
}
}
fail:
/* If we are not on end of line because of error,
* go to end of line.
*/
while (EOF != c && '\n' != c) {
c = fgetc(fp);
if (logfile && EOF != c) {
putc(c,logfile);
}
}
if ('\n' == c)
(*line_number)++;
if (EOF == c && logfile) {
fprintf(logfile,"<-- [EOF]\n");
}
return status;
}
static int same_char_cell_1 P_((struct char_cell_1 *p1,
struct char_cell_1 *p2));
static int same_char_cell_1(p1,p2)
struct char_cell_1 *p1;
struct char_cell_1 *p2;
{
if (p1->chartype != p2->chartype)
return 0;
if (p1->class != p2->class)
return 0;
if (p1->direction != p2->direction)
return 0;
if (p1->flags != p2->flags)
return 0;
if (0 != (p1->flags & FLAGS_have_decimal) && p1->decimal != p2->decimal)
return 0;
if (0 != (p1->flags & FLAGS_have_decomp) && p1->decomp != p2->decomp)
return 0;
if (0 != (p1->flags & FLAGS_have_upper) && p1->upper != p2->upper)
return 0;
if (0 != (p1->flags & FLAGS_have_lower) && p1->lower != p2->lower)
return 0;
if (0 != (p1->flags & FLAGS_have_title) && p1->title != p2->title)
return 0;
return 1;
}
static int push_decomp_cell P_((struct decomp_cell_1 buffer,
struct unidata_format_1 *v));
static int push_decomp_cell(buffer,v)
struct decomp_cell_1 buffer;
struct unidata_format_1 *v;
{
if (v->decomp_cells_count <
v->decomp_cells_length / sizeof (struct decomp_cell_1)) {
int idx = v->decomp_cells_count;
if (buffer.len_byte > 0) {
uint16 code = v->decomp_storage[buffer.storage];
while (code >= v->comp_vector_count) {
if (v->comp_vector_count >=
v->comp_vector_length / sizeof (uint16)) {
return -1; /* OVERFLOW */
}
/* add_decompostion should guarantee that first cell
* is unassigned
*/
v->comp_vector[v->comp_vector_count++] = 0x0000;
}
if (code < v->comp_vector_count) {
buffer.next_comp = v->comp_vector[code];
v->comp_vector[code] = idx;
} else
buffer.next_comp = 0;
} else {
DPRINT(Debug,5,(&Debug,
"unidata: push_decomp_cell (idx=%d (%04X)) -- zero decomposition\n",
idx,idx));
buffer.next_comp = 0;
}
v->decomp_cells[idx] = buffer;
v->decomp_cells_count++;
return idx;
}
return -1;
}
static int add_decomposition P_((char *decomposition_buffer,
int line_number,
CONST char *filename,
struct unidata_format_1 *v,
uint16 *decomp, FILE *logfile,
unsigned int code1));
static int add_decomposition(decomposition_buffer,
line_number,
filename,v,decomp,
logfile,code1)
char *decomposition_buffer;
int line_number;
CONST char *filename;
struct unidata_format_1 *v;
uint16 *decomp;
FILE *logfile;
unsigned int code1;
{
int status = 0;
char *brk = safe_strdup(decomposition_buffer);
char *ptr;
struct decomp_cell_1 buffer;
int code;
if (v->decomp_cells_count == 0)
push_decomp_cell(unassigned_decomp_buffer,v);
buffer.type_byte = 0;
buffer.len_byte = 0;
buffer.next_comp = 0;
buffer.storage = v -> decomp_storage_count;
buffer.value = code1;
/* Initial modifier */
if ('<' == brk[0]) {
int ptr1;
ptr = strtok(brk," ");
ptr1 = lookup_code(decomp_compat,ptr);
if (!decomp_compat[ptr1].name) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeFormatError,
"Format error on %.50s, line %d: %s"),
filename,line_number,ptr);
if (logfile) {
fprintf(logfile,catgets(elm_msg_cat, MeSet, MeFormatError,
"Format error on %.50s, line %d: %s"),
filename,line_number,ptr);
putc('\n',logfile);
}
goto fail;
}
buffer.type_byte = decomp_compat[ptr1].code;
ptr = NULL;
} else {
buffer.type_byte = 0;
ptr = brk;
}
for (ptr = strtok(ptr," "); ptr; ptr = strtok(NULL," ")) {
char *endptr;
long l;
if (v -> decomp_storage_count >=
v->decomp_storage_length / sizeof (uint16))
goto fail; /* OVERFLOW */
v->decomp_storage[v -> decomp_storage_count] =
l = strtol(ptr,&endptr,16);
if ('\0' != *endptr ||
v->decomp_storage[v -> decomp_storage_count] != l) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeFormatError,
"Format error on %.50s, line %d: %s"),
filename,line_number,ptr);
if (logfile) {
fprintf(logfile,catgets(elm_msg_cat, MeSet, MeFormatError,
"Format error on %.50s, line %d: %s"),
filename,line_number,ptr);
putc('\n',logfile);
}
goto fail;
}
buffer.len_byte = (++v -> decomp_storage_count) - buffer.storage;
if (v -> decomp_storage_count - buffer.storage > 255) {
/* OVERFLOW */
goto fail;
}
}
*decomp = code = push_decomp_cell(buffer,v);
if (code < 1 || *decomp != code)
goto fail;
status = 1;
fail:
free(brk);
return status;
}
int read_unidata_text(ptr,filename,logfile, silent_gaps)
struct unidata_mapped_data **ptr;
CONST char *filename;
FILE *logfile;
int silent_gaps;
{
struct unidata_mapped_data * res = *ptr;
int status = 0;
FILE *f;
int last_processed = -1;
int line_number = 1;
int unassigned_cell = -1;
char composition_buffer[160];
/* This should not have readed by setgid Elm ME+
so this test is not necessary */
int err = can_open(filename,"r");
if (err) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeUnidataCantOpen,
"Can't open UNIDATA2.TXT: %.50s: %.25s"),
filename,error_description(err));
return 0;
}
f = fopen(filename,"r");
if (!f) {
int err = errno;
lib_error(CATGETS(elm_msg_cat, MeSet, MeUnidataCantOpen,
"Can't open UNIDATA2.TXT: %.50s: %.25s"),
filename,error_description(err));
goto fail;
}
if (res)
free_unidata(res);
res = NULL;
res = safe_malloc(sizeof (struct unidata_mapped_data));
res->format = unidata_format_1;
/* malloc maximally needed area */
malloc_unidata_1(&(res->v.f1));
status = 1;
while (!feof(f)) {
struct char_cell_1 temp_buffer;
char temp_name_buffer[100], *point;
uint16 code,cell;
if (!read_line(f,&temp_buffer,&code,
temp_name_buffer, sizeof temp_name_buffer,
&line_number, filename, logfile,
composition_buffer,
sizeof composition_buffer)) {
if (feof(f))
break;
status = 0; /* FAILURE */
continue;
}
if (composition_buffer[0]) {
if (!add_decomposition(composition_buffer,line_number-1,
filename,&(res->v.f1),
&temp_buffer.decomp,logfile,code)) {
status = 0; /* FAILURE */
continue;
}
temp_buffer.flags |= FLAGS_have_decomp;
}
if (status && last_processed+1 != code) {
if (!silent_gaps) {
lib_error(CATGETS(elm_msg_cat, MeSet, MeSequenceError,
"%.50s, line %d: Got %d (%04X), exptected %d (%04X)"),
filename,line_number-1,code,code,
last_processed+1,last_processed+1);
}
if (logfile) {
fprintf(logfile,catgets(elm_msg_cat, MeSet, MeSequenceError,
"%.50s, line %d: Got %d (%04X), exptected %d (%04X)"),
filename,line_number-1,code,code,
last_processed+1,last_processed+1);
putc('\n',logfile);
/* Do not log failure... */
}
}
last_processed = code;
/* simple compression */
if (res->v.f1.cells_count < 1 ||
!same_char_cell_1(&(res->v.f1.cells[res->v.f1.cells_count-1]),
&temp_buffer)) {
if (res->v.f1.cells_count <
res->v.f1.cells_length / sizeof (struct char_cell_1)) {
cell = res->v.f1.cells_count;
res->v.f1.cells[cell] = temp_buffer;
res->v.f1.cells_count = cell+1;
} else
break; /* OVERFLOW */
} else
cell = res->v.f1.cells_count-1;
if (code < res->v.f1.vector_length / sizeof (uint16)) {
while (res->v.f1.vector_count < code) {
if (unassigned_cell == -1) {
if (res->v.f1.cells_count <
res->v.f1.cells_length / sizeof (struct char_cell_1)) {
unassigned_cell = res->v.f1.cells_count;
res->v.f1.cells[unassigned_cell] =
unassigned_cell_buffer;
res->v.f1.cells_count = unassigned_cell+1;
} else
break; /* OVERFLOW */
}
res->v.f1.vector[res->v.f1.vector_count++] = unassigned_cell;
}
res->v.f1.vector[code] = cell;
if (res->v.f1.vector_count <= code)
res->v.f1.vector_count++;
} else
break; /* OVERFLOW */
if ('<' == temp_name_buffer[0] &&
(point = strchr(temp_name_buffer,',')) &&
0 == strcmp(point,", First>")) {
int n = point - temp_name_buffer;
struct char_cell_1 temp_buffer2;
char temp_name_buffer2[100], *point2;
uint16 code2;
char composition_buffer2[160];
/* Whole range actually */
if (!read_line(f,&temp_buffer2,&code2,
temp_name_buffer2, sizeof temp_name_buffer2,
&line_number, filename, logfile,
composition_buffer2, sizeof composition_buffer2)) {
status = 0; /* FAILURE */
continue;
}
if (temp_buffer.flags & FLAGS_have_decomp) {
temp_buffer2.flags |= FLAGS_have_decomp;
temp_buffer2.decomp = temp_buffer.decomp;
}
if ('<' == temp_name_buffer2[0] &&
(point2 = strchr(temp_name_buffer2,',')) &&
0 == strcmp(point2,", Last>") &&
n == point2 - temp_name_buffer2 &&
0 == strncmp(temp_name_buffer,temp_name_buffer2,n) &&
code2 > code &&
0 == strcmp(composition_buffer,composition_buffer2) &&
same_char_cell_1(&temp_buffer,&temp_buffer2)) {
if (code2 < res->v.f1.vector_length / sizeof (uint16)) {
int i;
for (i = code; i <= code2; i++)
res->v.f1.vector[i] = cell;
if (res->v.f1.vector_count <= code2)
res->v.f1.vector_count = code2+1;
last_processed = code2;
} else
break; /* OVERFLOW */
} else {
lib_error(CATGETS(elm_msg_cat, MeSet, MeNotEndRange,
"%.50s: %d: %.25s is not end for %.25s"),
filename,line_number-1,
temp_name_buffer2,temp_name_buffer2);
if (logfile) {
fprintf(logfile,
catgets(elm_msg_cat, MeSet, MeNotEndRange,
"%.50s: %d: %.25s is not end for %.25s"),
filename,line_number-1,
temp_name_buffer2,temp_name_buffer2);
putc('\n',logfile);
}
status = 0;
}
}
}
if (status && last_processed != 0xFFFF) {
if (!silent_gaps)
lib_error(CATGETS(elm_msg_cat, MeSet, MeIncomplete,
"%.50s: Last processed was %d, should be %d"),
filename,last_processed,0xFFFF);
if (logfile) {
fprintf(logfile,
catgets(elm_msg_cat, MeSet, MeIncomplete,
"%.50s: Last processed was %d, should be %d"),
filename,last_processed,0xFFFF);
putc('\n',logfile);
}
}
/* recalculate space according of usage and
* zero fill unused area
*/
trim_unidata_1(&(res->v.f1));
debug_output(&(res->v.f1),status,
res->v.f1.header ?
READ_VALUE(res->v.f1.header->page_size,
res->v.f1.byte_swapped) :
0,"text",filename);
fail:
if (f)
fclose(f);
*ptr = res;
return status;
}
static int unicode_compress_input_1 P_((struct unidata_format_1 *v,
uint16 *unicode_res,
uint16 unicode_inp[],
int len,
int *comp_type));
int unicode_compress_input_1(v,unicode_res,unicode_inp,len,comp_type)
struct unidata_format_1 *v;
uint16 *unicode_res;
uint16 unicode_inp[];
int len;
int *comp_type;
{
int status = 0;
if (len < 1)
status = -1;
else {
uint16 idx = unicode_inp[0];
if (idx < v ->comp_vector_count) {
uint16 ptr = READ_VALUE(v->comp_vector[idx],v->byte_swapped);
int found = 0;
status = 0;
while(ptr != 0 && ptr < v->decomp_cells_count && !found) {
struct decomp_cell_1 *C = &v->decomp_cells[ptr];
uint16 storage = READ_VALUE(C->storage,v->byte_swapped);
uint8 len_1 = C->len_byte;
if (storage + len_1 <= v->decomp_storage_count) {
int i;
found = 1;
for (i = 0; i < len_1 && i < len; i++)
if (unicode_inp[i] !=
READ_VALUE(v->decomp_storage[storage+i],
v->byte_swapped))
found = 0;
if (found) {
*unicode_res = READ_VALUE(C->value,
v->byte_swapped);
*comp_type = C->type_byte;
if (i < len_1)
status = -1;
else
status = i;
}
}
ptr = READ_VALUE(C->next_comp,v->byte_swapped);
}
}
else
status = 0;
}
return status;
}
static int unicode_lookup_character_1 P_((struct unidata_format_1 *v,
unsigned int unicode,
struct character_information *info,
uint16 unicode_out[],
int buffer_len));
static int unicode_lookup_character_1(v,unicode,info,unicode_out,buffer_len)
struct unidata_format_1 *v;
unsigned int unicode;
struct character_information *info;
uint16 unicode_out[];
int buffer_len;
{
int status = -1;
info -> character_type = CHARTYPE_Cn;
info -> direction_data = 0;
info -> mirror_code = 0;
info -> upper = 0;
info -> lower = 0;
info -> title = 0;
info -> decomp_len = 0;
if (buffer_len > 0) { /* Pre-init buffer */
int i;
unicode_out[0] = unicode;
for (i = 1; i < buffer_len; i++)
unicode_out[i] = 0;
}
if (unicode < v -> vector_count) {
uint16 ptr = v->vector[unicode];
if (ptr < v -> cells_count) {
struct char_cell_1 *C = &(v->cells[ptr]);
uint16 chartype = READ_VALUE(C->chartype,v->byte_swapped);
uint16 class = READ_VALUE(C->class,v->byte_swapped);
uint16 direction = READ_VALUE(C->direction,v->byte_swapped);
uint16 decomp = READ_VALUE(C->decomp,v->byte_swapped);
uint16 decimal = READ_VALUE(C->decimal,v->byte_swapped);
uint16 flags = READ_VALUE(C->flags,v->byte_swapped);
uint16 upper = READ_VALUE(C->upper,v->byte_swapped);
uint16 lower = READ_VALUE(C->lower,v->byte_swapped);
uint16 title = READ_VALUE(C->title,v->byte_swapped);
uint16 mirror_code = 0xF000 & direction;
direction -= mirror_code;
info -> character_type = chartype;
info -> direction_data = direction;
info -> mirror_code = mirror_code;
if (flags & FLAGS_have_upper) {
info -> upper = upper;
}
if (flags & FLAGS_have_lower) {
info -> lower = lower;
}
if (flags & FLAGS_have_title) {
info -> title = title;
}
if (flags & FLAGS_have_decomp) {
if (decomp < v->decomp_cells_count) {
struct decomp_cell_1 *D = &(v->decomp_cells[decomp]);
uint16 storage = READ_VALUE(D->storage,
v->byte_swapped);
#if 0
uint8 type_byte = D->type_byte;
#endif
uint8 len_byte = D->len_byte;
if (storage + len_byte <= v->decomp_storage_count) {
if (buffer_len > 0) {
int i;
for (i = 0;
i < len_byte &&
i < buffer_len;
i++)
unicode_out[i] =
READ_VALUE(v->decomp_storage[storage+i],
v->byte_swapped);
}
info -> decomp_len = len_byte;
}
}
}
} else
return -1;
} else
return -1;
switch(CHARTYPE_major(info -> character_type)) {
case CHARTYPE_Mark:
case CHARTYPE_Number:
case CHARTYPE_Separator:
case CHARTYPE_Letter:
case CHARTYPE_Punctuation:
case CHARTYPE_Symbol:
status = 1;
break;
default:
status = 0;
break;
}
#ifdef DEBUG
if (status < 1) {
DPRINT(Debug,63,(&Debug,
"unicode_lookup_character_1: %04X: type=%d (%04X),",
unicode,info -> character_type,info -> character_type));
if (Debug.active > 62) {
int ptr = lookup_from_code(categories,info -> character_type);
if (categories[ptr].name) {
DPRINT(Debug,63,(&Debug," type=%s,",categories[ptr].name));
}
DPRINT(Debug,63,(&Debug,", return %d\n",status));
}
}
#endif
return status;
}
/* Note: buffer_len == 0 if not unicode decompression wanted
buffer_len : on bytes (sizeof)
Returns 0 = failure (not valid character)
1 = succeed
-1 = database bad
*/
int unicode_lookup_character(v,unicode,info, unicode_out, buffer_len)
struct unidata_mapped_data *v;
unsigned int unicode;
struct character_information *info;
uint16 unicode_out[];
int buffer_len;
{
int status = -1;
switch(v->format) {
case unidata_format_1:
status = unicode_lookup_character_1(&(v->v.f1),unicode,info,
unicode_out, buffer_len);
break;
}
return status;
}
/* Returns = 0 failure (not compressable)
= 1 (one-to-one mapping)
> 0 compressed input returned
= -1 incomplete input
*/
int unicode_compress_input(v,unicode_res,unicode_inp,len,comp_type)
struct unidata_mapped_data *v;
uint16 *unicode_res;
uint16 unicode_inp[];
int len;
int *comp_type;
{
int status = 0;
switch(v->format) {
case unidata_format_1:
status = unicode_compress_input_1(&(v->v.f1),
unicode_res,unicode_inp,len,
comp_type);
break;
}
return status;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1