Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/disc/sfkeyprintf.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2012 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
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
24
/*
25
* Glenn Fowler
26
* AT&T Research
27
*
28
* keyword printf support
29
*/
30
31
#include <ast.h>
32
#include <ccode.h>
33
#include <ctype.h>
34
#include <sfdisc.h>
35
#include <regex.h>
36
37
#define FMT_case 1
38
#define FMT_edit 2
39
40
typedef struct
41
{
42
Sffmt_t fmt;
43
void* handle;
44
Sf_key_lookup_t lookup;
45
Sf_key_convert_t convert;
46
Sfio_t* tmp[2];
47
regex_t red[2];
48
regex_t* re[2];
49
int invisible;
50
int level;
51
int version;
52
} Fmt_t;
53
54
typedef struct
55
{
56
char* next;
57
int delimiter;
58
int first;
59
} Field_t;
60
61
typedef union
62
{
63
char** p;
64
char* s;
65
Sflong_t q;
66
long l;
67
int i;
68
short h;
69
char c;
70
} Value_t;
71
72
#define initfield(f,s) ((f)->first = (f)->delimiter = *((f)->next = (s)))
73
74
static char*
75
getfield(register Field_t* f, int restore)
76
{
77
register char* s;
78
register int n;
79
register int c;
80
register int lp;
81
register int rp;
82
char* b;
83
84
if (!f->delimiter)
85
return 0;
86
s = f->next;
87
if (f->first)
88
f->first = 0;
89
else if (restore)
90
*s = f->delimiter;
91
b = ++s;
92
lp = rp = n = 0;
93
for (;;)
94
{
95
if (!(c = *s++))
96
{
97
f->delimiter = 0;
98
break;
99
}
100
else if (c == CC_esc || c == '\\')
101
{
102
if (*s)
103
s++;
104
}
105
else if (c == lp)
106
n++;
107
else if (c == rp)
108
n--;
109
else if (n <= 0)
110
{
111
if (c == '(' && restore)
112
{
113
lp = '(';
114
rp = ')';
115
n = 1;
116
}
117
else if (c == '[' && restore)
118
{
119
lp = '[';
120
rp = ']';
121
n = 1;
122
}
123
else if (c == f->delimiter)
124
{
125
*(f->next = --s) = 0;
126
break;
127
}
128
}
129
}
130
return b;
131
}
132
133
/*
134
* sfio %! extension function
135
*/
136
137
static int
138
getfmt(Sfio_t* sp, void* vp, Sffmt_t* dp)
139
{
140
register Fmt_t* fp = (Fmt_t*)dp;
141
Value_t* value = (Value_t*)vp;
142
register char* v;
143
char* t;
144
char* b;
145
char* a = 0;
146
char* s = 0;
147
Sflong_t n = 0;
148
int h = 0;
149
int i = 0;
150
int x = 0;
151
int d;
152
Field_t f;
153
regmatch_t match[10];
154
155
fp->level++;
156
if (fp->fmt.t_str && fp->fmt.n_str > 0 && (v = fmtbuf(fp->fmt.n_str + 1)))
157
{
158
memcpy(v, fp->fmt.t_str, fp->fmt.n_str);
159
v[fp->fmt.n_str] = 0;
160
b = v;
161
for (;;)
162
{
163
switch (*v++)
164
{
165
case 0:
166
break;
167
case '(':
168
h++;
169
continue;
170
case ')':
171
h--;
172
continue;
173
case '=':
174
case ':':
175
case ',':
176
if (h <= 0)
177
{
178
a = v;
179
break;
180
}
181
continue;
182
default:
183
continue;
184
}
185
if (i = *--v)
186
{
187
*v = 0;
188
if (i == ':' && fp->fmt.fmt == 's' && strlen(a) > 4 && !isalnum(*(a + 4)))
189
{
190
d = *(a + 4);
191
*(a + 4) = 0;
192
if (streq(a, "case"))
193
x = FMT_case;
194
else if (streq(a, "edit"))
195
x = FMT_edit;
196
*(a + 4) = d;
197
if (x)
198
a = 0;
199
}
200
}
201
break;
202
}
203
n = i;
204
t = fp->fmt.t_str;
205
fp->fmt.t_str = b;
206
h = (*fp->lookup)(fp->handle, &fp->fmt, a, &s, &n);
207
fp->fmt.t_str = t;
208
if (i)
209
*v++ = i;
210
}
211
else
212
{
213
h = (*fp->lookup)(fp->handle, &fp->fmt, a, &s, &n);
214
v = 0;
215
}
216
fp->fmt.flags |= SFFMT_VALUE;
217
switch (fp->fmt.fmt)
218
{
219
case 'c':
220
value->c = s ? *s : n;
221
break;
222
case 'd':
223
case 'i':
224
fp->fmt.size = sizeof(Sflong_t);
225
value->q = (Sflong_t)(s ? strtoll(s, NiL, 0) : n);
226
break;
227
case 'o':
228
case 'u':
229
case 'x':
230
fp->fmt.size = sizeof(Sflong_t);
231
value->q = s ? (Sflong_t)strtoull(s, NiL, 0) : n;
232
break;
233
case 'p':
234
if (s)
235
n = strtoll(s, NiL, 0);
236
value->p = pointerof(n);
237
break;
238
case 'q':
239
if (s)
240
{
241
fp->fmt.fmt = 's';
242
value->s = fmtquote(s, "$'", "'", strlen(s), 0);
243
}
244
else
245
{
246
fp->fmt.fmt = 'd';
247
value->q = n;
248
}
249
break;
250
case 's':
251
if (!s && (!h || !fp->tmp[1] && !(fp->tmp[1] = sfstropen()) || sfprintf(fp->tmp[1], "%I*d", sizeof(n), n) <= 0 || !(s = sfstruse(fp->tmp[1]))))
252
s = "";
253
if (x)
254
{
255
h = 0;
256
d = initfield(&f, v + 4);
257
switch (x)
258
{
259
case FMT_case:
260
while ((a = getfield(&f, 1)) && (v = getfield(&f, 0)))
261
{
262
if (strmatch(s, a))
263
{
264
Fmt_t fmt;
265
266
fmt = *fp;
267
fmt.fmt.form = v;
268
for (h = 0; h < elementsof(fmt.tmp); h++)
269
fmt.tmp[h] = 0;
270
if (!fp->tmp[0] && !(fp->tmp[0] = sfstropen()) || sfprintf(fp->tmp[0], "%!", &fmt) <= 0 || !(s = sfstruse(fp->tmp[0])))
271
s = "";
272
*(v - 1) = d;
273
if (f.delimiter)
274
*f.next = d;
275
for (h = 0; h < elementsof(fmt.tmp); h++)
276
if (fmt.tmp[h])
277
sfclose(fmt.tmp[h]);
278
h = 1;
279
break;
280
}
281
*(v - 1) = d;
282
}
283
break;
284
case FMT_edit:
285
for (x = 0; *f.next; x ^= 1)
286
{
287
if (fp->re[x])
288
regfree(fp->re[x]);
289
else
290
fp->re[x] = &fp->red[x];
291
if (regcomp(fp->re[x], f.next, REG_DELIMITED|REG_NULL))
292
break;
293
f.next += fp->re[x]->re_npat;
294
if (regsubcomp(fp->re[x], f.next, NiL, 0, 0))
295
break;
296
f.next += fp->re[x]->re_npat;
297
if (!regexec(fp->re[x], s, elementsof(match), match, 0) && !regsubexec(fp->re[x], s, elementsof(match), match))
298
{
299
s = fp->re[x]->re_sub->re_buf;
300
if (fp->re[x]->re_sub->re_flags & REG_SUB_STOP)
301
break;
302
}
303
}
304
h = 1;
305
break;
306
}
307
if (!h)
308
s = "";
309
}
310
value->s = s;
311
if (fp->level == 1)
312
while ((s = strchr(s, CC_esc)) && *(s + 1) == '[')
313
do fp->invisible++; while (*s && !islower(*s++));
314
break;
315
case 'Z':
316
fp->fmt.fmt = 'c';
317
value->c = 0;
318
break;
319
case '\n':
320
value->s = "\n";
321
break;
322
case '.':
323
value->i = n;
324
break;
325
default:
326
if ((!fp->convert || !(value->s = (*fp->convert)(fp->handle, &fp->fmt, a, s, n))) && (!fp->tmp[0] && !(fp->tmp[0] = sfstropen()) || sfprintf(fp->tmp[0], "%%%c", fp->fmt.fmt) <= 0 || !(value->s = sfstruse(fp->tmp[0]))))
327
value->s = "";
328
break;
329
}
330
fp->level--;
331
return 0;
332
}
333
334
/*
335
* this is the original interface
336
*/
337
338
#undef sfkeyprintf
339
340
int
341
sfkeyprintf(Sfio_t* sp, void* handle, const char* format, Sf_key_lookup_t lookup, Sf_key_convert_t convert)
342
{
343
register int i;
344
int r;
345
Fmt_t fmt;
346
347
memset(&fmt, 0, sizeof(fmt));
348
fmt.fmt.version = SFIO_VERSION;
349
fmt.fmt.form = (char*)format;
350
fmt.fmt.extf = getfmt;
351
fmt.handle = handle;
352
fmt.lookup = lookup;
353
fmt.convert = convert;
354
r = sfprintf(sp, "%!", &fmt) - fmt.invisible;
355
for (i = 0; i < elementsof(fmt.tmp); i++)
356
if (fmt.tmp[i])
357
sfclose(fmt.tmp[i]);
358
for (i = 0; i < elementsof(fmt.re); i++)
359
if (fmt.re[i])
360
regfree(fmt.re[i]);
361
return r;
362
}
363
364
#undef _AST_API_H
365
366
#include <ast_api.h>
367
368
/*
369
* Sffmt_t* callback args
370
*/
371
372
int
373
sfkeyprintf_20000308(Sfio_t* sp, void* handle, const char* format, Sf_key_lookup_t lookup, Sf_key_convert_t convert)
374
{
375
register int i;
376
int r;
377
Fmt_t fmt;
378
379
memset(&fmt, 0, sizeof(fmt));
380
fmt.version = 20030909;
381
fmt.fmt.version = SFIO_VERSION;
382
fmt.fmt.form = (char*)format;
383
fmt.fmt.extf = getfmt;
384
fmt.handle = handle;
385
fmt.lookup = lookup;
386
fmt.convert = convert;
387
r = sfprintf(sp, "%!", &fmt) - fmt.invisible;
388
for (i = 0; i < elementsof(fmt.tmp); i++)
389
if (fmt.tmp[i])
390
sfclose(fmt.tmp[i]);
391
return r;
392
}
393
394