1c3d0cca4SAndrey A. Chernov /*- 2c3d0cca4SAndrey A. Chernov * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> 3c3d0cca4SAndrey A. Chernov * at Electronni Visti IA, Kiev, Ukraine. 4c3d0cca4SAndrey A. Chernov * All rights reserved. 5c3d0cca4SAndrey A. Chernov * 6c3d0cca4SAndrey A. Chernov * Redistribution and use in source and binary forms, with or without 7c3d0cca4SAndrey A. Chernov * modification, are permitted provided that the following conditions 8c3d0cca4SAndrey A. Chernov * are met: 9c3d0cca4SAndrey A. Chernov * 1. Redistributions of source code must retain the above copyright 10c3d0cca4SAndrey A. Chernov * notice, this list of conditions and the following disclaimer. 11c3d0cca4SAndrey A. Chernov * 2. Redistributions in binary form must reproduce the above copyright 12c3d0cca4SAndrey A. Chernov * notice, this list of conditions and the following disclaimer in the 13c3d0cca4SAndrey A. Chernov * documentation and/or other materials provided with the distribution. 14c3d0cca4SAndrey A. Chernov * 15c3d0cca4SAndrey A. Chernov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 16c3d0cca4SAndrey A. Chernov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17c3d0cca4SAndrey A. Chernov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18c3d0cca4SAndrey A. Chernov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 19c3d0cca4SAndrey A. Chernov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20c3d0cca4SAndrey A. Chernov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21c3d0cca4SAndrey A. Chernov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22c3d0cca4SAndrey A. Chernov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23c3d0cca4SAndrey A. Chernov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24c3d0cca4SAndrey A. Chernov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25c3d0cca4SAndrey A. Chernov * SUCH DAMAGE. 26c3d0cca4SAndrey A. Chernov * 271130b656SJordan K. Hubbard * $FreeBSD$ 28c3d0cca4SAndrey A. Chernov */ 29c3d0cca4SAndrey A. Chernov 30c3d0cca4SAndrey A. Chernov #include <rune.h> 31c3d0cca4SAndrey A. Chernov #include <stdio.h> 32c3d0cca4SAndrey A. Chernov #include <stdlib.h> 33c3d0cca4SAndrey A. Chernov #include <string.h> 34926f20c9SAndrey A. Chernov #include <errno.h> 35926f20c9SAndrey A. Chernov #include <unistd.h> 36c3d0cca4SAndrey A. Chernov #include <sysexits.h> 37c3d0cca4SAndrey A. Chernov #include "collate.h" 3863407d34SAndrey A. Chernov #include "setlocale.h" 39c3d0cca4SAndrey A. Chernov 40c3d0cca4SAndrey A. Chernov int __collate_load_error = 1; 411642f84dSAndrey A. Chernov char __collate_version[STR_LEN]; 42c3d0cca4SAndrey A. Chernov u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 43c3d0cca4SAndrey A. Chernov struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 44c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE]; 45c3d0cca4SAndrey A. Chernov 46c3d0cca4SAndrey A. Chernov #define FREAD(a, b, c, d) \ 47c3d0cca4SAndrey A. Chernov do { \ 48c3d0cca4SAndrey A. Chernov if(fread(a, b, c, d) != c) { \ 49c3d0cca4SAndrey A. Chernov fclose(d); \ 50c3d0cca4SAndrey A. Chernov return -1; \ 51c3d0cca4SAndrey A. Chernov } \ 52c3d0cca4SAndrey A. Chernov } while(0) 53c3d0cca4SAndrey A. Chernov 54eaa86f9dSBruce Evans void __collate_err(int ex, const char *f) __dead2; 55926f20c9SAndrey A. Chernov 56c3d0cca4SAndrey A. Chernov int 57c3d0cca4SAndrey A. Chernov __collate_load_tables(encoding) 58c3d0cca4SAndrey A. Chernov char *encoding; 59c3d0cca4SAndrey A. Chernov { 60c3d0cca4SAndrey A. Chernov char buf[PATH_MAX]; 61c3d0cca4SAndrey A. Chernov FILE *fp; 62377da8e8SAndrey A. Chernov int save_load_error; 63c3d0cca4SAndrey A. Chernov 64377da8e8SAndrey A. Chernov save_load_error = __collate_load_error; 65c3d0cca4SAndrey A. Chernov __collate_load_error = 1; 66377da8e8SAndrey A. Chernov if (!encoding) { 67377da8e8SAndrey A. Chernov __collate_load_error = save_load_error; 68c3d0cca4SAndrey A. Chernov return -1; 69377da8e8SAndrey A. Chernov } 70c8f931a8SAndrey A. Chernov if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) 71377da8e8SAndrey A. Chernov return 0; 72c8f931a8SAndrey A. Chernov if (!_PathLocale) { 73c8f931a8SAndrey A. Chernov __collate_load_error = save_load_error; 74c8f931a8SAndrey A. Chernov return -1; 75c8f931a8SAndrey A. Chernov } 76d81a0916SAndrey A. Chernov /* Range checking not needed, encoding has fixed size */ 77af155bdfSAndrey A. Chernov (void) strcpy(buf, _PathLocale); 78af155bdfSAndrey A. Chernov (void) strcat(buf, "/"); 79af155bdfSAndrey A. Chernov (void) strcat(buf, encoding); 80af155bdfSAndrey A. Chernov (void) strcat(buf, "/LC_COLLATE"); 81377da8e8SAndrey A. Chernov if ((fp = fopen(buf, "r")) == NULL) { 82377da8e8SAndrey A. Chernov __collate_load_error = save_load_error; 83c3d0cca4SAndrey A. Chernov return -1; 84377da8e8SAndrey A. Chernov } 851642f84dSAndrey A. Chernov FREAD(__collate_version, sizeof(__collate_version), 1, fp); 861642f84dSAndrey A. Chernov if (strcmp(__collate_version, COLLATE_VERSION) != 0) { 871642f84dSAndrey A. Chernov fclose(fp); 881642f84dSAndrey A. Chernov return -1; 891642f84dSAndrey A. Chernov } 90c3d0cca4SAndrey A. Chernov FREAD(__collate_substitute_table, sizeof(__collate_substitute_table), 91c3d0cca4SAndrey A. Chernov 1, fp); 92c3d0cca4SAndrey A. Chernov FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, 93c3d0cca4SAndrey A. Chernov fp); 94c3d0cca4SAndrey A. Chernov FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, 95c3d0cca4SAndrey A. Chernov fp); 96c3d0cca4SAndrey A. Chernov fclose(fp); 97c3d0cca4SAndrey A. Chernov __collate_load_error = 0; 98c3d0cca4SAndrey A. Chernov return 0; 99c3d0cca4SAndrey A. Chernov } 100c3d0cca4SAndrey A. Chernov 101c3d0cca4SAndrey A. Chernov u_char * 102c3d0cca4SAndrey A. Chernov __collate_substitute(s) 103c3d0cca4SAndrey A. Chernov const u_char *s; 104c3d0cca4SAndrey A. Chernov { 105c3d0cca4SAndrey A. Chernov int dest_len = 0, len = 0; 106c3d0cca4SAndrey A. Chernov int delta = strlen(s); 107926f20c9SAndrey A. Chernov u_char *dest_str = NULL; 108c3d0cca4SAndrey A. Chernov 109926f20c9SAndrey A. Chernov if(s == NULL || *s == '\0') 110c3d0cca4SAndrey A. Chernov return __collate_strdup(""); 111c3d0cca4SAndrey A. Chernov while(*s) { 112c3d0cca4SAndrey A. Chernov len += strlen(__collate_substitute_table[*s]); 113c3d0cca4SAndrey A. Chernov while(dest_len <= len) { 114c3d0cca4SAndrey A. Chernov if(!dest_str) 115c3d0cca4SAndrey A. Chernov dest_str = calloc(dest_len = delta, 1); 116c3d0cca4SAndrey A. Chernov else 117c3d0cca4SAndrey A. Chernov dest_str = realloc(dest_str, dest_len += delta); 118926f20c9SAndrey A. Chernov if(dest_str == NULL) 119926f20c9SAndrey A. Chernov __collate_err(EX_OSERR, __FUNCTION__); 120c3d0cca4SAndrey A. Chernov } 121c3d0cca4SAndrey A. Chernov strcat(dest_str, __collate_substitute_table[*s++]); 122c3d0cca4SAndrey A. Chernov } 123c3d0cca4SAndrey A. Chernov return dest_str; 124c3d0cca4SAndrey A. Chernov } 125c3d0cca4SAndrey A. Chernov 126c3d0cca4SAndrey A. Chernov void 127c3d0cca4SAndrey A. Chernov __collate_lookup(t, len, prim, sec) 128c3d0cca4SAndrey A. Chernov u_char *t; 129c3d0cca4SAndrey A. Chernov int *len, *prim, *sec; 130c3d0cca4SAndrey A. Chernov { 131c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri *p2; 132c3d0cca4SAndrey A. Chernov 133c3d0cca4SAndrey A. Chernov *len = 1; 134c3d0cca4SAndrey A. Chernov *prim = *sec = 0; 135c3d0cca4SAndrey A. Chernov for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) { 136c3d0cca4SAndrey A. Chernov if(strncmp(t, p2->str, strlen(p2->str)) == 0) { 137c3d0cca4SAndrey A. Chernov *len = strlen(p2->str); 138c3d0cca4SAndrey A. Chernov *prim = p2->prim; 139c3d0cca4SAndrey A. Chernov *sec = p2->sec; 140c3d0cca4SAndrey A. Chernov return; 141c3d0cca4SAndrey A. Chernov } 142c3d0cca4SAndrey A. Chernov } 143c3d0cca4SAndrey A. Chernov *prim = __collate_char_pri_table[*t].prim; 144c3d0cca4SAndrey A. Chernov *sec = __collate_char_pri_table[*t].sec; 145c3d0cca4SAndrey A. Chernov } 146c3d0cca4SAndrey A. Chernov 147c3d0cca4SAndrey A. Chernov u_char * 148c3d0cca4SAndrey A. Chernov __collate_strdup(s) 149c3d0cca4SAndrey A. Chernov u_char *s; 150c3d0cca4SAndrey A. Chernov { 151926f20c9SAndrey A. Chernov u_char *t = strdup(s); 152c3d0cca4SAndrey A. Chernov 153926f20c9SAndrey A. Chernov if (t == NULL) 154926f20c9SAndrey A. Chernov __collate_err(EX_OSERR, __FUNCTION__); 155c3d0cca4SAndrey A. Chernov return t; 156c3d0cca4SAndrey A. Chernov } 157c3d0cca4SAndrey A. Chernov 158eaa86f9dSBruce Evans void 159eaa86f9dSBruce Evans __collate_err(int ex, const char *f) 160926f20c9SAndrey A. Chernov { 161926f20c9SAndrey A. Chernov extern char *__progname; /* Program name, from crt0. */ 162926f20c9SAndrey A. Chernov const char *s; 163926f20c9SAndrey A. Chernov int serrno = errno; 164926f20c9SAndrey A. Chernov 165926f20c9SAndrey A. Chernov s = __progname; 166926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 1673d4c9a4bSAndrey A. Chernov write(STDERR_FILENO, ": ", 2); 168926f20c9SAndrey A. Chernov s = f; 169926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 1703d4c9a4bSAndrey A. Chernov write(STDERR_FILENO, ": ", 2); 171926f20c9SAndrey A. Chernov s = strerror(serrno); 172926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 1733d4c9a4bSAndrey A. Chernov write(STDERR_FILENO, "\n", 1); 174926f20c9SAndrey A. Chernov exit(ex); 175926f20c9SAndrey A. Chernov } 176926f20c9SAndrey A. Chernov 177c3d0cca4SAndrey A. Chernov #ifdef COLLATE_DEBUG 178c3d0cca4SAndrey A. Chernov void 179c3d0cca4SAndrey A. Chernov __collate_print_tables() 180c3d0cca4SAndrey A. Chernov { 181c3d0cca4SAndrey A. Chernov int i; 182c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri *p2; 183c3d0cca4SAndrey A. Chernov 184c3d0cca4SAndrey A. Chernov printf("Substitute table:\n"); 185c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) 186967a5cb1SAndrey A. Chernov if (i != *__collate_substitute_table[i]) 187c3d0cca4SAndrey A. Chernov printf("\t'%c' --> \"%s\"\n", i, 188c3d0cca4SAndrey A. Chernov __collate_substitute_table[i]); 189c3d0cca4SAndrey A. Chernov printf("Chain priority table:\n"); 190c3d0cca4SAndrey A. Chernov for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) 191c3d0cca4SAndrey A. Chernov printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec); 192c3d0cca4SAndrey A. Chernov printf("Char priority table:\n"); 193c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) 194c3d0cca4SAndrey A. Chernov printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 195c3d0cca4SAndrey A. Chernov __collate_char_pri_table[i].sec); 196c3d0cca4SAndrey A. Chernov } 197c3d0cca4SAndrey A. Chernov #endif 198