Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libdss/cxmap.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2002-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* C expression library value map support
23
*
24
* Glenn Fowler
25
* AT&T Research
26
*/
27
28
#include "cxlib.h"
29
30
typedef struct Frame_s
31
{
32
struct Frame_s* prev;
33
Dt_t* str2num;
34
} Frame_t;
35
36
/*
37
* dt string ignorecase comparison
38
*/
39
40
static int
41
ignorecase(Dt_t* dt, void* a, void* b, Dtdisc_t* disc)
42
{
43
return strcasecmp((char*)a, (char*)b);
44
}
45
46
/*
47
* cxinitmap helper
48
*/
49
50
static int
51
initmap(Frame_t* frame, Cxmap_t* map, Cxdisc_t* disc)
52
{
53
register Cxpart_t* part;
54
register Cxitem_t* item;
55
Frame_t top;
56
Frame_t* fp;
57
int easy;
58
Cxunsigned_t masks;
59
60
static Dtdisc_t num2strdisc;
61
static Dtdisc_t str2numdisc;
62
static Dtdisc_t stricase2numdisc;
63
64
if (map->header.flags & CX_INITIALIZED)
65
return -1;
66
map->header.flags |= CX_INITIALIZED;
67
for (;;)
68
{
69
if (!map->mask)
70
map->mask = ~map->mask;
71
if (!map->map)
72
break;
73
map = map->map;
74
}
75
if (!map->part)
76
return 0;
77
if (map->str2num)
78
{
79
if (!frame)
80
return 0;
81
easy = 0;
82
}
83
else
84
{
85
str2numdisc.link = offsetof(Cxitem_t, str2num);
86
str2numdisc.key = offsetof(Cxitem_t, name);
87
str2numdisc.size = -1;
88
if (map->header.flags & CX_IGNORECASE)
89
{
90
stricase2numdisc = str2numdisc;
91
stricase2numdisc.comparf = ignorecase;
92
map->str2num = dtopen(&stricase2numdisc, Dtoset);
93
}
94
else
95
map->str2num = dtopen(&str2numdisc, Dtoset);
96
if (!map->str2num)
97
{
98
if (disc->errorf)
99
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
100
return -1;
101
}
102
top.prev = frame;
103
top.str2num = map->str2num;
104
frame = &top;
105
easy = 1;
106
}
107
for (part = map->part; part; part = part->next)
108
{
109
if (part->mask)
110
easy = 0;
111
else
112
part->mask = ~part->mask;
113
masks = part->item ? part->item->mask : 0;
114
for (item = part->item; item; item = item->next)
115
{
116
for (fp = frame; fp; fp = fp->prev)
117
dtinsert(fp->str2num, item);
118
if (item->mask != masks)
119
part->flags |= CX_ALL;
120
if (item->mask)
121
easy = 0;
122
else
123
item->mask = ~item->mask;
124
if (item->map)
125
{
126
if (initmap(frame, item->map, disc))
127
return -1;
128
easy = 0;
129
}
130
}
131
}
132
if (easy)
133
{
134
num2strdisc.link = offsetof(Cxitem_t, num2str);
135
num2strdisc.key = offsetof(Cxitem_t, value);
136
num2strdisc.size = sizeof(Cxunsigned_t);
137
if (!(map->num2str = dtopen(&num2strdisc, Dtoset)))
138
{
139
if (disc->errorf)
140
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
141
return -1;
142
}
143
part = map->part;
144
map->shift += part->shift;
145
map->mask |= part->mask;
146
for (item = part->item; item; item = item->next)
147
dtinsert(map->num2str, item);
148
}
149
return 0;
150
}
151
152
/*
153
* initialize map
154
*/
155
156
int
157
cxinitmap(Cxmap_t* map, Cxdisc_t* disc)
158
{
159
return initmap(NiL, map, disc);
160
}
161
162
/*
163
* cxnum2str helper
164
*/
165
166
static int
167
num2str(Cx_t* cx, Cxmap_t* map, Sfio_t* sp, Cxunsigned_t num, int del)
168
{
169
register Cxpart_t* part;
170
register Cxitem_t* item;
171
register Cxedit_t* edit;
172
Cxunsigned_t n;
173
char* s;
174
int v;
175
int p;
176
int r;
177
regmatch_t match[10];
178
char buf[64];
179
180
for (;;)
181
{
182
num >>= map->shift;
183
num &= map->mask;
184
if (!map->map)
185
break;
186
map = map->map;
187
}
188
if (map->num2str && (item = (Cxitem_t*)dtmatch(map->num2str, &num)))
189
{
190
sfprintf(sp, "%c%s", del, item->name);
191
return 1;
192
}
193
r = 0;
194
for (part = map->part; part; part = part->next)
195
{
196
n = num;
197
n >>= part->shift;
198
n &= part->mask;
199
v = !(part->flags & CX_ALL);
200
p = r;
201
for (item = part->item; item; item = item->next)
202
if ((n & item->mask) == item->value)
203
{
204
if (item->name)
205
{
206
sfprintf(sp, "%c%s", del, item->name);
207
r++;
208
}
209
if (item->map)
210
r += num2str(cx, item->map, sp, n, del);
211
if (v)
212
break;
213
}
214
if (r == p && part->num2str)
215
{
216
buf[0] = 0;
217
for (edit = part->num2str; edit; edit = edit->next)
218
if (!edit->num2strf)
219
{
220
if (!buf[0])
221
sfsprintf(buf, sizeof(buf), "%lld", n);
222
if (!regexec(&edit->re, buf, elementsof(match), match, 0) && !regsubexec(&edit->re, buf, elementsof(match), match))
223
{
224
sfprintf(sp, "%c%s", del, edit->re.re_sub->re_buf);
225
r++;
226
break;
227
}
228
}
229
else if (s = (*edit->num2strf)(cx, n, cx->disc))
230
{
231
sfprintf(sp, "%c%s", del, s);
232
r++;
233
break;
234
}
235
}
236
}
237
return r;
238
}
239
240
/*
241
* map number to string
242
*/
243
244
int
245
cxnum2str(Cx_t* cx, Cxformat_t* format, Cxunsigned_t num, char** p)
246
{
247
char* s;
248
int del;
249
250
if (format->map)
251
{
252
if ((del = format->delimiter) == -1)
253
del = '|';
254
if (!num2str(cx, format->map, cx->tp, num, del))
255
return -1;
256
}
257
else
258
sfprintf(cx->tp, "|%I*u", sizeof(num), num);
259
if (!(s = sfstruse(cx->tp)))
260
return -1;
261
if (p)
262
*p = s + 1;
263
return 0;
264
}
265
266
/*
267
* cxstr2num helper
268
*/
269
270
static int
271
str2num(Cx_t* cx, Cxmap_t* map, const char* str, Cxunsigned_t* num)
272
{
273
register Cxpart_t* part;
274
register Cxedit_t* edit;
275
regmatch_t match[10];
276
277
for (part = map->part; part; part = part->next)
278
for (edit = part->str2num; edit; edit = edit->next)
279
if (edit->str2numf)
280
{
281
if (!(*edit->str2numf)(cx, str, strlen(str), num, cx->disc))
282
return 1;
283
}
284
else if (!regexec(&edit->re, str, elementsof(match), match, 0) && !regsubexec(&edit->re, str, elementsof(match), match))
285
{
286
*num = strtoull(edit->re.re_sub->re_buf, NiL, 0);
287
return 1;
288
}
289
return 0;
290
}
291
292
/*
293
* map string to number
294
*/
295
296
int
297
cxstr2num(Cx_t* cx, Cxformat_t* format, const char* str, size_t siz, Cxunsigned_t* p)
298
{
299
register char* s;
300
register char* b;
301
int del;
302
Dt_t* dt;
303
Cxitem_t* item;
304
Cxunsigned_t n;
305
Cxunsigned_t m;
306
307
if (!format->map)
308
return -1;
309
del = format->delimiter;
310
dt = format->map->str2num;
311
n = 0;
312
sfwrite(cx->tp, str, siz);
313
if (!(s = sfstruse(cx->tp)))
314
return -1;
315
while (*s)
316
{
317
for (b = s; *s && *s != del && *s != '|' && *s != '+'; s++);
318
if (*s)
319
*s++ = 0;
320
if (item = (Cxitem_t*)dtmatch(dt, b))
321
n |= item->value;
322
else if (str2num(cx, format->map, b, &m))
323
n |= m;
324
else
325
return -1;
326
}
327
if (p)
328
*p = n;
329
return 0;
330
}
331
332
/*
333
* apply edit substitutions in edit to r
334
*/
335
336
int
337
cxsub(Cx_t* cx, Cxedit_t* edit, Cxoperand_t* r)
338
{
339
Cxtype_t* type;
340
regmatch_t match[10];
341
342
if (!cxisstring(r->type))
343
{
344
type = r->type;
345
if (cxcast(cx, r, NiL, cx->state->type_string, NiL, NiL))
346
return -1;
347
}
348
else
349
type = 0;
350
if (!regnexec(&edit->re, r->value.string.data, r->value.string.size, elementsof(match), match, 0) && !regsubexec(&edit->re, r->value.string.data, elementsof(match), match))
351
r->value.string.size = strlen(r->value.string.data = edit->re.re_sub->re_buf);
352
if (type && cxcast(cx, r, NiL, type, NiL, NiL))
353
return -1;
354
return 0;
355
}
356
357
/*
358
* apply edit substitutions in part to r
359
*/
360
361
int
362
cxsuball(Cx_t* cx, Cxpart_t* part, Cxoperand_t* r)
363
{
364
while (part)
365
{
366
if (part->edit && cxsub(cx, part->edit, r))
367
return -1;
368
part = part->next;
369
}
370
return 0;
371
}
372
373