xref: /titanic_50/usr/src/lib/libast/common/string/chresc.c (revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 /*
24  * Glenn Fowler
25  * AT&T Research
26  *
27  * return the next character in the string s
28  * \ character constants are converted
29  * p is updated to point to the next character in s
30  */
31 
32 #include <ast.h>
33 #include <ctype.h>
34 
35 #include <ccode.h>
36 #if !_PACKAGE_astsa
37 #include <regex.h>
38 #endif
39 
40 int
41 chresc(register const char* s, char** p)
42 {
43 	register const char*	q;
44 	register int		c;
45 	const char*		e;
46 #if !_PACKAGE_astsa
47 	int			n;
48 	char			buf[64];
49 #endif
50 
51 	switch (c = mbchar(s))
52 	{
53 	case 0:
54 		s--;
55 		break;
56 	case '\\':
57 		switch (c = *s++)
58 		{
59 		case '0': case '1': case '2': case '3':
60 		case '4': case '5': case '6': case '7':
61 			c -= '0';
62 			q = s + 2;
63 			while (s < q)
64 				switch (*s)
65 				{
66 				case '0': case '1': case '2': case '3':
67 				case '4': case '5': case '6': case '7':
68 					c = (c << 3) + *s++ - '0';
69 					break;
70 				default:
71 					q = s;
72 					break;
73 				}
74 			break;
75 		case 'a':
76 			c = CC_bel;
77 			break;
78 		case 'b':
79 			c = '\b';
80 			break;
81 		case 'c':
82 		control:
83 			if (c = *s)
84 			{
85 				s++;
86 				if (islower(c))
87 					c = toupper(c);
88 			}
89 			c = ccmapc(c, CC_NATIVE, CC_ASCII);
90 			c ^= 0x40;
91 			c = ccmapc(c, CC_ASCII, CC_NATIVE);
92 			break;
93 		case 'C':
94 			if (*s == '-' && *(s + 1))
95 			{
96 				s++;
97 				goto control;
98 			}
99 #if !_PACKAGE_astsa
100 			if (*s == '[' && (n = regcollate(s + 1, (char**)&e, buf, sizeof(buf))) >= 0)
101 			{
102 				if (n == 1)
103 					c = buf[0];
104 				s = e;
105 			}
106 #endif
107 			break;
108 		case 'e':
109 		case 'E':
110 			c = CC_esc;
111 			break;
112 		case 'f':
113 			c = '\f';
114 			break;
115 		case 'M':
116 			if (*s == '-')
117 			{
118 				s++;
119 				c = CC_esc;
120 			}
121 			break;
122 		case 'n':
123 			c = '\n';
124 			break;
125 		case 'r':
126 			c = '\r';
127 			break;
128 		case 't':
129 			c = '\t';
130 			break;
131 		case 'v':
132 			c = CC_vt;
133 			break;
134 		case 'u':
135 		case 'U':
136 		case 'x':
137 			c = 0;
138 			q = c == 'u' ? (s + 4) : c == 'U' ? (s + 8) : (char*)0;
139 			e = s;
140 			while (!e || !q || s < q)
141 			{
142 				switch (*s)
143 				{
144 				case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
145 					c = (c << 4) + *s++ - 'a' + 10;
146 					continue;
147 				case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
148 					c = (c << 4) + *s++ - 'A' + 10;
149 					continue;
150 				case '0': case '1': case '2': case '3': case '4':
151 				case '5': case '6': case '7': case '8': case '9':
152 					c = (c << 4) + *s++ - '0';
153 					continue;
154 				case '{':
155 				case '[':
156 					if (s != e)
157 						break;
158 					e = 0;
159 					s++;
160 					continue;
161 				case '}':
162 				case ']':
163 					if (!e)
164 						s++;
165 					break;
166 				default:
167 					break;
168 				}
169 				break;
170 			}
171 			break;
172 		case 0:
173 			s--;
174 			break;
175 		}
176 		break;
177 	}
178 	if (p)
179 		*p = (char*)s;
180 	return c;
181 }
182