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 * 27377da8e8SAndrey A. Chernov * $Id: collate.c,v 1.4 1995/05/30 05:40:40 rgrimes 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 39377da8e8SAndrey A. Chernov char *_PathLocale; 40c3d0cca4SAndrey A. Chernov int __collate_load_error = 1; 41c3d0cca4SAndrey A. Chernov u_char __collate_charmap_table[UCHAR_MAX + 1][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_name_pri __collate_name_pri_table[TABLE_SIZE]; 45c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE]; 46c3d0cca4SAndrey A. Chernov 47c3d0cca4SAndrey A. Chernov #define FREAD(a, b, c, d) \ 48c3d0cca4SAndrey A. Chernov do { \ 49c3d0cca4SAndrey A. Chernov if(fread(a, b, c, d) != c) { \ 50c3d0cca4SAndrey A. Chernov fclose(d); \ 51c3d0cca4SAndrey A. Chernov return -1; \ 52c3d0cca4SAndrey A. Chernov } \ 53c3d0cca4SAndrey A. Chernov } while(0) 54c3d0cca4SAndrey A. Chernov 55926f20c9SAndrey A. Chernov __dead void __collate_err(int ex, const char *f) __dead2; 56926f20c9SAndrey A. Chernov 57c3d0cca4SAndrey A. Chernov int 58c3d0cca4SAndrey A. Chernov __collate_load_tables(encoding) 59c3d0cca4SAndrey A. Chernov char *encoding; 60c3d0cca4SAndrey A. Chernov { 61c3d0cca4SAndrey A. Chernov char buf[PATH_MAX]; 62c3d0cca4SAndrey A. Chernov FILE *fp; 63377da8e8SAndrey A. Chernov int save_load_error; 64c3d0cca4SAndrey A. Chernov 65377da8e8SAndrey A. Chernov save_load_error = __collate_load_error; 66c3d0cca4SAndrey A. Chernov __collate_load_error = 1; 67377da8e8SAndrey A. Chernov if (!encoding) { 68377da8e8SAndrey A. Chernov __collate_load_error = save_load_error; 69c3d0cca4SAndrey A. Chernov return -1; 70377da8e8SAndrey A. Chernov } 71377da8e8SAndrey A. Chernov if (!*encoding || !strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) 72377da8e8SAndrey A. Chernov return 0; 73377da8e8SAndrey A. Chernov if (!_PathLocale && !(_PathLocale = getenv("PATH_LOCALE"))) 74377da8e8SAndrey A. Chernov _PathLocale = _PATH_LOCALE; 75377da8e8SAndrey A. Chernov strcpy(buf, _PathLocale); 76c3d0cca4SAndrey A. Chernov strcat(buf, "/"); 77c3d0cca4SAndrey A. Chernov strcat(buf, encoding); 78c3d0cca4SAndrey A. Chernov strcat(buf, "/LC_COLLATE"); 79377da8e8SAndrey A. Chernov if ((fp = fopen(buf, "r")) == NULL) { 80377da8e8SAndrey A. Chernov __collate_load_error = save_load_error; 81c3d0cca4SAndrey A. Chernov return -1; 82377da8e8SAndrey A. Chernov } 83c3d0cca4SAndrey A. Chernov FREAD(__collate_charmap_table, sizeof(__collate_charmap_table), 1, fp); 84c3d0cca4SAndrey A. Chernov FREAD(__collate_substitute_table, sizeof(__collate_substitute_table), 85c3d0cca4SAndrey A. Chernov 1, fp); 86c3d0cca4SAndrey A. Chernov FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, 87c3d0cca4SAndrey A. Chernov fp); 88c3d0cca4SAndrey A. Chernov FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, 89c3d0cca4SAndrey A. Chernov fp); 90c3d0cca4SAndrey A. Chernov FREAD(__collate_name_pri_table, sizeof(__collate_name_pri_table), 1, 91c3d0cca4SAndrey A. Chernov fp); 92c3d0cca4SAndrey A. Chernov fclose(fp); 93c3d0cca4SAndrey A. Chernov __collate_load_error = 0; 94c3d0cca4SAndrey A. Chernov return 0; 95c3d0cca4SAndrey A. Chernov } 96c3d0cca4SAndrey A. Chernov 97c3d0cca4SAndrey A. Chernov u_char * 98c3d0cca4SAndrey A. Chernov __collate_substitute(s) 99c3d0cca4SAndrey A. Chernov const u_char *s; 100c3d0cca4SAndrey A. Chernov { 101c3d0cca4SAndrey A. Chernov int dest_len = 0, len = 0; 102c3d0cca4SAndrey A. Chernov int delta = strlen(s); 103926f20c9SAndrey A. Chernov u_char *dest_str = NULL; 104c3d0cca4SAndrey A. Chernov 105926f20c9SAndrey A. Chernov if(s == NULL || *s == '\0') 106c3d0cca4SAndrey A. Chernov return __collate_strdup(""); 107c3d0cca4SAndrey A. Chernov while(*s) { 108c3d0cca4SAndrey A. Chernov len += strlen(__collate_substitute_table[*s]); 109c3d0cca4SAndrey A. Chernov while(dest_len <= len) { 110c3d0cca4SAndrey A. Chernov if(!dest_str) 111c3d0cca4SAndrey A. Chernov dest_str = calloc(dest_len = delta, 1); 112c3d0cca4SAndrey A. Chernov else 113c3d0cca4SAndrey A. Chernov dest_str = realloc(dest_str, dest_len += delta); 114926f20c9SAndrey A. Chernov if(dest_str == NULL) 115926f20c9SAndrey A. Chernov __collate_err(EX_OSERR, __FUNCTION__); 116c3d0cca4SAndrey A. Chernov } 117c3d0cca4SAndrey A. Chernov strcat(dest_str, __collate_substitute_table[*s++]); 118c3d0cca4SAndrey A. Chernov } 119c3d0cca4SAndrey A. Chernov return dest_str; 120c3d0cca4SAndrey A. Chernov } 121c3d0cca4SAndrey A. Chernov 122c3d0cca4SAndrey A. Chernov void 123c3d0cca4SAndrey A. Chernov __collate_lookup(t, len, prim, sec) 124c3d0cca4SAndrey A. Chernov u_char *t; 125c3d0cca4SAndrey A. Chernov int *len, *prim, *sec; 126c3d0cca4SAndrey A. Chernov { 127c3d0cca4SAndrey A. Chernov struct __collate_st_name_pri *p; 128c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri *p2; 129c3d0cca4SAndrey A. Chernov 130c3d0cca4SAndrey A. Chernov *len = 1; 131c3d0cca4SAndrey A. Chernov *prim = *sec = 0; 132c3d0cca4SAndrey A. Chernov if(__collate_charmap_table[*t][0]) { 133c3d0cca4SAndrey A. Chernov for(p = __collate_name_pri_table; p->str[0]; p++) { 134c3d0cca4SAndrey A. Chernov if(strncmp(__collate_charmap_table[*t], p->str, strlen(p->str)) 135c3d0cca4SAndrey A. Chernov == 0) { 136c3d0cca4SAndrey A. Chernov *prim = p->prim; 137c3d0cca4SAndrey A. Chernov *sec = p->sec; 138c3d0cca4SAndrey A. Chernov return; 139c3d0cca4SAndrey A. Chernov } 140c3d0cca4SAndrey A. Chernov } 141c3d0cca4SAndrey A. Chernov return; 142c3d0cca4SAndrey A. Chernov } 143c3d0cca4SAndrey A. Chernov for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) { 144c3d0cca4SAndrey A. Chernov if(strncmp(t, p2->str, strlen(p2->str)) == 0) { 145c3d0cca4SAndrey A. Chernov *len = strlen(p2->str); 146c3d0cca4SAndrey A. Chernov *prim = p2->prim; 147c3d0cca4SAndrey A. Chernov *sec = p2->sec; 148c3d0cca4SAndrey A. Chernov return; 149c3d0cca4SAndrey A. Chernov } 150c3d0cca4SAndrey A. Chernov } 151c3d0cca4SAndrey A. Chernov *prim = __collate_char_pri_table[*t].prim; 152c3d0cca4SAndrey A. Chernov *sec = __collate_char_pri_table[*t].sec; 153c3d0cca4SAndrey A. Chernov } 154c3d0cca4SAndrey A. Chernov 155c3d0cca4SAndrey A. Chernov u_char * 156c3d0cca4SAndrey A. Chernov __collate_strdup(s) 157c3d0cca4SAndrey A. Chernov u_char *s; 158c3d0cca4SAndrey A. Chernov { 159926f20c9SAndrey A. Chernov u_char *t = strdup(s); 160c3d0cca4SAndrey A. Chernov 161926f20c9SAndrey A. Chernov if (t == NULL) 162926f20c9SAndrey A. Chernov __collate_err(EX_OSERR, __FUNCTION__); 163c3d0cca4SAndrey A. Chernov return t; 164c3d0cca4SAndrey A. Chernov } 165c3d0cca4SAndrey A. Chernov 166926f20c9SAndrey A. Chernov __dead void __collate_err(int ex, const char *f) 167926f20c9SAndrey A. Chernov { 168926f20c9SAndrey A. Chernov extern char *__progname; /* Program name, from crt0. */ 169926f20c9SAndrey A. Chernov const char *s; 170926f20c9SAndrey A. Chernov int serrno = errno; 171926f20c9SAndrey A. Chernov 172926f20c9SAndrey A. Chernov s = __progname; 173926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 1743d4c9a4bSAndrey A. Chernov write(STDERR_FILENO, ": ", 2); 175926f20c9SAndrey A. Chernov s = f; 176926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 1773d4c9a4bSAndrey A. Chernov write(STDERR_FILENO, ": ", 2); 178926f20c9SAndrey A. Chernov s = strerror(serrno); 179926f20c9SAndrey A. Chernov write(STDERR_FILENO, s, strlen(s)); 1803d4c9a4bSAndrey A. Chernov write(STDERR_FILENO, "\n", 1); 181926f20c9SAndrey A. Chernov exit(ex); 182926f20c9SAndrey A. Chernov } 183926f20c9SAndrey A. Chernov 184c3d0cca4SAndrey A. Chernov #ifdef COLLATE_DEBUG 185c3d0cca4SAndrey A. Chernov void 186c3d0cca4SAndrey A. Chernov __collate_print_tables() 187c3d0cca4SAndrey A. Chernov { 188c3d0cca4SAndrey A. Chernov int i; 189c3d0cca4SAndrey A. Chernov struct __collate_st_name_pri *p; 190c3d0cca4SAndrey A. Chernov struct __collate_st_chain_pri *p2; 191c3d0cca4SAndrey A. Chernov 192c3d0cca4SAndrey A. Chernov printf("Substitute table:\n"); 193c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) 194c3d0cca4SAndrey A. Chernov printf("\t'%c' --> \"%s\"\n", i, 195c3d0cca4SAndrey A. Chernov __collate_substitute_table[i]); 196c3d0cca4SAndrey A. Chernov printf("Charmap table:\n"); 197c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) { 198c3d0cca4SAndrey A. Chernov if (__collate_charmap_table[i][0]) 199c3d0cca4SAndrey A. Chernov printf("\t\\x%02x --> \"%s\"\n", i, 200c3d0cca4SAndrey A. Chernov __collate_charmap_table[i]); 201c3d0cca4SAndrey A. Chernov } 202c3d0cca4SAndrey A. Chernov printf("Name priority table:\n"); 203c3d0cca4SAndrey A. Chernov for (p = __collate_name_pri_table; p->str[0]; p++) 204c3d0cca4SAndrey A. Chernov printf("\t\"%s\" : %d %d\n\n", p->str, p->prim, p->sec); 205c3d0cca4SAndrey A. Chernov printf("Chain priority table:\n"); 206c3d0cca4SAndrey A. Chernov for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) 207c3d0cca4SAndrey A. Chernov printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec); 208c3d0cca4SAndrey A. Chernov printf("Char priority table:\n"); 209c3d0cca4SAndrey A. Chernov for (i = 0; i < UCHAR_MAX + 1; i++) 210c3d0cca4SAndrey A. Chernov printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 211c3d0cca4SAndrey A. Chernov __collate_char_pri_table[i].sec); 212c3d0cca4SAndrey A. Chernov } 213c3d0cca4SAndrey A. Chernov #endif 214