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 * 27926f20c9SAndrey A. Chernov * $Id: collate.c,v 1.1 1995/02/16 04:24:28 ache Exp $ 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" 38c3d0cca4SAndrey A. Chernov 39c3d0cca4SAndrey A. Chernov int __collate_load_error = 1; 40c3d0cca4SAndrey A. Chernov u_char __collate_charmap_table[UCHAR_MAX + 1][STR_LEN]; 41c3d0cca4SAndrey A. Chernov u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 42c3d0cca4SAndrey A. Chernov struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 43c3d0cca4SAndrey A. Chernov struct __collate_st_name_pri __collate_name_pri_table[TABLE_SIZE]; 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 54926f20c9SAndrey A. Chernov __dead 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 static char *path_locale; 62c3d0cca4SAndrey A. Chernov FILE *fp; 63c3d0cca4SAndrey A. Chernov 64c3d0cca4SAndrey A. Chernov __collate_load_error = 1; 65c3d0cca4SAndrey A. Chernov if (!encoding) 66c3d0cca4SAndrey A. Chernov return -1; 67c3d0cca4SAndrey A. Chernov if (!path_locale && !(path_locale = getenv("PATH_LOCALE"))) 68c3d0cca4SAndrey A. Chernov path_locale = _PATH_LOCALE; 69c3d0cca4SAndrey A. Chernov strcpy(buf, path_locale); 70c3d0cca4SAndrey A. Chernov strcat(buf, "/"); 71c3d0cca4SAndrey A. Chernov strcat(buf, encoding); 72c3d0cca4SAndrey A. Chernov strcat(buf, "/LC_COLLATE"); 73c3d0cca4SAndrey A. Chernov if ((fp = fopen(buf, "r")) == NULL) 74c3d0cca4SAndrey A. Chernov return -1; 75c3d0cca4SAndrey A. Chernov FREAD(__collate_charmap_table, sizeof(__collate_charmap_table), 1, fp); 76c3d0cca4SAndrey A. Chernov FREAD(__collate_substitute_table, sizeof(__collate_substitute_table), 77c3d0cca4SAndrey A. Chernov 1, fp); 78c3d0cca4SAndrey A. Chernov FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, 79c3d0cca4SAndrey A. Chernov fp); 80c3d0cca4SAndrey A. Chernov FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, 81c3d0cca4SAndrey A. Chernov fp); 82c3d0cca4SAndrey A. Chernov FREAD(__collate_name_pri_table, sizeof(__collate_name_pri_table), 1, 83c3d0cca4SAndrey A. Chernov fp); 84c3d0cca4SAndrey A. Chernov fclose(fp); 85c3d0cca4SAndrey A. Chernov __collate_load_error = 0; 86c3d0cca4SAndrey A. Chernov return 0; 87c3d0cca4SAndrey A. Chernov } 88c3d0cca4SAndrey A. Chernov 89c3d0cca4SAndrey A. Chernov u_char * 90c3d0cca4SAndrey A. Chernov __collate_substitute(s) 91c3d0cca4SAndrey A. Chernov const u_char *s; 92c3d0cca4SAndrey A. Chernov { 93c3d0cca4SAndrey A. Chernov int dest_len = 0, len = 0; 94c3d0cca4SAndrey A. Chernov int delta = strlen(s); 95926f20c9SAndrey A. Chernov u_char *dest_str = NULL; 96c3d0cca4SAndrey A. Chernov 97926f20c9SAndrey A. Chernov if(s == NULL || *s == '\0') 98c3d0cca4SAndrey A. Chernov return __collate_strdup(""); 99c3d0cca4SAndrey A. Chernov while(*s) { 100c3d0cca4SAndrey A. Chernov len += strlen(__collate_substitute_table[*s]); 101c3d0cca4SAndrey A. Chernov while(dest_len <= len) { 102c3d0cca4SAndrey A. Chernov if(!dest_str) 103c3d0cca4SAndrey A. Chernov dest_str = calloc(dest_len = delta, 1); 104c3d0cca4SAndrey A. Chernov else 105c3d0cca4SAndrey A. Chernov dest_str = realloc(dest_str, dest_len += delta); 106926f20c9SAndrey A. Chernov if(dest_str == NULL) 107926f20c9SAndrey A. Chernov __collate_err(EX_OSERR, __FUNCTION__); 108c3d0cca4SAndrey A. Chernov } 109c3d0cca4SAndrey A. Chernov strcat(dest_str, __collate_substitute_table[*s++]); 110c3d0cca4SAndrey A. Chernov } 111c3d0cca4SAndrey A. Chernov return dest_str; 112c3d0cca4SAndrey A. Chernov } 113c3d0cca4SAndrey A. Chernov 114c3d0cca4SAndrey A. Chernov void 115c3d0cca4SAndrey A. Chernov __collate_lookup(t, len, prim, sec) 116c3d0cca4SAndrey A. Chernov u_char *t; 117c3d0cca4SAndrey A. Chernov int *len, *prim, *sec; 118c3d0cca4SAndrey A. Chernov { 119c3d0cca4SAndrey A. Chernov struct __collate_st_name_pri *p; 120c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri *p2; 121c3d0cca4SAndrey A. Chernov 122c3d0cca4SAndrey A. Chernov *len = 1; 123c3d0cca4SAndrey A. Chernov *prim = *sec = 0; 124c3d0cca4SAndrey A. Chernov if(__collate_charmap_table[*t][0]) { 125c3d0cca4SAndrey A. Chernov for(p = __collate_name_pri_table; p->str[0]; p++) { 126c3d0cca4SAndrey A. Chernov if(strncmp(__collate_charmap_table[*t], p->str, strlen(p->str)) 127c3d0cca4SAndrey A. Chernov == 0) { 128c3d0cca4SAndrey A. Chernov *prim = p->prim; 129c3d0cca4SAndrey A. Chernov *sec = p->sec; 130c3d0cca4SAndrey A. Chernov return; 131c3d0cca4SAndrey A. Chernov } 132c3d0cca4SAndrey A. Chernov } 133c3d0cca4SAndrey A. Chernov return; 134c3d0cca4SAndrey A. Chernov } 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 158926f20c9SAndrey A. Chernov __dead void __collate_err(int ex, const char *f) 159926f20c9SAndrey A. Chernov { 160926f20c9SAndrey A. Chernov extern char *__progname; /* Program name, from crt0. */ 161926f20c9SAndrey A. Chernov const char *s; 162926f20c9SAndrey A. Chernov int serrno = errno; 163926f20c9SAndrey A. Chernov 164926f20c9SAndrey A. Chernov s = __progname; 165926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 166926f20c9SAndrey A. Chernov s = ": "; 167926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 168926f20c9SAndrey A. Chernov s = f; 169926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 170926f20c9SAndrey A. Chernov s = ": "; 171926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 172926f20c9SAndrey A. Chernov s = strerror(serrno); 173926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 174926f20c9SAndrey A. Chernov s = "\n"; 175926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 176926f20c9SAndrey A. Chernov exit(ex); 177926f20c9SAndrey A. Chernov } 178926f20c9SAndrey A. Chernov 179c3d0cca4SAndrey A. Chernov #ifdef COLLATE_DEBUG 180c3d0cca4SAndrey A. Chernov void 181c3d0cca4SAndrey A. Chernov __collate_print_tables() 182c3d0cca4SAndrey A. Chernov { 183c3d0cca4SAndrey A. Chernov int i; 184c3d0cca4SAndrey A. Chernov struct __collate_st_name_pri *p; 185c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri *p2; 186c3d0cca4SAndrey A. Chernov 187c3d0cca4SAndrey A. Chernov printf("Substitute table:\n"); 188c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) 189c3d0cca4SAndrey A. Chernov printf("\t'%c' --> \"%s\"\n", i, 190c3d0cca4SAndrey A. Chernov __collate_substitute_table[i]); 191c3d0cca4SAndrey A. Chernov printf("Charmap table:\n"); 192c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) { 193c3d0cca4SAndrey A. Chernov if (__collate_charmap_table[i][0]) 194c3d0cca4SAndrey A. Chernov printf("\t\\x%02x --> \"%s\"\n", i, 195c3d0cca4SAndrey A. Chernov __collate_charmap_table[i]); 196c3d0cca4SAndrey A. Chernov } 197c3d0cca4SAndrey A. Chernov printf("Name priority table:\n"); 198c3d0cca4SAndrey A. Chernov for (p = __collate_name_pri_table; p->str[0]; p++) 199c3d0cca4SAndrey A. Chernov printf("\t\"%s\" : %d %d\n\n", p->str, p->prim, p->sec); 200c3d0cca4SAndrey A. Chernov printf("Chain priority table:\n"); 201c3d0cca4SAndrey A. Chernov for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) 202c3d0cca4SAndrey A. Chernov printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec); 203c3d0cca4SAndrey A. Chernov printf("Char priority table:\n"); 204c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) 205c3d0cca4SAndrey A. Chernov printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 206c3d0cca4SAndrey A. Chernov __collate_char_pri_table[i].sec); 207c3d0cca4SAndrey A. Chernov } 208c3d0cca4SAndrey A. Chernov #endif 209