1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12 
13 /* @(#)nls_file.c	1.3 05/05/01 2000 J. Schilling */
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License version 2
17  * as published by the Free Software Foundation.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License along with
25  * this program; see the file COPYING.  If not, write to the Free Software
26  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28 /*
29  *	Modifications to make the code portable Copyright (c) 2000 J. Schilling
30  *
31  * nls_file: create a charset table from a input table file
32  * from the Unicode Organization (www.unicode.org).
33  * The Unicode to charset table has only exact mappings.
34  *
35  * Only reads single byte to word matches.
36  *
37  * James Pearson (j.pearson@ge.ucl.ac.uk) 16-Aug-2000
38  */
39 
40 #include <mconfig.h>
41 #include <stdio.h>
42 #include <stdxlib.h>
43 #include <strdefs.h>
44 #include <libport.h>
45 #include "nls.h"
46 
47 #define	NUM	256
48 
49 static void	free_mem(struct unls_unicode *, unsigned char **);
50 
gethostid()51 static void
52 free_mem(struct unls_unicode *charset2uni, unsigned char **page_uni2charset)
53 {
54 	int	i;
55 
56 	if (charset2uni)
57 		free(charset2uni);
58 
59 	if (page_uni2charset) {
60 		for (i = 0; i < NUM; i++) {
61 			if (page_uni2charset[i]) {
62 				free(page_uni2charset[i]);
63 			}
64 		}
65 		free(page_uni2charset);
66 	}
67 }
68 
69 int
70 init_unls_file(char *filename)
71 {
72 	FILE	*fp;
73 	struct unls_unicode *charset2uni = NULL;
74 	unsigned char **page_uni2charset = NULL;
75 	char	buf[1024];
76 	char	*p;
77 	unsigned int	cp, uc;
78 	struct unls_table *table;
79 	int	i, ok = 0;
80 
81 	/* give up if no filename is given */
82 	if (filename == NULL)
83 		return (-1);
84 
85 	/*
86 	 * see if we already have a table with this name - built in tables
87 	 * have precedence of file tables - i.e. can't have the name of an
88 	 * existing table. Also, we may have already registered this file table
89 	 */
90 	if (find_unls(filename) != NULL)
91 		return (-1);
92 
93 	if ((fp = fopen(filename, "r")) == NULL)
94 		return (-1);
95 
96 	/* allocate memory for the forward conversion table */
97 	if ((charset2uni = (struct unls_unicode *)
98 			malloc(sizeof (struct unls_unicode) * NUM)) == NULL) {
99 		free_mem(charset2uni, page_uni2charset);
100 		return (-1);
101 	}
102 
103 	/* any unknown character should be mapped to NULL */
104 	memset(charset2uni, 0, sizeof (struct unls_unicode) * NUM);
105 
106 	/*
107 	 * some source files don't set the control characters 0x00 - 0x1f
108 	 * so set these by default
109 	 */
110 	for (i = 0; i < 32; i++) {
111 		charset2uni[i].unls_low = i;
112 	}
113 
114 	/* also set DELETE (0x7f) by default */
115 	charset2uni[0x7f].unls_low = 0x7f;
116 
117 	/* read each line of the file */
118 	while (fgets(buf, sizeof (buf), fp) != NULL) {
119 		/* cut off any comments */
120 		if ((p = strchr(buf, '#')) != NULL)
121 			*p = '\0';
122 
123 		/* look for two hex values */
124 		if (sscanf(buf, "%x%x", &cp, &uc) == 2) {
125 			/* if they are not in range - fail */
126 			if (cp > 0xff || uc > 0xffff) {
127 				continue;
128 			}
129 
130 			/* set the Unicode value for the given code point */
131 			charset2uni[cp].unls_low  = uc & 0xff;
132 			charset2uni[cp].unls_high = (uc >> 8) & 0xff;
133 
134 			/* make sure we find at least one pair ... */
135 			ok = 1;
136 		}
137 	}
138 
139 	fclose(fp);
140 
141 	if (!ok) {
142 		/* we haven't found anything ... */
143 		free_mem(charset2uni, page_uni2charset);
144 		return (-1);
145 	}
146 
147 	/* allocate memory for the reverse table */
148 	if ((page_uni2charset = (unsigned char **)
149 			malloc(sizeof (unsigned char *) * NUM)) == NULL) {
150 		free_mem(charset2uni, page_uni2charset);
151 		return (-1);
152 	}
153 
154 	memset(page_uni2charset, 0, sizeof (unsigned char *) * NUM);
155 
156 	/* loop through the forward table, setting the reverse value */
157 	for (i = 0; i < NUM; i++) {
158 		uc = charset2uni[i].unls_high;
159 		cp = charset2uni[i].unls_low;
160 		/* if the page doesn't exist, create a page */
161 		if (page_uni2charset[uc] == NULL) {
162 			if ((page_uni2charset[uc] =
163 				(unsigned char *) malloc(NUM)) == NULL) {
164 				free_mem(charset2uni, page_uni2charset);
165 				return (-1);
166 			}
167 			memset(page_uni2charset[uc], 0, NUM);
168 		}
169 
170 		/* set the reverse point in the page */
171 		page_uni2charset[uc][cp] = i;
172 	}
173 
174 	/* set up the table */
175 	if ((table = (struct unls_table *)malloc(sizeof (struct unls_table)))
176 							== NULL) {
177 		free_mem(charset2uni, page_uni2charset);
178 		return (-1);
179 	}
180 
181 	/* give the table the file name, so we can find it again if needed */
182 	table->unls_name = strdup(filename);
183 	table->unls_uni2cs = page_uni2charset;
184 	table->unls_cs2uni = charset2uni;
185 	table->unls_next = NULL;
186 
187 	/* register the table */
188 	return (register_unls(table));
189 }
190