Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libvcodex/vcmethod.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-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
* Phong Vo <[email protected]> *
18
* *
19
***********************************************************************/
20
#include "vchdr.h"
21
22
/* Managing lists of transforms.
23
**
24
** Written by Kiem-Phong Vo ([email protected])
25
*/
26
27
#if _PACKAGE_ast
28
#include <dlldefs.h>
29
#include <ccode.h>
30
#endif
31
32
/* reconstitute declarations for the default public methods */
33
34
_BEGIN_EXTERNS_
35
36
#ifdef __STDC__
37
#define VCMETHOD(m) extern Vcmethod_t _##m;
38
#else
39
#define VCMETHOD(m) extern Vcmethod_t _/**/m;
40
#endif
41
#include <vcmethods.h>
42
43
_END_EXTERNS_
44
45
/* reconstitute the list of pointers to the default public methods */
46
47
static Vcmethod_t* _Vcmethods[] =
48
{
49
#ifdef __STDC__
50
#define VCMETHOD(m) &_##m,
51
#else
52
#define VCMETHOD(m) &_/**/m,
53
#endif
54
#include <vcmethods.h>
55
};
56
57
typedef struct _vcmtlist_s Vcmtlist_t;
58
struct _vcmtlist_s
59
{ Vcmtlist_t* next; /* link list */
60
Vcmethod_t** list; /* list of methods */
61
int size; /* list size */
62
};
63
64
static Vcmtlist_t* _Vcmtlist;
65
static int _Doneinit;
66
#define VCMTINIT() (_Doneinit ? 0 : (_Doneinit = 1, vcmtinit()) )
67
68
static int vcmtinit _ARG_((void));
69
70
/* add a list of methods - perhaps dynamically loaded */
71
#if __STD_C
72
int vcaddmeth(Vcmethod_t** list, ssize_t size)
73
#else
74
int vcaddmeth(list, size)
75
Vcmethod_t** list; /* methods to be added */
76
ssize_t size; /* number of them */
77
#endif
78
{
79
Vcmtlist_t *mtl;
80
Vcmethod_t **lst;
81
82
if(VCMTINIT() < 0) /* initialize with our own methods first */
83
return -1;
84
85
if(!list || size < 0)
86
return 0;
87
88
if(!(mtl = (Vcmtlist_t*)malloc(sizeof(Vcmtlist_t) + (size ? 0 : sizeof(Vcmethod_t**)))) )
89
return -1;
90
91
if(_Vcmtlist)
92
{ mtl->next = _Vcmtlist->next;
93
_Vcmtlist->next = mtl;
94
}
95
else
96
{ mtl->next = NIL(Vcmtlist_t*);
97
_Vcmtlist = mtl;
98
}
99
if(!size)
100
{
101
lst = (Vcmethod_t**)(mtl + 1);
102
*lst = (Vcmethod_t*)list;
103
list = lst;
104
size = 1;
105
}
106
107
mtl->list = list;
108
mtl->size = size;
109
110
return 0;
111
}
112
113
#if _PACKAGE_ast
114
115
typedef Vcmethod_t* (*Vclib_f) _ARG_((const char*));
116
117
#if __STD_C
118
static Vcmethod_t* plugin(Void_t* dll, const char* path)
119
#else
120
static Vcmethod_t* plugin(dll, path)
121
Void_t* dll;
122
char* path;
123
#endif
124
{
125
Vcmethod_t* meth;
126
Vclib_f libf;
127
128
if ((libf = (Vclib_f)dlllook(dll, VC_LIB)) && (meth = (*libf)(path)))
129
{
130
vcaddmeth((Vcmethod_t**)meth, 0);
131
return meth;
132
}
133
dlclose(dll);
134
return 0;
135
}
136
137
#endif
138
139
/* return a method matching an id */
140
#if __STD_C
141
static int vcmtinit(void)
142
#else
143
static int vcmtinit()
144
#endif
145
{
146
#if _PACKAGE_ast
147
Dllscan_t *dls;
148
Dllent_t *dle;
149
Void_t *dll;
150
#endif
151
152
vcaddmeth(_Vcmethods, sizeof(_Vcmethods)/sizeof(_Vcmethods[0]));
153
154
#if _PACKAGE_ast
155
if (dls = dllsopen(VC_ID, NiL, NiL))
156
{ while (dle = dllsread(dls))
157
if (dll = dlopen(dle->path, RTLD_LAZY))
158
plugin(dll, dle->path);
159
else errorf("dll", NiL, 1, "%s: dlopen failed: %s", dle->path, dlerror());
160
dllsclose(dls);
161
}
162
#endif
163
164
return 0;
165
}
166
167
/* return a method matching an id */
168
#if __STD_C
169
Vcmethod_t* vcgetmeth(char* name, int portable)
170
#else
171
Vcmethod_t* vcgetmeth(name, portable)
172
char* name;
173
int portable; /* name is in portable format */
174
#endif
175
{
176
Vcmtlist_t *mtl;
177
char *port, *ident, buf1[1024], buf2[1024];
178
int i;
179
#if _PACKAGE_ast
180
Void_t *dll;
181
unsigned char *map;
182
#endif
183
184
if(VCMTINIT() < 0) /* initialize with our own methods first */
185
return NIL(Vcmethod_t*);
186
187
if(!name)
188
return NIL(Vcmethod_t*);
189
if(!(port = portable ? name : vcstrcode(name, buf1, sizeof(buf1))))
190
return NIL(Vcmethod_t*);
191
192
for(mtl = _Vcmtlist; mtl; mtl = mtl->next)
193
{ for(i = 0; i < mtl->size; ++i)
194
{ if(!(ident = vcgetident(mtl->list[i], buf2, sizeof(buf2))) )
195
return NIL(Vcmethod_t*);
196
if(strcmp(port, ident) == 0)
197
return mtl->list[i];
198
}
199
}
200
201
#if _PACKAGE_ast
202
if(portable && (map = ccmap(CC_ASCII, CC_NATIVE)))
203
{ for (i = 0; i < sizeof(buf2) - 1; i++)
204
buf2[i] = map[((unsigned char*)name)[i]];
205
name = buf2;
206
}
207
if (dll = dllplugin(VC_ID, name, NIL(char*), VCODEX_PLUGIN_VERSION, NiL, RTLD_LAZY, buf1, sizeof(buf1)))
208
return plugin(dll, buf1);
209
#endif
210
211
return NIL(Vcmethod_t*);
212
}
213
214
/* return the method after 'meth' in the union of all methods */
215
#if __STD_C
216
int vcwalkmeth(Vcwalk_f walkf, Void_t* disc)
217
#else
218
int vcwalkmeth(walkf, disc)
219
Vcwalk_f walkf;
220
Void_t* disc;
221
#endif
222
{
223
Vcmtlist_t *mtl;
224
int i, rv;
225
226
if(VCMTINIT() < 0) /* initialize with our own methods first */
227
return -1;
228
229
if(!walkf)
230
return -1;
231
232
for(mtl = _Vcmtlist; mtl; mtl = mtl->next)
233
{ for(i = 0; i < mtl->size; ++i)
234
{ rv = (*walkf)((Void_t*)mtl->list[i],
235
mtl->list[i]->name, mtl->list[i]->desc, disc);
236
if(rv < 0)
237
return rv;
238
}
239
}
240
241
return 0;
242
}
243
244
245
/* set data for a particular transformation context for the method */
246
#if __STD_C
247
int vcsetmtarg(Vcodex_t* vc, char* name, Void_t* val, int type)
248
#else
249
int vcsetmtarg(vc, name, val, type)
250
Vcodex_t* vc;
251
char* name; /* name of the parameter to set */
252
Void_t* val; /* data to set the parameter */
253
int type; /* different coding types: */
254
/* 0: null-terminated string */
255
/* 1: 'char' in C-style */
256
/* >0: 'int' in decimal */
257
/* <0: no value */
258
#endif
259
{
260
Vcchar_t data[1024], *v;
261
int k;
262
263
if(!vc || !vc->meth)
264
return -1;
265
if(!vc->meth->eventf)
266
return 0;
267
268
#define MAXNAME 128 /* max length for name */
269
for(k = 0; k < sizeof(data); ++k)
270
{ if(!isalnum(name[k]) )
271
break;
272
data[k] = name[k];
273
}
274
if(name[k] || k > MAXNAME)
275
return -1;
276
277
if(type == 0) /* string */
278
{ if((v = (Vcchar_t*)val) != NIL(Vcchar_t*) )
279
{ data[k++] = '=';
280
while(k < sizeof(data)-1)
281
{ if(*v == 0)
282
break;
283
data[k++] = *v++;
284
}
285
}
286
}
287
else if(type == 1) /* char, code in C-style octals */
288
{ data[k++] = '=';
289
290
type = (unsigned char)TYPECAST(int,val);
291
data[k++] = '\\';
292
if(type >= 64)
293
{ data[k++] = '0' + type/64; type %= 64;
294
goto do_8;
295
}
296
else if(type >= 8)
297
{ data[k++] = '0';
298
do_8: data[k++] = '0' + type/8; type %= 8;
299
goto do_0;
300
}
301
else
302
{ data[k++] = '0';
303
data[k++] = '0';
304
do_0: data[k++] = '0' + type;
305
}
306
}
307
else if(type > 0) /* int, code in base 10 */
308
{ data[k++] = '=';
309
310
if((type = TYPECAST(int,val)) < 0)
311
type = -type;
312
for(v = data + sizeof(data); ; )
313
{ *--v = '0' + type%10; type /= 10;
314
if(type == 0)
315
break;
316
}
317
if(TYPECAST(int,val) < 0)
318
*--v = '-';
319
320
while(v < &data[sizeof(data)] )
321
data[k++] = *v++;
322
}
323
324
data[k] = 0;
325
326
return (*vc->meth->eventf)(vc, VC_SETMTARG, (Void_t*)data);
327
}
328
329
/* from a string specification, find an argument and its value if any */
330
#if __STD_C
331
char* vcgetmtarg(char* data, char* val, ssize_t vlsz, Vcmtarg_t* args, Vcmtarg_t** arg)
332
#else
333
char* vcgetmtarg(data, val, vlsz, args, arg)
334
char* data; /* data to be parsed, null-terminated */
335
char* val; /* buffer to return the value */
336
ssize_t vlsz; /* length of value buffer */
337
Vcmtarg_t* args; /* list of matchable arguments */
338
Vcmtarg_t** arg; /* to return the matched argument */
339
#endif
340
{
341
Vcmtarg_t *a;
342
ssize_t k;
343
int csep;
344
char name[1024];
345
static char *nullstr = "";
346
347
if(arg)
348
*arg = NIL(Vcmtarg_t*);
349
350
if(!data)
351
data = nullstr;
352
353
if(!val)
354
vlsz = 0;
355
356
csep = VC_ARGSEP; /* use argument separator */
357
358
if(!args) /* partitioning by separator, no internal character processing */
359
return vcsubstring(data, csep, val, vlsz, 0);
360
361
/* a real name must be alphanumeric */
362
for(; *data; ++data )
363
if(isalnum(*data))
364
break;
365
366
/* extract the name */
367
for(k = 0; *data && k < sizeof(name); ++data, ++k)
368
{ if(!isalnum(*data))
369
break;
370
name[k] = *data;
371
}
372
if(k == sizeof(name))
373
k = 0;
374
name[k] = 0;
375
376
while(isblank(*data))
377
data += 1;
378
if(*data == '=') /* name=value syntax, get value with C syntax characters */
379
{ for(data += 1; isblank(*data); ++data)
380
;
381
data = vcsubstring(data, csep, val, vlsz, 1);
382
}
383
384
while(isblank(*data) || *data == csep) /* skip separators */
385
data += 1;
386
387
/* find the matching argument */
388
for(a = args; a->name; ++a)
389
if(strcmp(a->name, name) == 0)
390
break;
391
if(arg)
392
*arg = a;
393
394
/* next name=value, if any */
395
return (data == nullstr || *data == 0) ? NIL(char*) : data;
396
}
397
398
/* Get a substring from a larger string. There are two cases:
399
** type == 0: Only search for the separator csep. In this case,
400
** we still allow escape via backslash or grouping with braces
401
** and brackets but we do not process such characters.
402
** type == 1: In this case, brackets and C-notation for
403
** characters are processed.
404
** Return the left-over data.
405
*/
406
#if __STD_C
407
char* vcsubstring(char* data, int csep, char* val, ssize_t vlsz, int type)
408
#else
409
char* vcsubstring(data, csep, val, vlsz, type)
410
char* data; /* data to extract from */
411
int csep; /* separator character */
412
char* val; /* space for substring */
413
ssize_t vlsz; /* size of val in bytes */
414
int type; /* see above */
415
#endif
416
{
417
int c, k, endbrace, asep;
418
419
if(!val)
420
vlsz = 0;
421
asep = csep == VC_METHSEP ? '^' : 0;
422
423
for(endbrace = -1;;)
424
{
425
if((c = *data++) == 0 || c == csep || c == asep)
426
{ end_string:
427
if(c == 0) /* point to the zero-byte */
428
data -= 1;
429
if(vlsz > 0)
430
{ *val = 0; vlsz -= 1; }
431
return data;
432
}
433
434
if(c == '[' )
435
{ endbrace = ']';
436
437
if(type == 0) /* grab group as is */
438
{ do
439
{ if(vlsz > 1)
440
{ *val++ = c; vlsz -= 1; }
441
if(c == endbrace)
442
break;
443
if(c == '\\' && *data == endbrace)
444
{ c = *data++;
445
if(vlsz > 1)
446
{ *val++ = c; vlsz -= 1; }
447
}
448
} while((c = *data++) != 0 && c != endbrace);
449
450
if(c == 0)
451
goto end_string;
452
if(vlsz > 1)
453
{ *val++ = c; vlsz -= 1; }
454
455
endbrace = -1;
456
continue;
457
}
458
459
if((c = *data++) == 0) /* skip forward */
460
goto end_string;
461
}
462
463
if(c == endbrace)
464
{ endbrace = -1;
465
continue;
466
}
467
468
if(c == '\\')
469
{ if(type == 0) /* no processing, just keeping next letter */
470
{ if(vlsz > 1)
471
{ *val++ = c; vlsz -= 1; }
472
if((c = *data++) == 0)
473
goto end_string;
474
if(vlsz > 1)
475
{ *val++ = c; vlsz -= 1; }
476
continue;
477
}
478
479
if((c = *data++) == 0)
480
goto end_string; /* unexpected eos */
481
else if(c >= '0' && c <= '7') /* \ddd notation */
482
{ for(c -= '0', k = 0; k < 2; ++k)
483
{ if(*data < '0' || *data > '7')
484
break;
485
c = c*8 + (*data++ - '0');
486
}
487
}
488
else switch(c)
489
{ case 't' : c = '\t'; break;
490
case 'b' : c = '\b'; break;
491
case 'r' : c = '\r'; break;
492
case 'n' : c = '\n'; break;
493
}
494
}
495
496
if(vlsz > 1)
497
{ *val++ = c; vlsz -= 1; }
498
}
499
}
500
501
/* get the identification string of a method */
502
#if __STD_C
503
char* vcgetident(Vcmethod_t* meth, char* buf, ssize_t n)
504
#else
505
char* vcgetident(meth, buf, n)
506
Vcmethod_t* meth; /* method to get ID from */
507
char* buf; /* buffer to store ID if needed */
508
sszie_t n; /* size of buffer */
509
#endif
510
{
511
char *ident = NIL(char*);
512
513
if(!meth) /* bad invocation */
514
return NIL(char*);
515
516
#ifdef VC_GETIDENT
517
if(meth->eventf && /* ask the method for its identification string */
518
(*meth->eventf)(NIL(Vcodex_t*), VC_GETIDENT, (Void_t*)(&ident)) < 0 )
519
return NIL(char*);
520
#endif
521
522
if(!ident && meth->name) /* construct ID from name */
523
ident = vcstrcode(meth->name, buf, n);
524
525
return ident;
526
}
527
528