/*
 * Copyright (c) 1999 Sun Microsystems, Inc.
 * Copyright (c) 1999 Nihon Sun Microsystems K.K.
 * All rights reserved.
 */

/*
 * "$Id: euc_ct_set_comp.c,v 1.1.1.1 2000/10/29 16:44:42 himi Exp $"
 */

#pragma ident	"@(#)euc_ct_set_comp.c 1.5	99/05/18 SMI"


#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <sys/param.h>

#include "csc_conf_info.h"
#include "ct_map.h"
#include "euc_ct_set.h"
#include "utf16_ct_map.h"


#define RIGHT_MASK		(0x8080)
#define EUC_CT_SET_C		"euc_ct_set.c"


void *
malloc_vital(size_t size)
{
	void *	p;

	if (NULL == (p = malloc(size))) {
		perror("malloc");
		exit(1);
	}

	memset(p, 0, size);

	return p;
}


euc_ct_set_conf_t *
parse_euc_ct_set_conf()
{
	csc_conf_file_t	*	conf_file;
	csc_conf_str_t		conf_str[16];
	csc_conf_str_t *	csp;
	euc_ct_set_conf_t *	euc_ct_set_conf_first;
	euc_ct_set_conf_t *	euc_ct_set_conf_last;
	euc_ct_set_conf_t *	ectmp;
	int			num;
	int			i;
	int			n;

	conf_file = csc_conf_open(EUC_CT_SET_CONF, 0, NULL, 0);
	if (NULL == conf_file) {
		fprintf(stderr, "failed to open %s\n", EUC_CT_SET_CONF);
		exit(1);
	}

	euc_ct_set_conf_first = NULL;
	euc_ct_set_conf_last = NULL;

	while (0 < (num = csc_conf_read(conf_file, conf_str, 13))) {
		ectmp = malloc_vital(sizeof (ct_map_conf_t));
		if (NULL == euc_ct_set_conf_last) {
			euc_ct_set_conf_first = ectmp;
			euc_ct_set_conf_last = ectmp;
		} else {
			euc_ct_set_conf_last->next = ectmp;
			euc_ct_set_conf_last = ectmp;
		}
		ectmp->next = NULL;

		ectmp->euc_id = malloc_vital(conf_str[0].len + 1);
		memcpy(ectmp->euc_id, conf_str[0].ptr, conf_str[0].len);
		*(ectmp->euc_id + conf_str[0].len) = '\0';

		for (i = 0, n = 1; i < 4; i++, n += 3) {
			if (num <= n) {
				ectmp->cs_name[i] = NULL;
				ectmp->cs_glgr[i] = (-1);
				ectmp->cs_len[i] = 0;
				continue;
			}

			ectmp->cs_name[i] = malloc_vital(conf_str[n].len + 1);
			memcpy(ectmp->cs_name[i],
			       conf_str[n].ptr, conf_str[n].len);
			*(ectmp->cs_name[i] + conf_str[n].len) = '\0';

			csp = (conf_str + (n + 1));
			if (0 == csc_strcmp(ENC_GL_STR, csp)) {
				ectmp->cs_glgr[i] = ENC_GL;
			} else 	if (0 == csc_strcmp(ENC_GR_STR, csp)) {
				ectmp->cs_glgr[i] = ENC_GR;
			} else 	if (0 == csc_strcmp(ENC_GLGR_STR, csp)) {
				ectmp->cs_glgr[i] = ENC_GLGR;
			} else {
				fprintf(stderr,
					"invalid ENC_GL_GR value: %.*s\n",
					csp->len, csp->ptr);
				exit(1);
			}

			csp = (conf_str + (n + 2));
			ectmp->cs_len[i] = strtol(csp->ptr, NULL, 0);
			if (ectmp->cs_len[i] <= 0) {
				fprintf(stderr,
					"invalid cs_len: %d\n",
					ectmp->cs_len[i]);
				exit(1);
			}
		}
	}
	csc_conf_close(conf_file);

	return euc_ct_set_conf_first;
}


