1181834Sroberto
2285612Sdelphij/**
3285612Sdelphij * \file streqvcmp.c
4181834Sroberto *
5181834Sroberto *  String Equivalence Comparison
6181834Sroberto *
7181834Sroberto *  These routines allow any character to be mapped to any other
8181834Sroberto *  character before comparison.  In processing long option names,
9181834Sroberto *  the characters "-", "_" and "^" all need to be equivalent
10181834Sroberto *  (because they are treated so by different development environments).
11285612Sdelphij *
12285612Sdelphij * @addtogroup autoopts
13285612Sdelphij * @{
14181834Sroberto */
15181834Sroberto/*
16285612Sdelphij *  This file is part of AutoOpts, a companion to AutoGen.
17285612Sdelphij *  AutoOpts is free software.
18285612Sdelphij *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
19181834Sroberto *
20285612Sdelphij *  AutoOpts is available under any one of two licenses.  The license
21285612Sdelphij *  in use must be one of these two and the choice is under the control
22285612Sdelphij *  of the user of the license.
23181834Sroberto *
24285612Sdelphij *   The GNU Lesser General Public License, version 3 or later
25285612Sdelphij *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
26181834Sroberto *
27285612Sdelphij *   The Modified Berkeley Software Distribution License
28285612Sdelphij *      See the file "COPYING.mbsd"
29181834Sroberto *
30285612Sdelphij *  These files have the following sha256 sums:
31181834Sroberto *
32285612Sdelphij *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
33285612Sdelphij *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
34285612Sdelphij *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
35181834Sroberto *
36181834Sroberto * This array is designed for mapping upper and lower case letter
37181834Sroberto * together for a case independent comparison.  The mappings are
38181834Sroberto * based upon ascii character sequences.
39181834Sroberto */
40181834Srobertostatic unsigned char charmap[] = {
41285612Sdelphij    NUL,  0x01, 0x02, 0x03,  0x04, 0x05, 0x06, '\a',
42285612Sdelphij    '\b', '\t', NL,   '\v',  '\f', '\r', 0x0E, 0x0F,
43181834Sroberto    0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,
44181834Sroberto    0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E, 0x1F,
45181834Sroberto
46181834Sroberto    ' ',  '!',  '"',  '#',   '$',  '%',  '&',  '\'',
47181834Sroberto    '(',  ')',  '*',  '+',   ',',  '-',  '.',  '/',
48181834Sroberto    '0',  '1',  '2',  '3',   '4',  '5',  '6',  '7',
49181834Sroberto    '8',  '9',  ':',  ';',   '<',  '=',  '>',  '?',
50181834Sroberto
51181834Sroberto    '@',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
52181834Sroberto    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
53181834Sroberto    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
54181834Sroberto    'x',  'y',  'z',  '[',   '\\', ']',  '^',  '_',
55181834Sroberto    '`',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
56181834Sroberto    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
57181834Sroberto    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
58181834Sroberto    'x',  'y',  'z',  '{',   '|',  '}',  '~',  0x7f,
59181834Sroberto
60181834Sroberto    0x80, 0x81, 0x82, 0x83,  0x84, 0x85, 0x86, 0x87,
61181834Sroberto    0x88, 0x89, 0x8A, 0x8B,  0x8C, 0x8D, 0x8E, 0x8F,
62181834Sroberto    0x90, 0x91, 0x92, 0x93,  0x94, 0x95, 0x96, 0x97,
63181834Sroberto    0x98, 0x99, 0x9A, 0x9B,  0x9C, 0x9D, 0x9E, 0x9F,
64181834Sroberto    0xA0, 0xA1, 0xA2, 0xA3,  0xA4, 0xA5, 0xA6, 0xA7,
65181834Sroberto    0xA8, 0xA9, 0xAA, 0xAB,  0xAC, 0xAD, 0xAE, 0xAF,
66181834Sroberto    0xB0, 0xB1, 0xB2, 0xB3,  0xB4, 0xB5, 0xB6, 0xB7,
67181834Sroberto    0xB8, 0xB9, 0xBA, 0xBB,  0xBC, 0xBD, 0xBE, 0xBF,
68181834Sroberto
69181834Sroberto    0xC0, 0xC1, 0xC2, 0xC3,  0xC4, 0xC5, 0xC6, 0xC7,
70181834Sroberto    0xC8, 0xC9, 0xCA, 0xCB,  0xCC, 0xCD, 0xCE, 0xCF,
71181834Sroberto    0xD0, 0xD1, 0xD2, 0xD3,  0xD4, 0xD5, 0xD6, 0xD7,
72181834Sroberto    0xD8, 0xD9, 0xDA, 0xDB,  0xDC, 0xDD, 0xDE, 0xDF,
73181834Sroberto    0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,
74181834Sroberto    0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF,
75181834Sroberto    0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,
76181834Sroberto    0xF8, 0xF9, 0xFA, 0xFB,  0xFC, 0xFD, 0xFE, 0xFF,
77181834Sroberto};
78181834Sroberto
79181834Sroberto
80181834Sroberto/*=export_func strneqvcmp
81181834Sroberto *
82181834Sroberto * what: compare two strings with an equivalence mapping
83181834Sroberto *
84285612Sdelphij * arg:  + char const * + str1 + first string +
85285612Sdelphij * arg:  + char const * + str2 + second string +
86285612Sdelphij * arg:  + int          + ct   + compare length +
87181834Sroberto *
88181834Sroberto * ret_type:  int
89181834Sroberto * ret_desc:  the difference between two differing characters
90181834Sroberto *
91181834Sroberto * doc:
92181834Sroberto *
93181834Sroberto * Using a character mapping, two strings are compared for "equivalence".
94181834Sroberto * Each input character is mapped to a comparison character and the
95181834Sroberto * mapped-to characters are compared for the two NUL terminated input strings.
96181834Sroberto * The comparison is limited to @code{ct} bytes.
97181834Sroberto * This function name is mapped to option_strneqvcmp so as to not conflict
98181834Sroberto * with the POSIX name space.
99181834Sroberto *
100181834Sroberto * err:  none checked.  Caller responsible for seg faults.
101181834Sroberto=*/
102181834Srobertoint
103285612Sdelphijstrneqvcmp(char const * s1, char const * s2, int ct)
104181834Sroberto{
105181834Sroberto    for (; ct > 0; --ct) {
106181834Sroberto        unsigned char u1 = (unsigned char) *s1++;
107181834Sroberto        unsigned char u2 = (unsigned char) *s2++;
108285612Sdelphij        int dif;
109285612Sdelphij        if (u1 == u2) {
110285612Sdelphij            if (u1 == NUL)
111285612Sdelphij                return 0;
112285612Sdelphij            continue;
113285612Sdelphij        }
114181834Sroberto
115285612Sdelphij        dif = charmap[ u1 ] - charmap[ u2 ];
116285612Sdelphij
117181834Sroberto        if (dif != 0)
118181834Sroberto            return dif;
119181834Sroberto
120181834Sroberto        if (u1 == NUL)
121181834Sroberto            return 0;
122181834Sroberto    }
123181834Sroberto
124181834Sroberto    return 0;
125181834Sroberto}
126181834Sroberto
127181834Sroberto
128181834Sroberto/*=export_func streqvcmp
129181834Sroberto *
130181834Sroberto * what: compare two strings with an equivalence mapping
131181834Sroberto *
132285612Sdelphij * arg:  + char const * + str1 + first string +
133285612Sdelphij * arg:  + char const * + str2 + second string +
134181834Sroberto *
135181834Sroberto * ret_type:  int
136181834Sroberto * ret_desc:  the difference between two differing characters
137181834Sroberto *
138181834Sroberto * doc:
139181834Sroberto *
140181834Sroberto * Using a character mapping, two strings are compared for "equivalence".
141181834Sroberto * Each input character is mapped to a comparison character and the
142181834Sroberto * mapped-to characters are compared for the two NUL terminated input strings.
143181834Sroberto * This function name is mapped to option_streqvcmp so as to not conflict
144181834Sroberto * with the POSIX name space.
145181834Sroberto *
146181834Sroberto * err:  none checked.  Caller responsible for seg faults.
147181834Sroberto=*/
148181834Srobertoint
149285612Sdelphijstreqvcmp(char const * s1, char const * s2)
150181834Sroberto{
151181834Sroberto    for (;;) {
152181834Sroberto        unsigned char u1 = (unsigned char) *s1++;
153181834Sroberto        unsigned char u2 = (unsigned char) *s2++;
154285612Sdelphij        int dif;
155285612Sdelphij        if (u1 == u2) {
156285612Sdelphij            if (u1 == NUL)
157285612Sdelphij                return 0;
158285612Sdelphij            continue;
159285612Sdelphij        }
160181834Sroberto
161285612Sdelphij        dif = charmap[ u1 ] - charmap[ u2 ];
162285612Sdelphij
163181834Sroberto        if (dif != 0)
164181834Sroberto            return dif;
165181834Sroberto
166181834Sroberto        if (u1 == NUL)
167181834Sroberto            return 0;
168181834Sroberto    }
169181834Sroberto}
170181834Sroberto
171181834Sroberto
172181834Sroberto/*=export_func streqvmap
173181834Sroberto *
174181834Sroberto * what: Set the character mappings for the streqv functions
175181834Sroberto *
176285612Sdelphij * arg:  + char + from + Input character +
177285612Sdelphij * arg:  + char + to   + Mapped-to character +
178181834Sroberto * arg:  + int  + ct   + compare length +
179181834Sroberto *
180181834Sroberto * doc:
181181834Sroberto *
182181834Sroberto * Set the character mapping.  If the count (@code{ct}) is set to zero, then
183181834Sroberto * the map is cleared by setting all entries in the map to their index
184181834Sroberto * value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
185181834Sroberto * character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
186181834Sroberto * are incremented and the process repeated until @code{ct} entries have been
187181834Sroberto * set. For example,
188181834Sroberto * @example
189285612Sdelphij *    streqvmap('a', 'A', 26);
190181834Sroberto * @end example
191181834Sroberto * @noindent
192181834Sroberto * will alter the mapping so that all English lower case letters
193181834Sroberto * will map to upper case.
194181834Sroberto *
195181834Sroberto * This function name is mapped to option_streqvmap so as to not conflict
196181834Sroberto * with the POSIX name space.
197181834Sroberto *
198181834Sroberto * err:  none.
199181834Sroberto=*/
200181834Srobertovoid
201285612Sdelphijstreqvmap(char from, char to, int ct)
202181834Sroberto{
203181834Sroberto    if (ct == 0) {
204285612Sdelphij        ct = sizeof(charmap) - 1;
205181834Sroberto        do  {
206285612Sdelphij            charmap[ct] = (unsigned char)ct;
207181834Sroberto        } while (--ct >= 0);
208181834Sroberto    }
209181834Sroberto
210181834Sroberto    else {
211285612Sdelphij        unsigned int i_to   = (int)to   & 0xFF;
212285612Sdelphij        unsigned int i_from = (int)from & 0xFF;
213181834Sroberto
214181834Sroberto        do  {
215285612Sdelphij            charmap[i_from] = (unsigned char)i_to;
216285612Sdelphij            i_from++;
217285612Sdelphij            i_to++;
218285612Sdelphij            if ((i_from >= sizeof(charmap)) || (i_to >= sizeof(charmap)))
219181834Sroberto                break;
220181834Sroberto        } while (--ct > 0);
221181834Sroberto    }
222181834Sroberto}
223181834Sroberto
224181834Sroberto
225181834Sroberto/*=export_func strequate
226181834Sroberto *
227181834Sroberto * what: map a list of characters to the same value
228181834Sroberto *
229285612Sdelphij * arg:  + char const * + ch_list + characters to equivalence +
230181834Sroberto *
231181834Sroberto * doc:
232181834Sroberto *
233181834Sroberto * Each character in the input string get mapped to the first character
234181834Sroberto * in the string.
235181834Sroberto * This function name is mapped to option_strequate so as to not conflict
236181834Sroberto * with the POSIX name space.
237181834Sroberto *
238181834Sroberto * err:  none.
239181834Sroberto=*/
240181834Srobertovoid
241285612Sdelphijstrequate(char const * s)
242181834Sroberto{
243181834Sroberto    if ((s != NULL) && (*s != NUL)) {
244285612Sdelphij        unsigned char equiv = (unsigned char)*s;
245181834Sroberto        while (*s != NUL)
246285612Sdelphij            charmap[(unsigned char)*(s++)] = equiv;
247181834Sroberto    }
248181834Sroberto}
249181834Sroberto
250181834Sroberto
251181834Sroberto/*=export_func strtransform
252181834Sroberto *
253181834Sroberto * what: convert a string into its mapped-to value
254181834Sroberto *
255285612Sdelphij * arg:  + char *       + dest + output string +
256285612Sdelphij * arg:  + char const * + src  + input string +
257181834Sroberto *
258181834Sroberto * doc:
259181834Sroberto *
260181834Sroberto * Each character in the input string is mapped and the mapped-to
261181834Sroberto * character is put into the output.
262181834Sroberto * This function name is mapped to option_strtransform so as to not conflict
263181834Sroberto * with the POSIX name space.
264181834Sroberto *
265285612Sdelphij * The source and destination may be the same.
266285612Sdelphij *
267181834Sroberto * err:  none.
268181834Sroberto=*/
269181834Srobertovoid
270285612Sdelphijstrtransform(char * d, char const * s)
271181834Sroberto{
272181834Sroberto    do  {
273285612Sdelphij        *(d++) = (char)charmap[(unsigned char)*s];
274181834Sroberto    } while (*(s++) != NUL);
275181834Sroberto}
276181834Sroberto
277285612Sdelphij/** @}
278285612Sdelphij *
279181834Sroberto * Local Variables:
280181834Sroberto * mode: C
281181834Sroberto * c-file-style: "stroustrup"
282181834Sroberto * indent-tabs-mode: nil
283181834Sroberto * End:
284181834Sroberto * end of autoopts/streqvcmp.c */
285