[BACK]Return to libcode.c CVS log [TXT][DIR] Up to [jp.NetBSD.org] / othersrc / mgl / mgl2 / ext

File: [jp.NetBSD.org] / othersrc / mgl / mgl2 / ext / libcode.c (download)

Revision 1.1, Sun Apr 1 08:13:49 2001 UTC (16 years, 10 months ago) by suz
Branch: MAIN
CVS Tags: HEAD



mglext --- mgl 拡張機能

このライブラリは、kaffe を MGL に移植する際、必要だった機能のうち
切り出せるものをまとめたものです

/*
 * LIBCODE -- Code Converter Library -
 * Copyright (C) 2001
 *      Koji Suzuki (suz@at.sakura.ne.jp)
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY KOJI SUZUKI ``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 TERRENCE R. LAMBERT 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 <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

static inline int libcode_hash(int c,int sz) {
        int cc;
        cc = ((c << 8) & 0xff00 ) | ((c >> 8) & 0xff);
        cc = cc ^ 0x5555;
        cc = (cc % sz);
        return cc;
}

struct libcode_context {
	unsigned char *atob;
	unsigned char *btoa;
	int size_a;
	int size_b;
	int type;
};

static struct libcode_context *libcode_open(char *code_a,char *code_b);
static void libcode_close(struct libcode_context *lc);
static int libcode_convert(struct libcode_context *lc,int c);

#define LIBCODE_MAGIC_ARRAY "LC_ARRAY   0001"
#define LIBCODE_MAGIC_HASH  "LC_HASH    0001"

#ifdef LIBCODE_DIR
#define prefix LIBCODE_DIR
#else
//#define prefix "/usr/local/share/libcode"
#define prefix "."
#endif

#ifndef NULL
#define NULL (void *)0
#endif

static struct libcode_context *libcode_open(char *code_a,char *code_b) {
	int fd_a,fd_b,type,len;
	char fname[256];
	char magic[16];
	char *p;
	unsigned char *atob,*btoa;
	struct libcode_context *lc;

	strcpy(fname,prefix);
	strcat(fname,"/");
	strcat(fname,code_a);
	strcat(fname,"-");
	strcat(fname,code_b);
	p = fname + strlen(fname);
	strcpy(p,".array");
	fd_a = open(fname,O_RDONLY);

	if (fd_a >= 0) {
fprintf(stderr,"-- opened %s\n",fname);
		len = lseek(fd_a,0,SEEK_END);
		atob = mmap(NULL, len, PROT_READ, MAP_SHARED, fd_a, 0);
		if ((atob) == (void *)(-1)) {
			close(fd_a);
			return NULL;
		}
		close(fd_a);
		lc = malloc(sizeof(*lc));
		if (!lc) return NULL;
		memset(lc,0,sizeof(*lc));
		lc->type = 1;
		lc->atob = atob;
		lc->size_a = (len-16)/2;
		if (strcmp(LIBCODE_MAGIC_ARRAY,atob)) {
			libcode_close(lc);
			return NULL;
		}
		return lc;
	} else {
		strcpy(p,".hash");
		fd_a = open(fname,O_RDONLY);
		if (fd_a < 0) {
			return NULL;
		}
fprintf(stderr,"-- opened %s\n",fname);
		len = lseek(fd_a,0,SEEK_END);
		atob = mmap(NULL, len, PROT_READ, MAP_SHARED, fd_a, 0);
		if ((atob) == (void *)(-1)) {
			close(fd_a);
			return NULL;
		}
		close(fd_a);
		lc = malloc(sizeof(*lc));
		if (!lc) return NULL;
		memset(lc,0,sizeof(*lc));
		lc->type = 2;
		lc->atob = atob;
		lc->size_a = (len-16)/2;
		

		strcpy(fname,prefix);
		strcat(fname,"/");
		strcat(fname,code_b);
		strcat(fname,"-");
		strcat(fname,code_a);
		p = fname + strlen(fname);
		strcpy(p,".array");
		fd_b = open(fname,O_RDONLY);
		if (fd_b < 0) {
			munmap(atob,len);
			free(lc);
			return NULL;
		}
		len = lseek(fd_b,0,SEEK_END);
		btoa = mmap(NULL, len, PROT_READ, MAP_SHARED, fd_b, 0);
		if ((btoa) == (void *)(-1)) {
			munmap(atob,len);
			free(lc);
			close(fd_b);
			return NULL;
		}
		close(fd_b);
		lc->btoa = btoa;
		lc->size_b = (len-16)/2;
		if (strcmp(LIBCODE_MAGIC_ARRAY,btoa) || strcmp(LIBCODE_MAGIC_HASH,atob)) {
			libcode_close(lc);
			return NULL;
		}
		return lc;
	}
	return NULL;
}

static void
libcode_close(struct libcode_context *lc) {
	munmap(lc->atob,lc->size_a*2 + 16);
	munmap(lc->btoa,lc->size_b*2 + 16);
	free(lc);
}

static inline getcode(unsigned char *p, int idx) {
	return p[(idx << 1)+16] + ((int)p[(idx << 1)+1+16] << 8);
}

static int libcode_convert(struct libcode_context *lc,int c) {
	if (lc->type == 1) {
		int cc;
		if ((c < 0) || (c >= lc->size_a)) return -1;
		cc = getcode(lc->atob,c);
		if (cc == 0xffff) return -1;
		return cc;
	} else if (lc->type == 2) {
		int i,n,base_idx,idx;
		int cc,c2;
		n = lc->size_a;
		base_idx = libcode_hash(c,n);
		for (i=0; i< n; i++) {
			idx = base_idx + i;
			if (idx >= n) idx = 0;
			cc = getcode(lc->atob,idx);
			if (cc == 0xffff) return -1;
			if (cc >= lc->size_b) return -1;
			c2 = getcode(lc->btoa,cc);
			if (c2 == c) {
				return cc;
			}
		}
	}
	return -1;
}

static struct libcode_context *lc_uc_jis;
static struct libcode_context *lc_jis_uc;

int mglcode_init() {
	lc_uc_jis = libcode_open("unicode11","jisx208");
	lc_jis_uc = libcode_open("jisx208","unicode11");
	if (lc_uc_jis && lc_jis_uc) return 0;
	return -1;
}

int mglcode_from_uc(int c) {
	int cc,c1,c2;

	if (c < 0x100) return c;

	cc = 0xffff;
	if (lc_uc_jis) {
		cc = libcode_convert(lc_uc_jis,c);
	}
	if (cc == 0xffff)  {
		cc = 0xa2ab; /* GETA */
	} else {
		c1 = ( (cc / 96)+ 0x21) | 0x80;
		c2 = ( (cc % 96)+ 0x21) | 0x80;
		cc = (c1 << 8) | c2;
	}
	return cc;
}

int mglcode_to_uc(int c) {
	int cc,c1,c2;

	if (c < 0x100) return c;
	cc = 0xffff;
	if (lc_jis_uc || (c & 0x8080)) {
		c1 = ((c >> 8) & 0x7f) - 0x21;
		c2 = (c & 0x7f) - 0x21;
		c = c1 * 96 + c2;
		cc = libcode_convert(lc_jis_uc,c);
	}
	if (cc == 0xffff)  {
		cc = 0x3013; /* GETA */
	}
	return cc;
}