chiark / gitweb /
Change James's email address
[sympathy.git] / apps / expand.c
1 /* 
2  * expand.c:
3  *
4  * Copyright (c) 2008 James McKenzie <sympathy@madingley.org>,
5  * All rights reserved.
6  *
7  */
8
9 static char rcsid[] = "$Id: expand.c,v 1.6 2008/03/11 17:56:04 james Exp $";
10
11 /* 
12  * $Log: expand.c,v $
13  * Revision 1.6  2008/03/11 17:56:04  james
14  * *** empty log message ***
15  *
16  * Revision 1.5  2008/03/10 11:49:32  james
17  * *** empty log message ***
18  *
19  * Revision 1.4  2008/03/07 14:19:29  staffcvs
20  * *** empty log message ***
21  *
22  * Revision 1.3  2008/03/07 14:16:44  james
23  * *** empty log message ***
24  *
25  * Revision 1.2  2008/03/07 14:13:40  james
26  * *** empty log message ***
27  *
28  * Revision 1.1  2008/03/07 13:56:39  james
29  * *** empty log message ***
30  *
31  */
32
33 #include <sympathy.h>
34 #include <string.h>
35
36
37 static int
38 xdigit_to_i (char c)
39 {
40   switch (c) {
41   case '0':
42   case '1':
43   case '2':
44   case '3':
45   case '4':
46   case '5':
47   case '6':
48   case '7':
49   case '8':
50   case '9':
51     return c - '0';
52   case 'a':
53   case 'b':
54   case 'c':
55   case 'd':
56   case 'e':
57   case 'f':
58     return 0xa + (c - 'a');
59   case 'A':
60   case 'B':
61   case 'C':
62   case 'D':
63   case 'E':
64   case 'F':
65     return 0xA + (c - 'A');
66   }
67   return -1;
68 }
69
70 static int
71 my_isxdigit (char c)
72 {
73   return (xdigit_to_i (c) == -1) ? 0 : 1;
74 }
75
76
77 static int
78 my_isodigit (char c)
79 {
80   switch (c) {
81   case '0':
82   case '1':
83   case '2':
84   case '3':
85   case '4':
86   case '5':
87   case '6':
88   case '7':
89     return 1;
90   }
91   return 0;
92 }
93
94 static int
95 octal (const char **in)
96 {
97   int o = 0;
98
99   while (**in) {
100     if (!my_isodigit (**in))
101       return o;
102     o <<= 3;
103     o += (*((*in)++)) - '0';
104   }
105
106   return o;
107 }
108
109 static int
110 hex (const char **in)
111 {
112   int x = 0;
113
114   (*in)++;
115   while (**in) {
116     printf ("%c %d\n", **in, x);
117     if (!my_isxdigit (**in))
118       return x;
119     x <<= 4;
120     x += xdigit_to_i (*((*in)++));
121   }
122
123   return x;
124 }
125
126 char *
127 expand (const char *in, int *len)
128 {
129   const char *iptr = in;
130   int l;
131   char *optr;
132   char *ret;
133
134   if (!in)
135     return (char *) 0;
136   l = strlen (in);
137
138   optr = ret = malloc (l + 1);
139   if (!ret)
140     return ret;
141
142
143
144   l = 0;
145
146   while (*iptr) {
147     if (*iptr == '\\') {
148       iptr++;
149       switch (*iptr) {
150       case '\'':
151       case '\"':
152       case '\?':
153       case '\\':
154         *(optr++) = *(iptr++);
155         l++;
156         break;
157       case 'a':
158         *(optr++) = '\a';
159         l++;
160         iptr++;
161         break;
162       case 'b':
163         *(optr++) = '\b';
164         l++;
165         iptr++;
166         break;
167       case 'f':
168         *(optr++) = '\f';
169         l++;
170         iptr++;
171         break;
172       case 'n':
173         *(optr++) = '\n';
174         l++;
175         iptr++;
176         break;
177       case 'r':
178         *(optr++) = '\r';
179         l++;
180         iptr++;
181         break;
182       case 't':
183         *(optr++) = '\t';
184         l++;
185         iptr++;
186         break;
187       case 'v':
188         *(optr++) = '\v';
189         l++;
190         iptr++;
191         break;
192       case '0':
193       case '1':
194       case '2':
195       case '3':
196       case '4':
197       case '5':
198       case '6':
199       case '7':
200         *(optr++) = octal (&iptr);
201         l++;
202         break;
203       case 'x':
204         *(optr++) = hex (&iptr);
205         l++;
206         break;
207       default:
208         *(optr++) = '\\';
209         l++;
210         *(optr++) = *(iptr++);
211         l++;
212       }
213     } else {
214       *(optr++) = *(iptr++);
215       l++;
216     }
217   }
218
219   if (*len)
220     *len = l;
221
222
223   *(optr++) = 0;
224   return ret;
225 }