1181834Sroberto
2181834Sroberto/*
3181834Sroberto *  $Id: streqvcmp.c,v 4.10 2007/04/28 22:19:23 bkorb Exp $
4181834Sroberto * Time-stamp:      "2006-07-26 18:25:53 bkorb"
5181834Sroberto *
6181834Sroberto *  String Equivalence Comparison
7181834Sroberto *
8181834Sroberto *  These routines allow any character to be mapped to any other
9181834Sroberto *  character before comparison.  In processing long option names,
10181834Sroberto *  the characters "-", "_" and "^" all need to be equivalent
11181834Sroberto *  (because they are treated so by different development environments).
12181834Sroberto */
13181834Sroberto
14181834Sroberto/*
15181834Sroberto *  Automated Options copyright 1992-2007 Bruce Korb
16181834Sroberto *
17181834Sroberto *  Automated Options is free software.
18181834Sroberto *  You may redistribute it and/or modify it under the terms of the
19181834Sroberto *  GNU General Public License, as published by the Free Software
20181834Sroberto *  Foundation; either version 2, or (at your option) any later version.
21181834Sroberto *
22181834Sroberto *  Automated Options is distributed in the hope that it will be useful,
23181834Sroberto *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24181834Sroberto *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25181834Sroberto *  GNU General Public License for more details.
26181834Sroberto *
27181834Sroberto *  You should have received a copy of the GNU General Public License
28181834Sroberto *  along with Automated Options.  See the file "COPYING".  If not,
29181834Sroberto *  write to:  The Free Software Foundation, Inc.,
30181834Sroberto *             51 Franklin Street, Fifth Floor,
31181834Sroberto *             Boston, MA  02110-1301, USA.
32181834Sroberto *
33181834Sroberto * As a special exception, Bruce Korb gives permission for additional
34181834Sroberto * uses of the text contained in his release of AutoOpts.
35181834Sroberto *
36181834Sroberto * The exception is that, if you link the AutoOpts library with other
37181834Sroberto * files to produce an executable, this does not by itself cause the
38181834Sroberto * resulting executable to be covered by the GNU General Public License.
39181834Sroberto * Your use of that executable is in no way restricted on account of
40181834Sroberto * linking the AutoOpts library code into it.
41181834Sroberto *
42181834Sroberto * This exception does not however invalidate any other reasons why
43181834Sroberto * the executable file might be covered by the GNU General Public License.
44181834Sroberto *
45181834Sroberto * This exception applies only to the code released by Bruce Korb under
46181834Sroberto * the name AutoOpts.  If you copy code from other sources under the
47181834Sroberto * General Public License into a copy of AutoOpts, as the General Public
48181834Sroberto * License permits, the exception does not apply to the code that you add
49181834Sroberto * in this way.  To avoid misleading anyone as to the status of such
50181834Sroberto * modified files, you must delete this exception notice from them.
51181834Sroberto *
52181834Sroberto * If you write modifications of your own for AutoOpts, it is your choice
53181834Sroberto * whether to permit this exception to apply to your modifications.
54181834Sroberto * If you do not wish that, delete this exception notice.
55181834Sroberto */
56181834Sroberto
57181834Sroberto/*
58181834Sroberto * This array is designed for mapping upper and lower case letter
59181834Sroberto * together for a case independent comparison.  The mappings are
60181834Sroberto * based upon ascii character sequences.
61181834Sroberto */
62181834Srobertostatic unsigned char charmap[] = {
63181834Sroberto    0x00, 0x01, 0x02, 0x03,  0x04, 0x05, 0x06, '\a',
64181834Sroberto    '\b', '\t', '\n', '\v',  '\f', '\r', 0x0E, 0x0F,
65181834Sroberto    0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,
66181834Sroberto    0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E, 0x1F,
67181834Sroberto
68181834Sroberto    ' ',  '!',  '"',  '#',   '$',  '%',  '&',  '\'',
69181834Sroberto    '(',  ')',  '*',  '+',   ',',  '-',  '.',  '/',
70181834Sroberto    '0',  '1',  '2',  '3',   '4',  '5',  '6',  '7',
71181834Sroberto    '8',  '9',  ':',  ';',   '<',  '=',  '>',  '?',
72181834Sroberto
73181834Sroberto    '@',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
74181834Sroberto    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
75181834Sroberto    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
76181834Sroberto    'x',  'y',  'z',  '[',   '\\', ']',  '^',  '_',
77181834Sroberto    '`',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
78181834Sroberto    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
79181834Sroberto    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
80181834Sroberto    'x',  'y',  'z',  '{',   '|',  '}',  '~',  0x7f,
81181834Sroberto
82181834Sroberto    0x80, 0x81, 0x82, 0x83,  0x84, 0x85, 0x86, 0x87,
83181834Sroberto    0x88, 0x89, 0x8A, 0x8B,  0x8C, 0x8D, 0x8E, 0x8F,
84181834Sroberto    0x90, 0x91, 0x92, 0x93,  0x94, 0x95, 0x96, 0x97,
85181834Sroberto    0x98, 0x99, 0x9A, 0x9B,  0x9C, 0x9D, 0x9E, 0x9F,
86181834Sroberto    0xA0, 0xA1, 0xA2, 0xA3,  0xA4, 0xA5, 0xA6, 0xA7,
87181834Sroberto    0xA8, 0xA9, 0xAA, 0xAB,  0xAC, 0xAD, 0xAE, 0xAF,
88181834Sroberto    0xB0, 0xB1, 0xB2, 0xB3,  0xB4, 0xB5, 0xB6, 0xB7,
89181834Sroberto    0xB8, 0xB9, 0xBA, 0xBB,  0xBC, 0xBD, 0xBE, 0xBF,
90181834Sroberto
91181834Sroberto    0xC0, 0xC1, 0xC2, 0xC3,  0xC4, 0xC5, 0xC6, 0xC7,
92181834Sroberto    0xC8, 0xC9, 0xCA, 0xCB,  0xCC, 0xCD, 0xCE, 0xCF,
93181834Sroberto    0xD0, 0xD1, 0xD2, 0xD3,  0xD4, 0xD5, 0xD6, 0xD7,
94181834Sroberto    0xD8, 0xD9, 0xDA, 0xDB,  0xDC, 0xDD, 0xDE, 0xDF,
95181834Sroberto    0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,
96181834Sroberto    0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF,
97181834Sroberto    0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,
98181834Sroberto    0xF8, 0xF9, 0xFA, 0xFB,  0xFC, 0xFD, 0xFE, 0xFF,
99181834Sroberto};
100181834Sroberto
101181834Sroberto
102181834Sroberto/*=export_func strneqvcmp
103181834Sroberto *
104181834Sroberto * what: compare two strings with an equivalence mapping
105181834Sroberto *
106181834Sroberto * arg:  + char const* + str1 + first string +
107181834Sroberto * arg:  + char const* + str2 + second string +
108181834Sroberto * arg:  + int         + ct   + compare length +
109181834Sroberto *
110181834Sroberto * ret_type:  int
111181834Sroberto * ret_desc:  the difference between two differing characters
112181834Sroberto *
113181834Sroberto * doc:
114181834Sroberto *
115181834Sroberto * Using a character mapping, two strings are compared for "equivalence".
116181834Sroberto * Each input character is mapped to a comparison character and the
117181834Sroberto * mapped-to characters are compared for the two NUL terminated input strings.
118181834Sroberto * The comparison is limited to @code{ct} bytes.
119181834Sroberto * This function name is mapped to option_strneqvcmp so as to not conflict
120181834Sroberto * with the POSIX name space.
121181834Sroberto *
122181834Sroberto * err:  none checked.  Caller responsible for seg faults.
123181834Sroberto=*/
124181834Srobertoint
125181834Srobertostrneqvcmp( tCC* s1, tCC* s2, int ct )
126181834Sroberto{
127181834Sroberto    for (; ct > 0; --ct) {
128181834Sroberto        unsigned char u1 = (unsigned char) *s1++;
129181834Sroberto        unsigned char u2 = (unsigned char) *s2++;
130181834Sroberto        int dif = charmap[ u1 ] - charmap[ u2 ];
131181834Sroberto
132181834Sroberto        if (dif != 0)
133181834Sroberto            return dif;
134181834Sroberto
135181834Sroberto        if (u1 == NUL)
136181834Sroberto            return 0;
137181834Sroberto    }
138181834Sroberto
139181834Sroberto    return 0;
140181834Sroberto}
141181834Sroberto
142181834Sroberto
143181834Sroberto/*=export_func streqvcmp
144181834Sroberto *
145181834Sroberto * what: compare two strings with an equivalence mapping
146181834Sroberto *
147181834Sroberto * arg:  + char const* + str1 + first string +
148181834Sroberto * arg:  + char const* + str2 + second string +
149181834Sroberto *
150181834Sroberto * ret_type:  int
151181834Sroberto * ret_desc:  the difference between two differing characters
152181834Sroberto *
153181834Sroberto * doc:
154181834Sroberto *
155181834Sroberto * Using a character mapping, two strings are compared for "equivalence".
156181834Sroberto * Each input character is mapped to a comparison character and the
157181834Sroberto * mapped-to characters are compared for the two NUL terminated input strings.
158181834Sroberto * This function name is mapped to option_streqvcmp so as to not conflict
159181834Sroberto * with the POSIX name space.
160181834Sroberto *
161181834Sroberto * err:  none checked.  Caller responsible for seg faults.
162181834Sroberto=*/
163181834Srobertoint
164181834Srobertostreqvcmp( tCC* s1, tCC* s2 )
165181834Sroberto{
166181834Sroberto    for (;;) {
167181834Sroberto        unsigned char u1 = (unsigned char) *s1++;
168181834Sroberto        unsigned char u2 = (unsigned char) *s2++;
169181834Sroberto        int dif = charmap[ u1 ] - charmap[ u2 ];
170181834Sroberto
171181834Sroberto        if (dif != 0)
172181834Sroberto            return dif;
173181834Sroberto
174181834Sroberto        if (u1 == NUL)
175181834Sroberto            return 0;
176181834Sroberto    }
177181834Sroberto}
178181834Sroberto
179181834Sroberto
180181834Sroberto/*=export_func streqvmap
181181834Sroberto *
182181834Sroberto * what: Set the character mappings for the streqv functions
183181834Sroberto *
184181834Sroberto * arg:  + char + From + Input character +
185181834Sroberto * arg:  + char + To   + Mapped-to character +
186181834Sroberto * arg:  + int  + ct   + compare length +
187181834Sroberto *
188181834Sroberto * doc:
189181834Sroberto *
190181834Sroberto * Set the character mapping.  If the count (@code{ct}) is set to zero, then
191181834Sroberto * the map is cleared by setting all entries in the map to their index
192181834Sroberto * value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
193181834Sroberto * character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
194181834Sroberto * are incremented and the process repeated until @code{ct} entries have been
195181834Sroberto * set. For example,
196181834Sroberto * @example
197181834Sroberto *    streqvmap( 'a', 'A', 26 );
198181834Sroberto * @end example
199181834Sroberto * @noindent
200181834Sroberto * will alter the mapping so that all English lower case letters
201181834Sroberto * will map to upper case.
202181834Sroberto *
203181834Sroberto * This function name is mapped to option_streqvmap so as to not conflict
204181834Sroberto * with the POSIX name space.
205181834Sroberto *
206181834Sroberto * err:  none.
207181834Sroberto=*/
208181834Srobertovoid
209181834Srobertostreqvmap( char From, char To, int ct )
210181834Sroberto{
211181834Sroberto    if (ct == 0) {
212181834Sroberto        ct = sizeof( charmap ) - 1;
213181834Sroberto        do  {
214181834Sroberto            charmap[ ct ] = ct;
215181834Sroberto        } while (--ct >= 0);
216181834Sroberto    }
217181834Sroberto
218181834Sroberto    else {
219181834Sroberto        int  chTo   = (int)To   & 0xFF;
220181834Sroberto        int  chFrom = (int)From & 0xFF;
221181834Sroberto
222181834Sroberto        do  {
223181834Sroberto            charmap[ chFrom ] = (unsigned)chTo;
224181834Sroberto            chFrom++;
225181834Sroberto            chTo++;
226181834Sroberto            if ((chFrom >= sizeof( charmap )) || (chTo >= sizeof( charmap )))
227181834Sroberto                break;
228181834Sroberto        } while (--ct > 0);
229181834Sroberto    }
230181834Sroberto}
231181834Sroberto
232181834Sroberto
233181834Sroberto/*=export_func strequate
234181834Sroberto *
235181834Sroberto * what: map a list of characters to the same value
236181834Sroberto *
237181834Sroberto * arg:  + char const* + ch_list + characters to equivalence +
238181834Sroberto *
239181834Sroberto * doc:
240181834Sroberto *
241181834Sroberto * Each character in the input string get mapped to the first character
242181834Sroberto * in the string.
243181834Sroberto * This function name is mapped to option_strequate so as to not conflict
244181834Sroberto * with the POSIX name space.
245181834Sroberto *
246181834Sroberto * err:  none.
247181834Sroberto=*/
248181834Srobertovoid
249181834Srobertostrequate( char const* s )
250181834Sroberto{
251181834Sroberto    if ((s != NULL) && (*s != NUL)) {
252181834Sroberto        unsigned char equiv = (unsigned)*s;
253181834Sroberto        while (*s != NUL)
254181834Sroberto            charmap[ (unsigned)*(s++) ] = equiv;
255181834Sroberto    }
256181834Sroberto}
257181834Sroberto
258181834Sroberto
259181834Sroberto/*=export_func strtransform
260181834Sroberto *
261181834Sroberto * what: convert a string into its mapped-to value
262181834Sroberto *
263181834Sroberto * arg:  + char*       + dest + output string +
264181834Sroberto * arg:  + char const* + src  + input string +
265181834Sroberto *
266181834Sroberto * doc:
267181834Sroberto *
268181834Sroberto * Each character in the input string is mapped and the mapped-to
269181834Sroberto * character is put into the output.
270181834Sroberto * This function name is mapped to option_strtransform so as to not conflict
271181834Sroberto * with the POSIX name space.
272181834Sroberto *
273181834Sroberto * err:  none.
274181834Sroberto=*/
275181834Srobertovoid
276181834Srobertostrtransform( char* d, char const* s )
277181834Sroberto{
278181834Sroberto    do  {
279181834Sroberto        *(d++) = (char)charmap[ (unsigned)*s ];
280181834Sroberto    } while (*(s++) != NUL);
281181834Sroberto}
282181834Sroberto
283181834Sroberto/*
284181834Sroberto * Local Variables:
285181834Sroberto * mode: C
286181834Sroberto * c-file-style: "stroustrup"
287181834Sroberto * indent-tabs-mode: nil
288181834Sroberto * End:
289181834Sroberto * end of autoopts/streqvcmp.c */
290