1/* $NetBSD: streqvcmp.c,v 1.2 2012/02/03 21:36:40 christos Exp $ */ 2 3 4/** 5 * \file streqvcmp.c 6 * 7 * Time-stamp: "2010-07-17 10:16:24 bkorb" 8 * 9 * String Equivalence Comparison 10 * 11 * These routines allow any character to be mapped to any other 12 * character before comparison. In processing long option names, 13 * the characters "-", "_" and "^" all need to be equivalent 14 * (because they are treated so by different development environments). 15 * 16 * This file is part of AutoOpts, a companion to AutoGen. 17 * AutoOpts is free software. 18 * AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved 19 * 20 * AutoOpts is available under any one of two licenses. The license 21 * in use must be one of these two and the choice is under the control 22 * of the user of the license. 23 * 24 * The GNU Lesser General Public License, version 3 or later 25 * See the files "COPYING.lgplv3" and "COPYING.gplv3" 26 * 27 * The Modified Berkeley Software Distribution License 28 * See the file "COPYING.mbsd" 29 * 30 * These files have the following md5sums: 31 * 32 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 33 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 34 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd 35 * 36 * This array is designed for mapping upper and lower case letter 37 * together for a case independent comparison. The mappings are 38 * based upon ascii character sequences. 39 */ 40static unsigned char charmap[] = { 41 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, '\a', 42 '\b', '\t', '\n', '\v', '\f', '\r', 0x0E, 0x0F, 43 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 44 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 45 46 ' ', '!', '"', '#', '$', '%', '&', '\'', 47 '(', ')', '*', '+', ',', '-', '.', '/', 48 '0', '1', '2', '3', '4', '5', '6', '7', 49 '8', '9', ':', ';', '<', '=', '>', '?', 50 51 '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 52 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 53 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 54 'x', 'y', 'z', '[', '\\', ']', '^', '_', 55 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 56 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 57 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 58 'x', 'y', 'z', '{', '|', '}', '~', 0x7f, 59 60 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 61 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 62 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 63 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 64 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 65 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 66 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 67 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 68 69 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 70 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 71 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 72 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 73 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 74 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 75 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 76 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 77}; 78 79 80/*=export_func strneqvcmp 81 * 82 * what: compare two strings with an equivalence mapping 83 * 84 * arg: + char const* + str1 + first string + 85 * arg: + char const* + str2 + second string + 86 * arg: + int + ct + compare length + 87 * 88 * ret_type: int 89 * ret_desc: the difference between two differing characters 90 * 91 * doc: 92 * 93 * Using a character mapping, two strings are compared for "equivalence". 94 * Each input character is mapped to a comparison character and the 95 * mapped-to characters are compared for the two NUL terminated input strings. 96 * The comparison is limited to @code{ct} bytes. 97 * This function name is mapped to option_strneqvcmp so as to not conflict 98 * with the POSIX name space. 99 * 100 * err: none checked. Caller responsible for seg faults. 101=*/ 102int 103strneqvcmp(tCC* s1, tCC* s2, int ct) 104{ 105 for (; ct > 0; --ct) { 106 unsigned char u1 = (unsigned char) *s1++; 107 unsigned char u2 = (unsigned char) *s2++; 108 int dif = charmap[ u1 ] - charmap[ u2 ]; 109 110 if (dif != 0) 111 return dif; 112 113 if (u1 == NUL) 114 return 0; 115 } 116 117 return 0; 118} 119 120 121/*=export_func streqvcmp 122 * 123 * what: compare two strings with an equivalence mapping 124 * 125 * arg: + char const* + str1 + first string + 126 * arg: + char const* + str2 + second string + 127 * 128 * ret_type: int 129 * ret_desc: the difference between two differing characters 130 * 131 * doc: 132 * 133 * Using a character mapping, two strings are compared for "equivalence". 134 * Each input character is mapped to a comparison character and the 135 * mapped-to characters are compared for the two NUL terminated input strings. 136 * This function name is mapped to option_streqvcmp so as to not conflict 137 * with the POSIX name space. 138 * 139 * err: none checked. Caller responsible for seg faults. 140=*/ 141int 142streqvcmp(tCC* s1, tCC* s2) 143{ 144 for (;;) { 145 unsigned char u1 = (unsigned char) *s1++; 146 unsigned char u2 = (unsigned char) *s2++; 147 int dif = charmap[ u1 ] - charmap[ u2 ]; 148 149 if (dif != 0) 150 return dif; 151 152 if (u1 == NUL) 153 return 0; 154 } 155} 156 157 158/*=export_func streqvmap 159 * 160 * what: Set the character mappings for the streqv functions 161 * 162 * arg: + char + From + Input character + 163 * arg: + char + To + Mapped-to character + 164 * arg: + int + ct + compare length + 165 * 166 * doc: 167 * 168 * Set the character mapping. If the count (@code{ct}) is set to zero, then 169 * the map is cleared by setting all entries in the map to their index 170 * value. Otherwise, the "@code{From}" character is mapped to the "@code{To}" 171 * character. If @code{ct} is greater than 1, then @code{From} and @code{To} 172 * are incremented and the process repeated until @code{ct} entries have been 173 * set. For example, 174 * @example 175 * streqvmap('a', 'A', 26); 176 * @end example 177 * @noindent 178 * will alter the mapping so that all English lower case letters 179 * will map to upper case. 180 * 181 * This function name is mapped to option_streqvmap so as to not conflict 182 * with the POSIX name space. 183 * 184 * err: none. 185=*/ 186void 187streqvmap(char From, char To, int ct) 188{ 189 if (ct == 0) { 190 ct = sizeof(charmap) - 1; 191 do { 192 charmap[ ct ] = ct; 193 } while (--ct >= 0); 194 } 195 196 else { 197 size_t chTo = (int)To & 0xFF; 198 size_t chFrom = (int)From & 0xFF; 199 200 do { 201 charmap[ chFrom ] = (unsigned)chTo; 202 chFrom++; 203 chTo++; 204 if ((chFrom >= sizeof(charmap)) || (chTo >= sizeof(charmap))) 205 break; 206 } while (--ct > 0); 207 } 208} 209 210 211/*=export_func strequate 212 * 213 * what: map a list of characters to the same value 214 * 215 * arg: + char const* + ch_list + characters to equivalence + 216 * 217 * doc: 218 * 219 * Each character in the input string get mapped to the first character 220 * in the string. 221 * This function name is mapped to option_strequate so as to not conflict 222 * with the POSIX name space. 223 * 224 * err: none. 225=*/ 226void 227strequate(char const* s) 228{ 229 if ((s != NULL) && (*s != NUL)) { 230 unsigned char equiv = (unsigned)*s; 231 while (*s != NUL) 232 charmap[ (unsigned)*(s++) ] = equiv; 233 } 234} 235 236 237/*=export_func strtransform 238 * 239 * what: convert a string into its mapped-to value 240 * 241 * arg: + char* + dest + output string + 242 * arg: + char const* + src + input string + 243 * 244 * doc: 245 * 246 * Each character in the input string is mapped and the mapped-to 247 * character is put into the output. 248 * This function name is mapped to option_strtransform so as to not conflict 249 * with the POSIX name space. 250 * 251 * The source and destination may be the same. 252 * 253 * err: none. 254=*/ 255void 256strtransform(char* d, char const* s) 257{ 258 do { 259 *(d++) = (char)charmap[ (unsigned)*s ]; 260 } while (*(s++) != NUL); 261} 262 263/* 264 * Local Variables: 265 * mode: C 266 * c-file-style: "stroustrup" 267 * indent-tabs-mode: nil 268 * End: 269 * end of autoopts/streqvcmp.c */ 270