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