1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright (c) 1996, by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * Implementation of the mks M_INVARIANT family of mapping macros.
31 * Based on the IBM C/370 getsyntx() and variant.h implementation.
32 *
33 * Copyright 1993 by Mortice Kern Systems Inc.  All rights reserved.
34 *
35 */
36
37#ifdef M_RCSID
38#ifndef lint
39static char const rcsID[] = "$Header: /rd/src/libc/mks/rcs/m_varian.c 1.14 1994/12/08 23:14:58 ross Exp $";
40#endif /* lint */
41#endif /* M_RCSID */
42
43#include <mks.h>
44#include <m_invari.h>
45
46#ifdef M_VARIANTS
47
48#include <variant.h>
49
50#define SHORT_STRING_LEN	100
51
52void __m_setinvariant(void);
53
54char	__m_invariant[M_CSETSIZE] = {
55	  0,   1,   2,   3,   4,   5,   6,   7,
56	  8,   9,  10,  11,  12,  13,  14,  15,
57	 16,  17,  18,  19,  20,  21,  22,  23,
58	 24,  25,  26,  27,  28,  29,  30,  31,
59	 32,  33,  34,  35,  36,  37,  38,  39,
60	 40,  41,  42,  43,  44,  45,  46,  47,
61	 48,  49,  50,  51,  52,  53,  54,  55,
62	 56,  57,  58,  59,  60,  61,  62,  63,
63	 64,  65,  66,  67,  68,  69,  70,  71,
64	 72,  73,  74,  75,  76,  77,  78,  79,
65	 80,  81,  82,  83,  84,  85,  86,  87,
66	 88,  89,  90,  91,  92,  93,  94,  95,
67	 96,  97,  98,  99, 100, 101, 102, 103,
68	104, 105, 106, 107, 108, 109, 110, 111,
69	112, 113, 114, 115, 116, 117, 118, 119,
70	120, 121, 122, 123, 124, 125, 126, 127,
71	128, 129, 130, 131, 132, 133, 134, 135,
72	136, 137, 138, 139, 140, 141, 142, 143,
73	144, 145, 146, 147, 148, 149, 150, 151,
74	152, 153, 154, 155, 156, 157, 158, 159,
75	160, 161, 162, 163, 164, 165, 166, 167,
76	168, 169, 170, 171, 172, 173, 174, 175,
77	176, 177, 178, 179, 180, 181, 182, 183,
78	184, 185, 186, 187, 188, 189, 190, 191,
79	192, 193, 194, 195, 196, 197, 198, 199,
80	200, 201, 202, 203, 204, 205, 206, 207,
81	208, 209, 210, 211, 212, 213, 214, 215,
82	216, 217, 218, 219, 220, 221, 222, 223,
83	224, 225, 226, 227, 228, 229, 230, 231,
84	232, 233, 234, 235, 236, 237, 238, 239,
85	240, 241, 242, 243, 244, 245, 246, 247,
86	248, 249, 250, 251, 252, 253, 254, 255,
87#if M_CSETSIZE > 256
88	256, 257, 258, 259, 260, 261, 262, 263,
89	264, 265, 266, 267, 268, 269, 270, 271,
90	272, 273, 274, 275, 276, 277, 278, 279,
91	280, 281, 282, 283, 284, 285, 286, 287,
92	288, 289, 290, 291, 292, 293, 294, 295,
93	296, 297, 298, 299, 300, 301, 302, 303,
94	304, 305, 306, 307, 308, 309, 310, 311,
95	312, 313, 314, 315, 316, 317, 318, 319,
96	320, 321, 322, 323, 324, 325, 326, 327,
97	328, 329, 330, 331, 332, 333, 334, 335,
98	336, 337, 338, 339, 340, 341, 342, 343,
99	344, 345, 346, 347, 348, 349, 350, 351,
100	352, 353, 354, 355, 356, 357, 358, 359,
101	360, 361, 362, 363, 364, 365, 366, 367,
102	368, 369, 370, 371, 372, 373, 374, 375,
103	376, 377, 378, 379, 380, 381, 382, 383,
104	384, 385, 386, 387, 388, 389, 390, 391,
105	392, 393, 394, 395, 396, 397, 398, 399,
106	400, 401, 402, 403, 404, 405, 406, 407,
107	408, 409, 410, 411, 412, 413, 414, 415,
108	416, 417, 418, 419, 420, 421, 422, 423,
109	424, 425, 426, 427, 428, 429, 430, 431,
110	432, 433, 434, 435, 436, 437, 438, 439,
111	440, 441, 442, 443, 444, 445, 446, 447,
112	448, 449, 450, 451, 452, 453, 454, 455,
113	456, 457, 458, 459, 460, 461, 462, 463,
114	464, 465, 466, 467, 468, 469, 470, 471,
115	472, 473, 474, 475, 476, 477, 478, 479,
116	480, 481, 482, 483, 484, 485, 486, 487,
117	488, 489, 490, 491, 492, 493, 494, 495,
118	496, 497, 498, 499, 500, 501, 502, 503,
119	504, 505, 506, 507, 508, 509, 510, 511
120#endif
121#if M_CSETSIZE > 512
122#error __m_invariant table needs to be extended
123#endif
124};
125char	__m_unvariant[M_CSETSIZE] = {
126	  0,   1,   2,   3,   4,   5,   6,   7,
127	  8,   9,  10,  11,  12,  13,  14,  15,
128	 16,  17,  18,  19,  20,  21,  22,  23,
129	 24,  25,  26,  27,  28,  29,  30,  31,
130	 32,  33,  34,  35,  36,  37,  38,  39,
131	 40,  41,  42,  43,  44,  45,  46,  47,
132	 48,  49,  50,  51,  52,  53,  54,  55,
133	 56,  57,  58,  59,  60,  61,  62,  63,
134	 64,  65,  66,  67,  68,  69,  70,  71,
135	 72,  73,  74,  75,  76,  77,  78,  79,
136	 80,  81,  82,  83,  84,  85,  86,  87,
137	 88,  89,  90,  91,  92,  93,  94,  95,
138	 96,  97,  98,  99, 100, 101, 102, 103,
139	104, 105, 106, 107, 108, 109, 110, 111,
140	112, 113, 114, 115, 116, 117, 118, 119,
141	120, 121, 122, 123, 124, 125, 126, 127,
142	128, 129, 130, 131, 132, 133, 134, 135,
143	136, 137, 138, 139, 140, 141, 142, 143,
144	144, 145, 146, 147, 148, 149, 150, 151,
145	152, 153, 154, 155, 156, 157, 158, 159,
146	160, 161, 162, 163, 164, 165, 166, 167,
147	168, 169, 170, 171, 172, 173, 174, 175,
148	176, 177, 178, 179, 180, 181, 182, 183,
149	184, 185, 186, 187, 188, 189, 190, 191,
150	192, 193, 194, 195, 196, 197, 198, 199,
151	200, 201, 202, 203, 204, 205, 206, 207,
152	208, 209, 210, 211, 212, 213, 214, 215,
153	216, 217, 218, 219, 220, 221, 222, 223,
154	224, 225, 226, 227, 228, 229, 230, 231,
155	232, 233, 234, 235, 236, 237, 238, 239,
156	240, 241, 242, 243, 244, 245, 246, 247,
157	248, 249, 250, 251, 252, 253, 254, 255,
158#if M_CSETSIZE > 256
159	256, 257, 258, 259, 260, 261, 262, 263,
160	264, 265, 266, 267, 268, 269, 270, 271,
161	272, 273, 274, 275, 276, 277, 278, 279,
162	280, 281, 282, 283, 284, 285, 286, 287,
163	288, 289, 290, 291, 292, 293, 294, 295,
164	296, 297, 298, 299, 300, 301, 302, 303,
165	304, 305, 306, 307, 308, 309, 310, 311,
166	312, 313, 314, 315, 316, 317, 318, 319,
167	320, 321, 322, 323, 324, 325, 326, 327,
168	328, 329, 330, 331, 332, 333, 334, 335,
169	336, 337, 338, 339, 340, 341, 342, 343,
170	344, 345, 346, 347, 348, 349, 350, 351,
171	352, 353, 354, 355, 356, 357, 358, 359,
172	360, 361, 362, 363, 364, 365, 366, 367,
173	368, 369, 370, 371, 372, 373, 374, 375,
174	376, 377, 378, 379, 380, 381, 382, 383,
175	384, 385, 386, 387, 388, 389, 390, 391,
176	392, 393, 394, 395, 396, 397, 398, 399,
177	400, 401, 402, 403, 404, 405, 406, 407,
178	408, 409, 410, 411, 412, 413, 414, 415,
179	416, 417, 418, 419, 420, 421, 422, 423,
180	424, 425, 426, 427, 428, 429, 430, 431,
181	432, 433, 434, 435, 436, 437, 438, 439,
182	440, 441, 442, 443, 444, 445, 446, 447,
183	448, 449, 450, 451, 452, 453, 454, 455,
184	456, 457, 458, 459, 460, 461, 462, 463,
185	464, 465, 466, 467, 468, 469, 470, 471,
186	472, 473, 474, 475, 476, 477, 478, 479,
187	480, 481, 482, 483, 484, 485, 486, 487,
188	488, 489, 490, 491, 492, 493, 494, 495,
189	496, 497, 498, 499, 500, 501, 502, 503,
190	504, 505, 506, 507, 508, 509, 510, 511
191#endif
192#if M_CSETSIZE > 512
193#error __m_unvariant table needs to be extended
194#endif
195};
196
197/*f
198 * Initialize the variant <--> invariant tables.
199 * May be called more than once -- successive calls ignored.
200 * Void return -- can't fail.
201 */
202void
203m_invariantinit(void)
204{
205	static int first = 1;
206
207	if (!first)
208		return;
209	first = 0;
210	__m_setinvariant();
211	return;
212}
213
214/*f
215 * Initialize the variant -> invariant tables.
216 * Void return -- can't fail.
217 */
218void
219__m_setinvariant(void)
220{
221	int i;
222	struct variant *v;
223
224	/* Initialize to identity mappings */
225	for (i = 0; i < M_CSETSIZE; i++) {
226		__m_invariant[i] = i;
227		__m_unvariant[i] = i;
228	}
229
230	/*
231	 * Find the set of variant characters
232	 * On error, return success -- i.e. assume it wasn't specified, and
233	 * hence it is the identity.
234	 */
235	if ((v = getsyntx()) == NULL)
236		return;
237
238	/*
239	 * Build the invariant mapping tables: map from current codeset's
240	 * variant locations, to the location that we were compiled in.
241	 */
242	__m_invariant[v->backslash] = '\\';
243	__m_invariant[v->right_bracket] = ']';
244	__m_invariant[v->left_bracket] = '[';
245	__m_invariant[v->right_brace] = '}';
246	__m_invariant[v->left_brace] = '{';
247	__m_invariant[v->circumflex] = '^';
248	__m_invariant[v->tilde] = '~';
249	__m_invariant[v->exclamation_mark] = '!';
250	__m_invariant[v->number_sign] = '#';
251	__m_invariant[v->vertical_line] = '|';
252	__m_invariant[v->dollar_sign] = '$';
253	__m_invariant[v->commercial_at] = '@';
254	__m_invariant[v->grave_accent] = '`';
255
256	/*
257	 * Build the unvariant mapping tables: map from compiled codeset
258	 * to that of the current codeset.
259	 */
260	__m_unvariant['\\'] = v->backslash;
261	__m_unvariant[']'] = v->right_bracket;
262	__m_unvariant['['] = v->left_bracket;
263	__m_unvariant['}'] = v->right_brace;
264	__m_unvariant['{'] = v->left_brace;
265	__m_unvariant['^'] = v->circumflex;
266	__m_unvariant['~'] = v->tilde;
267	__m_unvariant['!'] = v->exclamation_mark;
268	__m_unvariant['#'] = v->number_sign;
269	__m_unvariant['|'] = v->vertical_line;
270	__m_unvariant['$'] = v->dollar_sign;
271	__m_unvariant['@'] = v->commercial_at;
272	__m_unvariant['`'] = v->grave_accent;
273
274	return;
275}
276
277/*f
278 * Convert a compiled in string to the external form.  Assumes a fixed
279 * length short string which is available until another call to m_unvariantstr.
280 * Uses 10 alternating strings to allow multiple calls on a printf.
281 * The extra buffers are probably only required by yacc.
282 */
283char *
284m_unvariantstr(char const *s)
285{
286	static char str[10][SHORT_STRING_LEN];
287	static int buf = 0;
288	char *ret;
289	char c;
290	int i = 0;
291
292	ret = str[buf++];
293	if (buf >= 10)
294		buf = 0;
295
296	while((ret[i++] = M_UNVARIANT(*s)) != '\0') {
297		s++;
298		if (i >= SHORT_STRING_LEN) {
299			fprintf(stderr, "m_unvariantstr: internal error.\n"),
300			abort();
301		}
302	}
303	ret[i] = '\0';
304	return ret;
305}
306
307/*f
308 * Ditto, for wchar's
309 */
310wchar_t *
311m_wunvariantstr(wchar_t const *s)
312{
313	static wchar_t str[SHORT_STRING_LEN];
314	static wchar_t * const strend = str + sizeof(str);
315	wchar_t *s1;
316	int i = 0;
317
318	for (s1 = str ; *s != '\0'; s++) {
319		*s1++ = M_UNVARIANT(*s);
320		if (str == strend) {
321			fprintf(stderr, "m_wunvariantstr: internal error.\n"),
322			abort();
323		}
324	}
325	*s1 = '\0';
326
327	return str;
328}
329#endif /* M_VARIANTS */
330