void
dump_euc_ct_map(
	const ct_map_conf_t *		ct_map_conf,
	const euc_ct_set_conf_t *	euc_ct_set_conf)
{
	FILE *				fp;
	const ct_map_conf_t *		ctmc;
	const euc_ct_set_conf_t *	ectmc;
	const char *			p;
	int				i;
	int				j;
	int				n;
	unsigned int			cs_id;

	fp = fopen(EUC_CT_SET_C, "w");
	if (NULL == fp) {
		perror("fopen");
		fprintf(stderr, "cannot open %s\n", EUC_CT_SET_C);
		exit(1);
	}

	fprintf(fp, "#include \"config.h\"\n");
	fprintf(fp, "#include <stddef.h>\n");
	fprintf(fp, "#include \"euc_ct_set.h\"\n");
	fprintf(fp, "\n");

	cs_id = 0;
	for (ectmc = euc_ct_set_conf; NULL != ectmc; ectmc = ectmc->next) {
		for (i = 0; i < 4; i++) {
			if (NULL == ectmc->cs_name[i]) {
				continue;
			}

			for (ctmc = ct_map_conf;
			     NULL != ctmc; ctmc = ctmc->next) {
				if (0 != strcmp(ectmc->cs_name[i],
						ctmc->enc_name)) {
					continue;
				}
				if (ectmc->cs_glgr[i] != ctmc->enc_gl_gr) {
					continue;
				}

				if (ctmc->cs_id & cs_id) {
					break;
				} else {
					cs_id |= ctmc->cs_id;
				}

				fprintf(fp, "static const unsigned char\t");
				fprintf(fp, "%s[] = {", ctmc->design_name);
				for (j = 0; j < (ctmc->design_length - 1); j++) {
					fprintf(fp, "0x%02x, ",
						*(ctmc->design_str + j));
				}
				fprintf(fp, "0x%02x};\n",
					*(ctmc->design_str + j));
				break;
			}
		}
	}

	fprintf(fp, "\n");
	fprintf(fp, "const csc_euc_ct_set_t	euc_ct_set[] = {\n");

	for (ectmc = euc_ct_set_conf; NULL != ectmc; ectmc = ectmc->next) {
		fprintf(fp, "\t{\n");
		fprintf(fp, "\t\t\"%s\",\n", ectmc->euc_id);
		fprintf(fp, "\t\t{\n");
		for (i = 0; i < 4; i++) {
			if (NULL == ectmc->cs_name[i]) {
				fprintf(fp, "\t\t\t{NULL,\t\t0, 0, NULL,\t\t0}");
				if (i != 3) {
					fputc(',', fp);
				}
				fputc('\n', fp);
				continue;
			}

			for (ctmc = ct_map_conf;
			     NULL != ctmc; ctmc = ctmc->next) {
				if (0 != strcmp(ectmc->cs_name[i],
						ctmc->enc_name)) {
					continue;
				}
				if (ectmc->cs_glgr[i] != ctmc->enc_gl_gr) {
					continue;
				}
				fprintf(fp, "\t\t\t{");
				fprintf(fp, "\"%s\"", ctmc->enc_name);
				fprintf(fp, ",\t");
				fprintf(fp, "%d", ectmc->cs_len[i]);
				fprintf(fp, ", ");
				fprintf(fp, "%d", ctmc->extended_segment);
				fprintf(fp, ", ");
				fprintf(fp, "%d", ectmc->cs_glgr[i]);
				fprintf(fp, ", ");
				fprintf(fp, "%s", ctmc->design_name);
				fprintf(fp, ",\t");
				fprintf(fp, "%d}", ctmc->design_length);
				break;
			}
			if (NULL == ctmc) {
				fprintf(fp, "\t\t\t{NULL,\t\t0, 0, 0, NULL,\t\t0},\n");
			}
			if (i != 3) {
				fputc(',', fp);
			}
			fputc('\n', fp);
		}
		fprintf(fp, "\t\t}\n");
		fprintf(fp, "\t},\n");
	}

	fprintf(fp, "\t{\tNULL,\n");
	fprintf(fp, "\t\t{\n");
	fprintf(fp, "\t\t\t{NULL,\t\t0, 0, 0, NULL,\t\t0},\n");
	fprintf(fp, "\t\t\t{NULL,\t\t0, 0, 0, NULL,\t\t0},\n");
	fprintf(fp, "\t\t\t{NULL,\t\t0, 0, 0, NULL,\t\t0},\n");
	fprintf(fp, "\t\t\t{NULL,\t\t0, 0, 0, NULL,\t\t0}\n");
	fprintf(fp, "\t\t}\n");
	fprintf(fp, "\t}\n");
	fprintf(fp, "};\n");

	fclose(fp);

	return;
}


int
main(int argc, char ** argv)
{
	ct_map_conf_t *		ct_map_conf;
	euc_ct_set_conf_t *	euc_ct_set_conf;

	ct_map_conf = parse_ct_map_conf();
	if (NULL == ct_map_conf) {
		fprintf(stderr, "failed to parse %s\n", CT_MAP_CONF);
		exit(1);
	}

	euc_ct_set_conf = parse_euc_ct_set_conf();
	if (NULL == ct_map_conf) {
		fprintf(stderr, "failed to parse %s\n", EUC_CT_SET_CONF);
		exit(1);
	}

	dump_euc_ct_map(ct_map_conf, euc_ct_set_conf);

	return 0;
}
