1 /*- 2 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> 3 * at Electronni Visti IA, Kiev, Ukraine. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $Id: collate.c,v 1.2 1995/02/17 16:36:12 ache Exp $ 28 */ 29 30 #include <rune.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <sysexits.h> 37 #include "collate.h" 38 39 int __collate_load_error = 1; 40 u_char __collate_charmap_table[UCHAR_MAX + 1][STR_LEN]; 41 u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 42 struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 43 struct __collate_st_name_pri __collate_name_pri_table[TABLE_SIZE]; 44 struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE]; 45 46 #define FREAD(a, b, c, d) \ 47 do { \ 48 if(fread(a, b, c, d) != c) { \ 49 fclose(d); \ 50 return -1; \ 51 } \ 52 } while(0) 53 54 __dead void __collate_err(int ex, const char *f) __dead2; 55 56 int 57 __collate_load_tables(encoding) 58 char *encoding; 59 { 60 char buf[PATH_MAX]; 61 static char *path_locale; 62 FILE *fp; 63 64 __collate_load_error = 1; 65 if (!encoding) 66 return -1; 67 if (!path_locale && !(path_locale = getenv("PATH_LOCALE"))) 68 path_locale = _PATH_LOCALE; 69 strcpy(buf, path_locale); 70 strcat(buf, "/"); 71 strcat(buf, encoding); 72 strcat(buf, "/LC_COLLATE"); 73 if ((fp = fopen(buf, "r")) == NULL) 74 return -1; 75 FREAD(__collate_charmap_table, sizeof(__collate_charmap_table), 1, fp); 76 FREAD(__collate_substitute_table, sizeof(__collate_substitute_table), 77 1, fp); 78 FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, 79 fp); 80 FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, 81 fp); 82 FREAD(__collate_name_pri_table, sizeof(__collate_name_pri_table), 1, 83 fp); 84 fclose(fp); 85 __collate_load_error = 0; 86 return 0; 87 } 88 89 u_char * 90 __collate_substitute(s) 91 const u_char *s; 92 { 93 int dest_len = 0, len = 0; 94 int delta = strlen(s); 95 u_char *dest_str = NULL; 96 97 if(s == NULL || *s == '\0') 98 return __collate_strdup(""); 99 while(*s) { 100 len += strlen(__collate_substitute_table[*s]); 101 while(dest_len <= len) { 102 if(!dest_str) 103 dest_str = calloc(dest_len = delta, 1); 104 else 105 dest_str = realloc(dest_str, dest_len += delta); 106 if(dest_str == NULL) 107 __collate_err(EX_OSERR, __FUNCTION__); 108 } 109 strcat(dest_str, __collate_substitute_table[*s++]); 110 } 111 return dest_str; 112 } 113 114 void 115 __collate_lookup(t, len, prim, sec) 116 u_char *t; 117 int *len, *prim, *sec; 118 { 119 struct __collate_st_name_pri *p; 120 struct __collate_st_chain_pri *p2; 121 122 *len = 1; 123 *prim = *sec = 0; 124 if(__collate_charmap_table[*t][0]) { 125 for(p = __collate_name_pri_table; p->str[0]; p++) { 126 if(strncmp(__collate_charmap_table[*t], p->str, strlen(p->str)) 127 == 0) { 128 *prim = p->prim; 129 *sec = p->sec; 130 return; 131 } 132 } 133 return; 134 } 135 for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) { 136 if(strncmp(t, p2->str, strlen(p2->str)) == 0) { 137 *len = strlen(p2->str); 138 *prim = p2->prim; 139 *sec = p2->sec; 140 return; 141 } 142 } 143 *prim = __collate_char_pri_table[*t].prim; 144 *sec = __collate_char_pri_table[*t].sec; 145 } 146 147 u_char * 148 __collate_strdup(s) 149 u_char *s; 150 { 151 u_char *t = strdup(s); 152 153 if (t == NULL) 154 __collate_err(EX_OSERR, __FUNCTION__); 155 return t; 156 } 157 158 __dead void __collate_err(int ex, const char *f) 159 { 160 extern char *__progname; /* Program name, from crt0. */ 161 const char *s; 162 int serrno = errno; 163 164 s = __progname; 165 write(STDERR_FILENO, s, strlen(s)); 166 write(STDERR_FILENO, ": ", 2); 167 s = f; 168 write(STDERR_FILENO, s, strlen(s)); 169 write(STDERR_FILENO, ": ", 2); 170 s = strerror(serrno); 171 write(STDERR_FILENO, s, strlen(s)); 172 write(STDERR_FILENO, "\n", 1); 173 exit(ex); 174 } 175 176 #ifdef COLLATE_DEBUG 177 void 178 __collate_print_tables() 179 { 180 int i; 181 struct __collate_st_name_pri *p; 182 struct __collate_st_chain_pri *p2; 183 184 printf("Substitute table:\n"); 185 for (i = 0; i < UCHAR_MAX + 1; i++) 186 printf("\t'%c' --> \"%s\"\n", i, 187 __collate_substitute_table[i]); 188 printf("Charmap table:\n"); 189 for (i = 0; i < UCHAR_MAX + 1; i++) { 190 if (__collate_charmap_table[i][0]) 191 printf("\t\\x%02x --> \"%s\"\n", i, 192 __collate_charmap_table[i]); 193 } 194 printf("Name priority table:\n"); 195 for (p = __collate_name_pri_table; p->str[0]; p++) 196 printf("\t\"%s\" : %d %d\n\n", p->str, p->prim, p->sec); 197 printf("Chain priority table:\n"); 198 for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) 199 printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec); 200 printf("Char priority table:\n"); 201 for (i = 0; i < UCHAR_MAX + 1; i++) 202 printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 203 __collate_char_pri_table[i].sec); 204 } 205 #endif 206