Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/kshlib/dss/dss.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-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
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* dss type library
23
*
24
* David Korn
25
* AT&T Labs
26
*
27
*/
28
29
#include <shell.h>
30
#include <dsslib.h>
31
32
#ifndef SH_DICT
33
# define SH_DICT "libshell"
34
#endif
35
36
#define vnode(np) ((Cxvariable_t*)((np)->nvname))
37
38
static int match(int, char *[], Shbltin_t *);
39
static Namval_t *create_dss(Namval_t*,const char*,int,Namfun_t*);
40
static Namval_t *create_type(Namval_t*,const char*,int,Namfun_t*);
41
42
static const Namdisc_t parent_disc;
43
static Dt_t *typedict;
44
static Dssdisc_t Dssdisc;
45
static size_t buflen;
46
47
struct Optdisc
48
{
49
Dssoptdisc_t dss;
50
Namval_t *np;
51
};
52
53
typedef struct Namtype Namtype_t;
54
typedef struct Namchld
55
{
56
Namfun_t fun;
57
Namtype_t *ptype;
58
Namtype_t *ttype;
59
} Namchld_t;
60
61
struct type
62
{
63
Namfun_t fun;
64
Cxtype_t *type;
65
Cx_t *cx;
66
Namval_t *bltins[1];
67
Namfun_t *pfun;
68
Namval_t details;
69
};
70
71
struct Namtype
72
{
73
Namfun_t fun;
74
Shell_t *sh;
75
Namval_t *np;
76
Namval_t *parent;
77
char *nodes;
78
char *data;
79
Namchld_t childfun;
80
int numnodes;
81
char **names;
82
};
83
84
struct dsstype
85
{
86
Namfun_t fun;
87
Shell_t *sh;
88
char **names;
89
int nnames;
90
};
91
92
struct dssfile
93
{
94
Sfdisc_t disc;
95
Dssfile_t *fp;
96
Dssrecord_t *rp;
97
Namval_t *np;
98
Namval_t *mp;
99
char *dp;
100
};
101
102
struct query
103
{
104
struct query *next;
105
Cxexpr_t expr;
106
Cxquery_t *query;
107
int index;
108
};
109
110
111
struct parent
112
{
113
Namtype_t hdr;
114
Dt_t *dict;
115
Namfun_t parentfun;
116
size_t namelen;
117
char *name;
118
Dssdisc_t *disc;
119
Cxstate_t *state;
120
Cx_t *cx;
121
Dss_t *dss;
122
Cxtype_t *type;
123
struct dssfile *sp;
124
struct query *qp;
125
};
126
127
128
/*
129
* the following function is added as a builtin for each query
130
* function that a variable can have
131
*/
132
static int query(int argc, char *argv[], Shbltin_t *bp)
133
{
134
struct parent *dp = (struct parent*)nv_hasdisc(bp->vnode,&parent_disc);
135
Dss_t *dss = dp->dss;
136
struct query *pp = dp->qp;
137
Cxquery_t *qp = pp?pp->query:0;
138
Cx_t *cx = dss->cx;
139
Dssrecord_t *data;
140
int n = (char**)bp->ptr-dp->hdr.names;
141
char *savedata;
142
size_t savesize;
143
while(pp && pp->index!=n)
144
pp = pp->next;
145
if(!pp || argv[1])
146
{
147
if(!pp)
148
{
149
if(!(qp = cxquery(cx, dp->hdr.names[n], cx->disc)))
150
errormsg(SH_DICT,ERROR_exit(1),"%s: load method %s",argv[0]);
151
pp = newof(NiL,struct query,1,0);
152
pp->index = n;
153
pp->next = dp->qp;
154
dp->qp = pp;
155
pp->query = qp;
156
memset((void*)&pp->expr,0,sizeof(pp->expr));
157
}
158
if(pp->expr.query && qp->end)
159
(*qp->end)(cx,&pp->expr,(void*)0,cx->disc);
160
if(argc==2 && strcmp(argv[1],"end")==0)
161
{
162
struct query *xp, **ppp = &dp->qp;
163
while((xp= *ppp) && xp != pp)
164
ppp = &xp->next;
165
if(xp)
166
*ppp = pp->next;
167
free((void*)pp);
168
return(0);
169
}
170
pp->expr.query = pp->query;
171
pp->expr.op = sfstdout;
172
if(qp->beg)
173
{
174
if((*qp->beg)(cx,&pp->expr,(void*)argv,cx->disc))
175
{
176
pp->expr.query = 0;
177
return(2);
178
}
179
}
180
return(0);
181
}
182
if(!bp->vnode->nvalue || !dp->sp || !(data = dp->sp->rp))
183
return(1);
184
savedata = data->data;
185
savesize = data->size;
186
data->data = bp->vnode->nvalue;
187
data->size = nv_size(bp->vnode);
188
if(qp->sel)
189
{
190
if((n=(*qp->sel)(cx,&pp->expr,data,cx->disc))<=0)
191
return(n<0?2:1);
192
}
193
if(qp->act)
194
return(-(*qp->act)(cx, &pp->expr,data,cx->disc));
195
data->data = savedata;
196
data->size = savesize;
197
return(0);
198
}
199
200
static char *getbuf(size_t len)
201
{
202
static char *buf;
203
if(buflen < len)
204
{
205
if(buflen==0)
206
buf = (char*)malloc(len);
207
else
208
buf = (char*)realloc(buf,len);
209
buflen = len;
210
}
211
return(buf);
212
}
213
214
static void check_numeric(Namval_t *np, Cxtype_t *tp, Cxstate_t *sp)
215
{
216
if(cxisnumber(tp))
217
{
218
nv_onattr(np,NV_LDOUBLE|NV_EXPNOTE);
219
nv_setsize(np,10);
220
}
221
else if(cxisbuffer(tp))
222
nv_onattr(np,NV_BINARY);
223
}
224
225
static Namval_t *typenode(const char *name, int flag)
226
{
227
int offset = stktell(stkstd);
228
Namval_t *mp;
229
sfputc(stkstd,0);
230
sfprintf(stkstd,"dss.%s",name);
231
sfputc(stkstd,0);
232
mp = nv_search(stkptr(stkstd,offset+1),typedict,flag);
233
stkseek(stkstd,offset);
234
#if 0
235
if(flag&NV_ADD)
236
{
237
/* create reference variable name to NV_CLASS.dss.name */
238
Shell_t *shp = sh_getinterp();
239
Namval_t *rp;
240
sfputc(stkstd,0);
241
sfprintf(stkstd,NV_CLASS".dss.%s",name);
242
sfputc(stkstd,0);
243
rp = nv_open(name, shp->var_tree, NV_IDENT);
244
nv_unset(rp);
245
nv_putval(rp,stkptr(stkstd,offset+1),0);
246
nv_setref(rp,shp->var_tree,NV_VARNAME|NV_NOREF);
247
stkseek(stkstd,offset);
248
}
249
#endif
250
return(mp);
251
}
252
253
Cxvalue_t *get_child_common(Namval_t *np, Namfun_t *fp, Cxoperand_t *op)
254
{
255
Namchld_t *cp = (Namchld_t*)fp;
256
struct parent *pp = (struct parent*)cp->ptype;
257
Cxtype_t *tp = pp->type;
258
Cxvariable_t *vp = vnode(np);
259
Cxinstruction_t in;
260
if(nv_isattr(pp->hdr.np,NV_INTEGER))
261
{
262
in.data.variable = vp;
263
op->type = vp->type;
264
op->value.number = nv_getnum(pp->hdr.np);
265
if((*tp->member->getf)(pp->cx,&in,op,NiL,NiL,NiL,pp->cx->disc)==0)
266
return(&op->value);
267
}
268
return(0);
269
}
270
271
static char* get_child(register Namval_t* np, Namfun_t *fp)
272
{
273
Cxvariable_t *vp = vnode(np);
274
Cxoperand_t op;
275
Cxvalue_t *val;
276
if(val = get_child_common(np, fp, &op))
277
{
278
if(cxisnumber(vp->type))
279
{
280
long l = nv_size(np)+8;
281
char *sp = getbuf(l);
282
sfsprintf(sp,l,"%.*Lg\0",nv_size(np),val->number);
283
return(sp);
284
}
285
return(val->string.data);
286
}
287
return(0);
288
}
289
290
static char* get_mchild(register Namval_t* np, Namfun_t *fp)
291
{
292
Cxoperand_t ret;
293
Namchld_t *pp = (Namchld_t*)fp;
294
struct parent *dp = (struct parent*)pp->ptype;
295
Cxvariable_t *vp = vnode(np);
296
char *savedata=0, *value;
297
size_t savesize;
298
Dssrecord_t *rp, rec;
299
if(!dp->hdr.np->nvalue)
300
return(0);
301
if(dp->sp && dp->sp->rp)
302
{
303
rp = dp->sp->rp;
304
savedata = rp->data;
305
savesize = rp->size;
306
}
307
else
308
memset(rp= &rec, 0, sizeof(rec));
309
rp->data = dp->hdr.np->nvalue;
310
rp->size = nv_size(dp->hdr.np);
311
if(nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
312
{
313
if(cxcast(dp->cx,&ret,vp,dp->state->type_buffer,rp,(char*)0)==0)
314
{
315
nv_setsize(np,ret.value.buffer.size);
316
value = ret.value.buffer.data;
317
}
318
}
319
else if(cxcast(dp->cx,&ret,vp,dp->state->type_string,rp,(char*)0)==0)
320
value = ret.value.string.data;
321
else
322
value = nv_name(np);
323
if(savedata)
324
{
325
rp->data = savedata;
326
rp->size = savesize;
327
}
328
return(value);
329
}
330
331
static Sfdouble_t nget_child(register Namval_t* np, Namfun_t *fp)
332
{
333
Cxvariable_t *vp = vnode(np);
334
Cxoperand_t op;
335
Cxvalue_t *val;
336
op.type = 0;
337
if(val = get_child_common(np, fp, &op))
338
{
339
Sfdouble_t ld;
340
if(cxisnumber(vp->type))
341
return(val->number);
342
else
343
{
344
ld = sh_strnum(val->string.data, (char**)0, 1);
345
return(ld);
346
}
347
}
348
return(0);
349
}
350
351
static Sfdouble_t nget_mchild(register Namval_t* np, Namfun_t *fp)
352
{
353
Cxoperand_t ret;
354
Namchld_t *pp = (Namchld_t*)fp;
355
struct parent *dp = (struct parent*)pp->ptype;
356
Cxvariable_t *vp = vnode(np);
357
#if 1
358
if(cxcast(dp->cx,&ret,vp,dp->state->type_number,dp->hdr.np->nvalue,(char*)0)==0)
359
#else
360
if(cxcast(dp->cx,&ret,vp,dp->state->type_number,dp->hdr.data,(char*)0)==0)
361
#endif
362
return(ret.value.number);
363
return(0.0);
364
}
365
366
static void put_child(Namval_t* np, const char* val, int flags, Namfun_t* fp)
367
{
368
Namchld_t *cp = (Namchld_t*)fp;
369
struct parent *pp = (struct parent*)cp->ptype;
370
Cxtype_t *tp = pp->type;
371
Cxvariable_t *vp = vnode(np);
372
Cxinstruction_t in;
373
Cxoperand_t ret,op;
374
in.data.variable = vp;
375
nv_onattr(np,NV_NODISC);
376
nv_putval(np,val,flags);
377
nv_offattr(np,NV_NODISC);
378
ret.type = vp->type;
379
ret.value.number = nv_getnum(pp->hdr.np);
380
op.value.number = nv_getn(np,fp);
381
if((*tp->member->setf)(pp->cx,&in, &ret,&op,NiL,NiL,pp->cx->disc)==0)
382
nv_putval(pp->hdr.np,(char*)&ret.value.number,NV_INTEGER|NV_DOUBLE|NV_LONG|NV_NODISC);
383
}
384
385
static void put_mchild(Namval_t* np, const char* val, int flag, Namfun_t* fp)
386
{
387
}
388
389
static char *name_child(Namval_t *np, Namfun_t *fp)
390
{
391
Namchld_t *pp = (Namchld_t*)fp;
392
struct parent *dp = (struct parent*)pp->ptype;
393
const char *name = vnode(np)->name;
394
char *cp;
395
size_t l,len;
396
cp = nv_name(dp->hdr.np);
397
len = (l=strlen(cp)) + strlen(name)+2;
398
if(dp->namelen < len)
399
{
400
if(dp->namelen==0)
401
dp->name = (char*)malloc(len);
402
else
403
dp->name = (char*)realloc(dp->name,len);
404
dp->namelen = len;
405
}
406
memcpy(dp->name,cp,l);
407
dp->name[l++] = '.';
408
strcpy(&dp->name[l],name);
409
return(dp->name);
410
}
411
412
static Namval_t *type_child(register Namval_t* np, Namfun_t *fp)
413
{
414
struct parent *pp = (struct parent*)((Namchld_t*)fp)->ptype;
415
Cxstate_t *sp = pp->state;
416
Cxvariable_t *vp = vnode(np);
417
if(!pp->dss || vp->type==sp->type_number || vp->type==sp->type_string)
418
return(0);
419
return(typenode(vp->type->name,0));
420
}
421
422
/* for child variables of compound variables */
423
static const Namdisc_t child_disc =
424
{
425
sizeof(Namchld_t),
426
put_child,
427
get_child,
428
nget_child,
429
0,
430
0,
431
0,
432
name_child,
433
0,
434
type_child
435
};
436
437
/* for child variables of methods */
438
static const Namdisc_t mchild_disc =
439
{
440
sizeof(Namchld_t),
441
put_mchild,
442
get_mchild,
443
nget_mchild,
444
0,
445
0,
446
0,
447
name_child,
448
0,
449
type_child
450
};
451
452
static const Namdisc_t type_disc;
453
454
static Namval_t *node(Cxvariable_t *vp,struct parent *dp)
455
{
456
Namval_t *mp, *np=0;
457
Namfun_t *fp, *nfp=0;
458
if(!dp->hdr.nodes)
459
{
460
struct type *tp;
461
struct parent *pp;
462
if(!(dp->hdr.nodes = (char*)calloc(dp->hdr.numnodes,NV_MINSZ)))
463
return(0);
464
np = nv_namptr(dp->hdr.nodes,0);
465
np->nvname = NV_DATA;
466
nv_onattr(np,NV_MINIMAL);
467
tp = (struct type*)nv_hasdisc(mp=dp->hdr.fun.type,&type_disc);
468
if(tp)
469
pp = (struct parent*)tp->fun.next;
470
else
471
pp = (struct parent*)nv_hasdisc(mp,&parent_disc);
472
if(mp!=dp->hdr.np && pp && pp->hdr.fun.disc==&parent_disc && pp->hdr.nodes)
473
mp = nv_namptr(pp->hdr.nodes,0);
474
else if(tp)
475
mp = &tp->details;
476
else
477
mp = 0;
478
if(mp && !nv_isnull(mp))
479
nv_clone(mp,np,0);
480
}
481
if(!vp)
482
return(np?np:nv_namptr(dp->hdr.nodes,0));
483
np = nv_namptr(dp->hdr.nodes,vp->header.index+1);
484
if(!np->nvname)
485
{
486
nv_disc(np,&dp->hdr.childfun.fun,NV_FIRST);
487
nv_onattr(np,NV_MINIMAL);
488
check_numeric(np, vp->type, dp->state);
489
if(!dp->dss && vp->type->base && (mp=typenode(vp->type->name,0)) && (fp = nv_hasdisc(mp, &type_disc)))
490
{
491
int size = fp->dsize;
492
if(size==0 || (!fp->disc || (size=fp->disc->dsize)==0))
493
size = sizeof(Namfun_t);
494
if(fp->disc && fp->disc->clonef)
495
nfp = (*fp->disc->clonef)(np,mp,0,fp);
496
else if(nfp = malloc(size))
497
{
498
memcpy((void*)nfp,(void*)fp,size);
499
nfp->nofree &= ~1;
500
}
501
if(nfp)
502
nv_disc(np,nfp,NV_FIRST);
503
if(((struct type*)fp)->details.nvalue)
504
nv_setvtree(np);
505
}
506
np->nvname = (char*)vp;
507
}
508
return(np);
509
}
510
511
static Namfun_t *clone_parent(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
512
{
513
Namtype_t *dp;
514
struct type *tp;
515
size_t size = fp->dsize;
516
if(size==0 && (!fp->disc || (size=fp->disc->dsize)==0))
517
size = sizeof(Namfun_t);
518
dp = (Namtype_t*)calloc(1,size);
519
memcpy((void*)dp,(void*)fp,size);
520
dp->childfun.ptype = dp;
521
dp->childfun.ttype = (Namtype_t*)fp;
522
if(tp=(struct type*)nv_hasdisc(mp,&type_disc))
523
tp->pfun = &dp->fun;
524
dp->data = 0;
525
dp->np = mp;
526
dp->nodes = 0;
527
dp->parent = nv_lastdict();
528
((struct parent*)dp)->namelen = 0;
529
return(&dp->fun);
530
}
531
532
static void pushtype(Namval_t *np, Cxtype_t *tt, Namfun_t *fp)
533
{
534
Namval_t *mp;
535
for(; tt->base; tt = tt->base)
536
{
537
if(tt->member)
538
{
539
Namfun_t *nfp;
540
mp = typenode(tt->name,0);
541
if(!fp->next && np!=fp->type)
542
{
543
fp = nv_disc(np, fp, NV_CLONE);
544
}
545
nfp = nv_hasdisc(mp, &parent_disc);
546
nfp = clone_parent(mp,np,0,nfp);
547
nfp->type = fp->type;
548
((struct type*)fp)->pfun = nfp;
549
if(mp=node((Cxvariable_t*)0,(struct parent*)nfp))
550
nv_clone( &((struct type*)fp)->details,mp,NV_MOVE);
551
nfp->next = fp->next;
552
fp->next = nfp;
553
}
554
}
555
}
556
557
static Namval_t *create_parent(Namval_t *np,const char *name,int flag,Namfun_t *fp)
558
{
559
struct parent *dp = (struct parent*)fp;
560
Dt_t *dict = dp->dict;
561
Cxvariable_t *vp;
562
char *last=(char*)name;
563
int c;
564
if(!name)
565
return(dp->hdr.np);
566
while((c=*last) && c!='.' && c!='=' && c!='[' && c!='+')
567
last++;
568
if(c)
569
*last = 0;
570
if(strcmp(name,NV_DATA)==0)
571
{
572
np = node((Cxvariable_t*)0,dp);
573
if(c)
574
*last = c;
575
fp->last = last;
576
return(np);
577
}
578
vp = (Cxvariable_t*)dtmatch(dict,name);
579
if(c)
580
*last = c;
581
if(vp)
582
{
583
np = node(vp,dp);
584
fp->last = last;
585
if(c=='.')
586
{
587
Namfun_t *rp = np->nvfun;
588
if(rp == &dp->hdr.childfun.fun)
589
{
590
fp = nv_disc(np,np->nvfun, NV_CLONE);
591
pushtype(np, vp->type, fp);
592
}
593
for(;rp && !(rp->disc && rp->disc->createf);rp = rp->next);
594
if(rp)
595
fp = rp;
596
np = (*fp->disc->createf)(np,last+1, flag, fp);
597
dp->hdr.fun.last = fp->last;
598
}
599
return(np);
600
}
601
return(0);
602
}
603
604
static void dss_unset(Namval_t *np, struct parent *dp)
605
{
606
if(dp->namelen)
607
free((void*)dp->name);
608
if(!dp->hdr.np)
609
{
610
if(dp->dss)
611
dssclose(dp->dss);
612
else
613
cxclose(dp->cx);
614
}
615
nv_disc(np,&dp->hdr.fun,NV_POP);
616
if(dp->hdr.nodes)
617
free((void*)dp->hdr.nodes);
618
if(!dp->hdr.fun.nofree&1)
619
free((void*)dp);
620
}
621
622
static void put_parent(Namval_t* np, const char* val, int flag, Namfun_t* fp)
623
{
624
struct parent *pp = (struct parent*)fp;
625
Namval_t *nq;
626
if(!val)
627
{
628
nv_putv(np,val,flag,fp);
629
dss_unset(np, pp);
630
}
631
else if(nq=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL))
632
{
633
Namfun_t *pp;
634
if((pp=nv_hasdisc(nq,fp->disc)) && pp->type==fp->type)
635
{
636
nv_unset(np);
637
nv_clone(nq,np,0);
638
return;
639
}
640
}
641
if(!pp->dss || (flag&NV_NOFREE))
642
nv_putv(np,val, flag, fp);
643
}
644
645
646
#define DSS_EVENT (SF_EVENT+100)
647
static int dss_except(Sfio_t* iop, int event, void *data, Sfdisc_t *fp)
648
{
649
if(event==SF_CLOSING)
650
{
651
struct dssfile *sp = (struct dssfile*)fp;
652
if(sp && sp->np)
653
{
654
Namfun_t *nfp;
655
for(nfp=sp->np->nvfun; nfp && !nfp->disc && !nfp->disc->readf; nfp=nfp->next);
656
if(nfp)
657
(*nfp->disc->readf)(sp->np, (Sfio_t*)0, 0, nfp);
658
}
659
dssfclose(sp->fp);
660
free((void*)fp);
661
}
662
if(event!= DSS_EVENT)
663
return(0);
664
*(Sfdisc_t**)data = fp;
665
return(1);
666
}
667
668
static int read_parent(register Namval_t* np, Sfio_t *iop, int delim, Namfun_t *fp)
669
{
670
Namval_t *mp;
671
struct parent *dp = (struct parent*)fp;
672
struct dssfile *sp;
673
if(!iop)
674
sp = dp->sp;
675
else if(sfraise(iop, DSS_EVENT, (void*)&sp)==0)
676
{
677
sp = (struct dssfile*)calloc(1,sizeof(struct dssfile));
678
sp->np = np;
679
if(!((sp->fp = dssfopen(dp->dss,(char*)0,iop,DSS_FILE_READ,0))))
680
{
681
errormsg(SH_DICT,ERROR_exit(1),"%d: invalid dss format",sffileno(iop));
682
return(1);
683
}
684
sp->disc.exceptf = dss_except;
685
sfdisc(iop, &sp->disc);
686
}
687
if(sp && sp->rp)
688
{
689
if(!iop)
690
mp = np;
691
else if(sp->np != np)
692
mp = sp->mp?sp->mp:sp->np;
693
else
694
mp = sp->mp;
695
if(mp && mp->nvalue==sp->rp->data)
696
{
697
char *bp = (char*)malloc(sp->rp->size);
698
mp->nvalue = memcpy(bp,sp->rp->data,sp->rp->size);
699
nv_offattr(mp,NV_NOFREE);
700
}
701
}
702
dp->sp = 0;
703
if(iop)
704
{
705
int flags = nv_isattr(np,~NV_RDONLY)|NV_NOFREE|NV_NODISC;
706
Namarr_t *ap = nv_arrayptr(np);
707
dp->sp = sp;
708
sp->np = np;
709
sp->mp = 0;
710
if(!(sp->rp = dssfread(sp->fp)))
711
return(1);
712
if(ap)
713
{
714
(*ap->hdr.disc->putval)(np,sp->rp->data,flags,&ap->hdr);
715
np = sp->mp = nv_opensub(np);
716
}
717
else
718
nv_putval(np, sp->rp->data, flags);
719
nv_setsize(np,sp->rp->size);
720
nv_onattr(np,NV_BINARY);
721
}
722
return(0);
723
}
724
725
static int write_parent(register Namval_t* np, Sfio_t *iop, int delim, Namfun_t *fp)
726
{
727
struct parent *dp = (struct parent*)fp;
728
struct dssfile *sp;
729
if(sfraise(iop, DSS_EVENT, (void*)&sp)==0)
730
{
731
sp = (struct dssfile*)calloc(1,sizeof(struct dssfile));
732
sp->np = np;
733
if(!((sp->fp = dssfopen(dp->dss,(char*)0,iop,DSS_FILE_WRITE,0))))
734
{
735
errormsg(SH_DICT,ERROR_exit(1),"%d: cannot open for dss write",sffileno(iop));
736
return(1);
737
}
738
sp->disc.exceptf = dss_except;
739
sfdisc(iop, &sp->disc);
740
}
741
if(!sp->rp)
742
sp->rp = (Dssrecord_t*)calloc(1,sizeof(Dssrecord_t));
743
sp->rp->data = np->nvalue;
744
sp->rp->size = nv_size(np);
745
return dssfwrite(sp->fp,sp->rp) < 0 ? -1 : 0;
746
}
747
748
static Namval_t *next_parent(register Namval_t* np, Dt_t *root,Namfun_t *fp)
749
{
750
struct parent *dp = (struct parent*)fp;
751
Cxvariable_t *vp=0;
752
if(root && (np!=nv_namptr(dp->hdr.nodes,0)))
753
{
754
if((fp=nv_hasdisc(np,&mchild_disc)) || (fp=nv_hasdisc(np,&child_disc)))
755
dp = (struct parent*)((Namchld_t*)fp)->ptype;
756
757
}
758
if(!fp)
759
return(0);
760
do
761
{
762
if(root)
763
{
764
if(np==nv_namptr(dp->hdr.nodes,0))
765
{ root=dp->dict;
766
vp=(Cxvariable_t*)dtfirst(root);
767
}
768
else
769
{
770
if(!vp)
771
vp = vnode(np);
772
vp=(Cxvariable_t*)dtnext(dp->dict,vp);
773
}
774
#if 0
775
if(vp)
776
sfprintf(sfstderr,"%x: next=%s index=%d np=%x\n",vp,vp->name,vp->header.index,np);
777
else sfprintf(sfstderr,"vp==NULL\n");
778
#endif
779
}
780
else
781
{
782
np=node(vp,dp);
783
return (np);
784
#if 0
785
if(vp)
786
sfprintf(sfstderr,"%x: first=%s index=%d\n",vp,vp->name,vp->header.index);
787
#endif
788
}
789
}
790
while(vp && vp->header.index>=dp->hdr.numnodes-1);
791
if(!vp)
792
return((Namval_t*)0);
793
np = node(vp,dp);
794
return(np);
795
}
796
797
static const Namdisc_t parent_disc =
798
{
799
sizeof(struct parent),
800
put_parent,
801
0,
802
0,
803
0,
804
create_parent,
805
clone_parent,
806
0,
807
next_parent,
808
0,
809
read_parent,
810
write_parent
811
};
812
813
/*
814
* should only get here when requesting raw binary data
815
* This must come after the nv_tree discipline
816
*/
817
static char* get_parent(register Namval_t* np, Namfun_t *fp)
818
{
819
#if 1
820
char *data = np->nvalue;
821
size_t size = nv_size(np);
822
#else
823
#if 1
824
Dssrecord_t *rp = (Dssrecord_t*)np->nvalue;
825
#else
826
struct parent *dp = (struct parent*)nv_hasdisc(np,&parent_disc);
827
Dssrecord_t *rp = (Dssrecord_t*)dp->hdr.data;
828
#endif
829
#endif
830
char *cp;
831
#if 1
832
if(size>0)
833
{
834
size_t m, n = (4*size)/3 + size/45 + 8;
835
m = base64encode(data,size,(void**)0,cp=getbuf(n),n,(void**)0);
836
#else
837
if(rp && rp->size>0)
838
{
839
size_t m, n = (4*rp->size)/3 + rp->size/45 + 8;
840
m = base64encode(rp->data,rp->size, (void**)0, cp=getbuf(n), n, (void**)0);
841
#endif
842
nv_setsize(np,m);
843
return(cp);
844
}
845
return(0);
846
}
847
848
static const Namdisc_t parent2_disc =
849
{
850
0,0,get_parent
851
};
852
853
/*
854
* add discipline builtin given by name to type
855
*/
856
static Namval_t *add_discipline(const char *typename, const char *name, int (*fun)(int, char*[],Shbltin_t*), void* context)
857
{
858
Namval_t *mp;
859
int offset = stktell(stkstd);
860
sfputc(stkstd,0);
861
sfprintf(stkstd,NV_CLASS".dss.%s.%s",typename,name);
862
sfputc(stkstd,0);
863
mp = sh_addbuiltin(stkptr(stkstd,offset+1),fun,context);
864
stkseek(stkstd,offset);
865
nv_onattr(mp,NV_RDONLY);
866
nv_offattr(mp,NV_NOFREE);
867
return(mp);
868
}
869
870
static void put_type(Namval_t* np, const char* val, int flag, Namfun_t* fp)
871
{
872
struct type *tp = (struct type*)fp;
873
Cxoperand_t cop;
874
Namval_t *nq;
875
if(val && (nq=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL)))
876
{
877
Namfun_t *pp;
878
if((pp=nv_hasdisc(nq,fp->disc)) && pp->type==fp->type)
879
880
{
881
_nv_unset(np, flag);
882
nv_clone(nq,np,0);
883
return;
884
}
885
}
886
if(val && !(flag&NV_INTEGER) && tp->type->internalf && !cxisstring(tp->type))
887
{
888
size_t size = strlen(val);
889
cop.type = tp->type;
890
if((*tp->type->internalf)(tp->cx, tp->type, NiL, NiL, &cop, val, size, Vmregion, &Dssdisc) <0)
891
errormsg(SH_DICT,ERROR_exit(1),"%s: cannot covert to type dss.%s",val,tp->type->name);
892
if(cxisnumber(cop.type))
893
nv_putv(np,(char*)&cop.value.number,flag|NV_LDOUBLE,fp);
894
else
895
{
896
nv_setsize(np,cop.value.buffer.size);
897
nv_putv(np, (char*)cop.value.buffer.data, NV_RAW|NV_BINARY,fp);
898
}
899
}
900
else
901
nv_putv(np,val,flag,fp);
902
if(!val)
903
{
904
nv_disc(np,fp,NV_POP);
905
if(fp->nofree&~1)
906
free((void*)fp);
907
else
908
{
909
Namval_t *mp;
910
int i;
911
for(i=0; i < sizeof(tp->bltins)/sizeof(Namval_t*); i++)
912
{
913
if(mp = tp->bltins[i])
914
{
915
Shell_t *shp = sh_getinterp();
916
dtdelete(shp->bltin_tree,mp);
917
free((void*)mp);
918
}
919
}
920
free((void*)fp);
921
}
922
}
923
}
924
925
static char* get_type(register Namval_t* np, Namfun_t *fp)
926
{
927
struct type *tp = (struct type*)fp;
928
struct parent *dp;
929
Cxvalue_t cval;
930
int i,n;
931
char *buf,*format;
932
Cxvariable_t *vp=0;
933
Namval_t *mp = &tp->details;
934
if(!tp->type->externalf)
935
return(nv_getv(np,fp));
936
if(nv_isattr(np,NV_INTEGER))
937
cval.number = nv_getn(np,fp);
938
else
939
{
940
nv_onattr(np,NV_RAW);
941
cval.string.data = nv_getv(np,fp);
942
nv_offattr(np,NV_RAW);
943
if((n=nv_size(np))==0)
944
n = strlen(cval.string.data);
945
cval.string.size = n;
946
}
947
buf = getbuf(32);
948
if(nv_hasdisc(np,&child_disc))
949
vp = vnode(np);
950
if(dp=(struct parent*)nv_hasdisc(np,&parent_disc))
951
mp = node((Cxvariable_t*)0,dp);
952
if(!(format = nv_getval(mp)) && vp)
953
format = vp->format.details;
954
for(i=0; i < 2; i++)
955
{
956
n = (*tp->type->externalf)(tp->cx, tp->type, format, NiL, &cval, buf, buflen, &Dssdisc);
957
if(n<buflen)
958
break;
959
buf = getbuf(n);
960
}
961
return(buf);
962
}
963
964
/*
965
* They can all share one instance of the discipline
966
*/
967
static Namfun_t *clone_type(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
968
{
969
struct type *tp = (struct type*)fp;
970
if(!fp->next)
971
pushtype(np, tp->type, fp);
972
if(fp->next)
973
{
974
struct type *dp = newof((struct type*)0, struct type,1,0);
975
*dp = *tp;
976
dp->fun.nofree &= ~0;
977
return(&dp->fun);
978
}
979
fp->nofree |=1;
980
return(fp);
981
}
982
983
static Namval_t *next_type(register Namval_t* np, Dt_t *root,Namfun_t *fp)
984
{
985
struct type *tp = (struct type*)fp;
986
Namfun_t *fpn = fp->next;
987
if(!root && (!fpn || fpn->disc != &parent_disc))
988
{
989
pushtype(np, tp->type, fp);
990
if(fp->next==fpn)
991
return(&((struct type*)fp)->details);
992
}
993
if(tp->pfun)
994
return((*tp->pfun->disc->nextf)(np,root,tp->pfun));
995
return(0);
996
}
997
998
static char *setdisc_type(Namval_t *np, const char *event, Namval_t* action, Namfun_t
999
*fp)
1000
{
1001
struct type *tp = (struct type*)fp;
1002
int n = -1;
1003
const char *name = event?event:(const char*)action;
1004
if(name)
1005
{
1006
if(strcmp(name,"match")==0 && tp->type->match)
1007
n = 0;
1008
}
1009
if(!event)
1010
{
1011
if(!action && tp->type->match)
1012
return("match");
1013
n = -1;
1014
}
1015
if(n<0)
1016
return(nv_setdisc(np,event,action,fp));
1017
if(action==np)
1018
{
1019
/* clone the discipline for variable specific function */
1020
if((fp->nofree&1) && fp->type!=np)
1021
{
1022
tp = (struct type*)nv_disc(np, fp, NV_CLONE);
1023
fp->nofree &= ~1;
1024
}
1025
action = tp->bltins[n];
1026
}
1027
else if(action)
1028
tp->bltins[n] = action;
1029
else
1030
{
1031
action = tp->bltins[n];
1032
tp->bltins[n] = 0;
1033
}
1034
return(action?(char*)action:"");
1035
}
1036
1037
static Namval_t *create_type(Namval_t *np,const char *name,int flag,Namfun_t *fp)
1038
{
1039
struct type *tp = (struct type*)fp;
1040
if(!fp->next)
1041
{
1042
pushtype(np, tp->type, fp);
1043
fp = nv_hasdisc(np,fp->disc);
1044
}
1045
while (fp = fp->next)
1046
if (fp->disc && fp->disc->createf)
1047
{
1048
if(np = (*fp->disc->createf)(np, name, flag, fp))
1049
tp->fun.last = fp->last;
1050
return(np);
1051
}
1052
if(memcmp(name,NV_DATA,sizeof(NV_DATA)-1)==0 && (name[sizeof(NV_DATA)-1]==0 || strchr("+=[",name[sizeof(NV_DATA)-1])))
1053
{
1054
tp->fun.last = (char*)name + sizeof(NV_DATA)-1;
1055
return(&tp->details);
1056
}
1057
return(0);
1058
}
1059
1060
static const Namdisc_t type_disc =
1061
{
1062
0,
1063
put_type,
1064
get_type,
1065
0,
1066
setdisc_type,
1067
create_type,
1068
clone_type,
1069
0,
1070
next_type
1071
};
1072
1073
static const char sh_opttype[] =
1074
"[-1c?\n@(#)$Id: type (AT&T Research) 2008-06-09 $\n]"
1075
USAGE_LICENSE
1076
"[+NAME?\f?\f - set the type of variables to \b\f?\f\b]"
1077
"[+DESCRIPTION?\b\f?\f\b sets the type of each of the variables specified "
1078
"by \aname\a to \b\f?\f\b. If \b=\b\avalue\a is specified, "
1079
"the variable \aname\a is set to \avalue\a before the variable "
1080
"is converted to \b\f?\f\b.]"
1081
"[+?If no \aname\as are specified then the names and values of all "
1082
"variables of this type are written to standard output.]"
1083
"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
1084
"field splitting and pathname expansion are not performed on "
1085
"the arguments. Tilde expansion occurs on \avalue\a.]"
1086
"[+?The types are:]{\ftypes\f}"
1087
"[r?Enables readonly. Once enabled, the value cannot be changed or unset.]"
1088
"[a?index array. Each \aname\a will converted to an index "
1089
"array of type \b\f?\f\b. If a variable already exists, the current "
1090
"value will become index \b0\b.]"
1091
"[A?Associative array. Each \aname\a will converted to an associate "
1092
"array of type \b\f?\f\b. If a variable already exists, the current "
1093
"value will become subscript \b0\b.]"
1094
"[p?Causes the output to be in a form of \b\f?\f\b commands that can be "
1095
"used as input to the shell to recreate the current type of "
1096
"these variables.]"
1097
"\n"
1098
"\n[name[=value]...]\n"
1099
"\n"
1100
"[+EXIT STATUS?]{"
1101
"[+0?Successful completion.]"
1102
"[+>0?An error occurred.]"
1103
"}"
1104
1105
"[+SEE ALSO?\breadonly\b(1), \btypeset\b(1)]"
1106
;
1107
1108
static void mktype(Namval_t *np, Cxtype_t *tp, Cx_t *cx)
1109
{
1110
struct type *pp;
1111
struct Optdisc optdisc;
1112
pp = newof((struct type*)0, struct type,1,0);
1113
pp->fun.dsize = sizeof(struct type);
1114
pp->fun.type = np;
1115
pp->fun.nofree = 1;
1116
pp->fun.disc = &type_disc;
1117
pp->type = tp;
1118
pp->cx = cx;
1119
if(tp->format.details)
1120
{
1121
Namval_t *mp = &pp->details;
1122
nv_setvtree(np);
1123
mp->nvname = NV_DATA;
1124
mp->nvalue = tp->format.details;
1125
nv_onattr(mp,NV_NOFREE);
1126
}
1127
nv_disc(np,&pp->fun,NV_LAST);
1128
if(tp->match)
1129
pp->bltins[0] = add_discipline(pp->type->name, "match",match,pp );
1130
memset(&optdisc,0,sizeof(optdisc));
1131
optdisc.dss.optdisc.infof = dssoptinfo;
1132
optdisc.dss.header = (Cxheader_t*)tp;
1133
optdisc.np = np;
1134
nv_addtype(np, sh_opttype, &optdisc.dss.optdisc, sizeof(optdisc));
1135
while(tp = tp->base)
1136
{
1137
if(tp->base && !typenode(tp->name, 0))
1138
create_dss((Namval_t*)0, tp->name, 0, (Namfun_t*)0);
1139
}
1140
}
1141
1142
static Namval_t *create_dss(Namval_t *np,const char *name,int flag,Namfun_t *fp)
1143
{
1144
Cxvariable_t *vp;
1145
Cxstate_t *sp;
1146
Cxtype_t *tp=0;
1147
Cx_t *cx;
1148
struct parent *dp;
1149
Namval_t *mp;
1150
Dss_t *dss=0;
1151
Dssmeth_t *meth;
1152
long n;
1153
Dt_t *dict;
1154
Namval_t *parent = nv_lastdict();
1155
struct Optdisc optdisc;
1156
char *cp=0;
1157
Dssdisc.errorf = (Error_f)errorf;
1158
if(fp && !(cp = strchr(name,'.')))
1159
fp->last = (char*)name + strlen(name);
1160
mp = typenode(name,0);
1161
if(cp)
1162
{
1163
Namfun_t *fq;
1164
*cp = '.';
1165
if(!mp)
1166
return(0);
1167
for(fq=mp->nvfun ;fq && !(fq->disc && fq->disc->createf); fq->next);
1168
if(!fq)
1169
return(0);
1170
if(np = (*fq->disc->createf)(mp, cp+1, flag, fq))
1171
fp->last = fq->last;
1172
return(np);
1173
}
1174
if(mp)
1175
return(mp);
1176
if(meth = dssmeth(name,&Dssdisc))
1177
{
1178
if(!(dss = dssopen(0, 0,&Dssdisc,meth)))
1179
errormsg(SH_DICT,ERROR_exit(1),"dssopen failed");
1180
cx = dss->cx;
1181
sp = cx->state;
1182
}
1183
else
1184
{
1185
Dssstate_t *state = dssstate(&Dssdisc);
1186
if(!state || !(tp = dtmatch(state->cx->types,name)))
1187
errormsg(SH_DICT,ERROR_exit(1),"%s: unknown dss type",name);
1188
sp = state->cx;
1189
cx = cxopen(0,0,&Dssdisc);
1190
}
1191
mp = typenode(name,NV_ADD);
1192
if(dss)
1193
dict = dss->cx->variables;
1194
else
1195
{
1196
check_numeric(mp, tp, sp);
1197
if(!tp->member || !(dict = tp->member->members))
1198
{
1199
mktype(mp, tp, cx);
1200
return(mp);
1201
}
1202
}
1203
for (n=0,vp = (Cxvariable_t*)dtfirst(dict); vp; vp = (Cxvariable_t*)dtnext(dict, vp))
1204
{
1205
Namval_t *qp;
1206
if(strcmp(vp->name,"dss")==0)
1207
continue;
1208
#if 0
1209
vp->header.index = n;
1210
sfprintf(sfstderr,"tname=%s name=%s n=%d index=%d\n",name,vp->name,n,vp->header.index);
1211
#endif
1212
vp->data = (void*)n++;
1213
if(vp->type==sp->type_number || vp->type==sp->type_string || vp->type==sp->type_buffer)
1214
continue;
1215
if(!(qp=typenode(vp->type->name,0)))
1216
{
1217
if(!vp->type->member && (qp=typenode(vp->type->name,NV_ADD)))
1218
{
1219
mktype(qp,vp->type,cx);
1220
check_numeric(qp, vp->type, sp);
1221
}
1222
else if(vp->type->member)
1223
qp = create_dss(np, vp->name,flag,fp);
1224
}
1225
}
1226
if(!(dp = newof((struct parent*)0, struct parent,1,0)))
1227
return(0);
1228
dp->hdr.numnodes = n+1;
1229
dp->hdr.fun.disc = &parent_disc;
1230
dp->hdr.fun.type = mp;
1231
dp->hdr.np = mp;
1232
dp->hdr.sh = fp?((struct dsstype*)fp)->sh:0;
1233
dp->hdr.parent = parent;
1234
dp->dss = dss;
1235
dp->cx = cx;
1236
dp->dict = dict;
1237
dp->state = sp;
1238
dp->type = tp;
1239
dp->disc = &Dssdisc;
1240
dp->hdr.childfun.fun.disc = meth?&mchild_disc:&child_disc;
1241
dp->hdr.childfun.fun.nofree = 1;
1242
dp->hdr.childfun.ptype = &dp->hdr;
1243
dp->parentfun.disc = &parent2_disc;
1244
dp->parentfun.nofree = 1;
1245
#if 0
1246
nv_disc(mp, &dp->parentfun,NV_FIRST);
1247
#endif
1248
nv_setvtree(mp);
1249
if(dss)
1250
{
1251
int i,n=((struct dsstype*)fp)->nnames;
1252
dp->hdr.names = ((struct dsstype*)fp)->names;
1253
nv_adddisc(mp,(const char**)dp->hdr.names,0);
1254
for(i=0; i < n; i++)
1255
add_discipline(name,dp->hdr.names[i], query,&dp->hdr.names[i]);
1256
}
1257
nv_disc(mp,&dp->hdr.fun,NV_FIRST);
1258
mp->nvalue = 0;
1259
if(dss)
1260
nv_onattr(mp,NV_BINARY|NV_RAW);
1261
memset(&optdisc,0,sizeof(optdisc));
1262
optdisc.dss.optdisc.infof = dssoptinfo;
1263
optdisc.dss.header = meth?(Cxheader_t*)meth:(Cxheader_t*)tp;
1264
optdisc.np = mp;
1265
nv_addtype(mp, sh_opttype, &optdisc.dss.optdisc, sizeof(optdisc));
1266
return(mp);
1267
}
1268
1269
static char *name_dss(Namval_t *np, Namfun_t *fp)
1270
{
1271
int len = sizeof(NV_CLASS)+strlen(np->nvname)+1 ;
1272
char *name = getbuf(len);
1273
memcpy(name,NV_CLASS,sizeof(NV_CLASS)-1);
1274
name[sizeof(NV_CLASS)-1] = '.';
1275
strcpy(&name[sizeof(NV_CLASS)],np->nvname);
1276
return(name);
1277
}
1278
1279
static const Namdisc_t dss_disc =
1280
{
1281
0,
1282
0,
1283
0,
1284
0,
1285
0,
1286
create_dss,
1287
0,
1288
name_dss,
1289
};
1290
1291
static const char *discnames[] = { "list", "load", 0 };
1292
1293
static const char optlist[] =
1294
"[-1c?\n@(#)$Id: dss.list (AT&T Research) 2007-05-09 $\n]"
1295
USAGE_LICENSE
1296
"[+NAME?\f?\f - list the known dss entities]"
1297
"[+DESCRIPTION?\b\f?\f\b causes each of the specified dss entities "
1298
"specified as options to be written to standard output. If no "
1299
"options are specified, all entities are written.]"
1300
"[+?If multiple entities types are written, then the entity type is written "
1301
"before each of the names.]"
1302
"[l?List the names of library entities.]"
1303
"[m?List the names of method entities.]"
1304
"[q?List the names of query entities.]"
1305
"[t?List the names of type entities.]"
1306
"[v?A description of each entity will be listed along with the name.]"
1307
"\n"
1308
"\n\n"
1309
"\n"
1310
"[+EXIT STATUS?]{"
1311
"[+0?Successful completion.]"
1312
"[+>0?An error occurred.]"
1313
"}"
1314
"[+SEE ALSO?\b"NV_CLASS".dss.load\b(1)]"
1315
;
1316
1317
#define fval(x) (1L<<(x)-'a')
1318
static const char *listnames[] = { "library", "method", "query", "type", 0 };
1319
1320
static int listdss(int argc, char *argv[], Shbltin_t *bp)
1321
{
1322
Cxstate_t *sp = cxstate((Cxdisc_t*)bp->ptr);
1323
int flags=0, n, delim='\n';
1324
Dt_t *dict;
1325
char *name;
1326
Cxtype_t *tp;
1327
NOT_USED(argc);
1328
while((n = optget(argv,optlist))) switch(n)
1329
{
1330
case 'm': case 'l': case 't': case 'q':
1331
flags |= fval(n);
1332
break;
1333
case 'v':
1334
delim = '\t';
1335
break;
1336
case ':':
1337
errormsg(SH_DICT,2, "%s", opt_info.arg);
1338
case '?':
1339
errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
1340
return(2);
1341
}
1342
argv += opt_info.index;
1343
if(error_info.errors || *argv)
1344
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
1345
if(flags==0)
1346
flags = fval('m')|fval('l')|fval('q')|fval('t');
1347
n = flags&(flags-1);
1348
argv = (char**)listnames;
1349
while(name = *argv++)
1350
{
1351
if(fval('t') && *name=='t')
1352
dict = sp->types;
1353
else if(fval('l') && *name=='l')
1354
dict = sp->libraries;
1355
else if(fval('q') && *name=='q')
1356
dict = sp->queries;
1357
else if(fval('m') && *name=='m')
1358
dict = sp->methods;
1359
else
1360
continue;
1361
for (tp = (Cxtype_t*)dtfirst(dict); tp; tp = (Cxtype_t*)dtnext(dict, tp))
1362
{
1363
if(n)
1364
sfprintf(sfstdout,"%s\t",name);
1365
sfputr(sfstdout,tp->name,delim);
1366
if(delim!='\n')
1367
sfputr(sfstdout,tp->description,'\n');
1368
}
1369
}
1370
return(error_info.errors);
1371
}
1372
1373
static const char optload[] =
1374
"[-1c?\n@(#)$Id: dss.load (AT&T Research) 2003-01-10 $\n]"
1375
USAGE_LICENSE
1376
"[+NAME?\f?\f - load a dss format library]"
1377
"[+DESCRIPTION?\b\f?\f\b causes each of the specified dss libraries \alib\a "
1378
"to be loaded into the shell and its contents merged with other "
1379
"dss libraries.]"
1380
"\n"
1381
"\nlib ...\n"
1382
"\n"
1383
"[+EXIT STATUS?]{"
1384
"[+0?Successful completion.]"
1385
"[+>0?An error occurred.]"
1386
"}"
1387
"[+SEE ALSO?\b"NV_CLASS".dss.list\b(1)]"
1388
;
1389
1390
static int loadlib(int argc, char *argv[], Shbltin_t *bp)
1391
{
1392
Cxdisc_t *dp = (Cxdisc_t*)bp->ptr;
1393
char *name;
1394
int n;
1395
NOT_USED(argc);
1396
while((n = optget(argv,optload))) switch(n)
1397
{
1398
case ':':
1399
errormsg(SH_DICT,2, "%s", opt_info.arg);
1400
case '?':
1401
errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
1402
return(2);
1403
}
1404
argv += opt_info.index;
1405
if(error_info.errors || !*argv)
1406
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
1407
while(name = *argv++)
1408
if(!dssload(name, dp))
1409
error_info.errors = 1;
1410
return(error_info.errors);
1411
}
1412
1413
static Cxvalue_t *getvalue(Namval_t *np, Namfun_t *fp, Cxoperand_t *valp)
1414
{
1415
if(fp && fp->disc==&child_disc)
1416
{
1417
Namchld_t *pp = (Namchld_t*)fp;
1418
struct parent *dp = (struct parent*)pp->ptype;
1419
Cxvariable_t *vp = vnode(np);
1420
#if 1
1421
cxcast(dp->cx,valp,vp,vp->type,dp->hdr.parent->nvalue,(char*)0);
1422
#else
1423
cxcast(dp->cx,valp,vp,vp->type,dp->hdr.data,(char*)0);
1424
#endif
1425
}
1426
else
1427
{
1428
if(nv_isattr(np, NV_INTEGER))
1429
valp->value.number = nv_getnum(np);
1430
else
1431
{
1432
valp->value.string.data = nv_getval(np);
1433
valp->value.string.size = nv_size(np);
1434
if(!valp->value.string.size)
1435
valp->value.string.size = strlen(valp->value.string.data);
1436
}
1437
}
1438
return(&valp->value);
1439
}
1440
1441
static const char optmatch[] =
1442
"[-1c?\n@(#)$Id: dss.match (AT&T Research) 2003-01-15 $\n]"
1443
USAGE_LICENSE
1444
"[+NAME?\f?\f - match a dss type variable to a pattern]"
1445
"[+DESCRIPTION?\b\f?\f\b causes the value of the variable whose name "
1446
"precedes \b.match\b in the callers name to be matched against "
1447
"the specified pattern \apattern\a. The interpretation of "
1448
"\apattern\a depends on the type of this variable.]"
1449
"[+?\fmatch\f]"
1450
"[v?\apattern\a is a variable name that contains the pattern.]"
1451
"\n"
1452
"\npattern\n"
1453
"\n"
1454
"[+EXIT STATUS?]{"
1455
"[+0?The value of the variable matched \apattern\a.]"
1456
"[+1?The value of the variable did not match \apattern\a.]"
1457
"[+2?A usage error was found or a help request was made.]"
1458
"[+>2?An error occurred.]"
1459
"}"
1460
"[+SEE ALSO?\bdss\b(3)]"
1461
;
1462
1463
static int match(int argc, char *argv[], Shbltin_t *bp)
1464
{
1465
struct type *tp = (struct type*)bp->ptr;
1466
Cxmatch_t *mp = tp->type->match;
1467
Namval_t *np;
1468
Namfun_t *fp;
1469
Cxoperand_t cval;
1470
Cxvalue_t *valp = &cval.value;
1471
Cxtype_t *tptr=0;
1472
Dssoptdisc_t disc;
1473
char *cp;
1474
void *comp;
1475
int n, flag=0;
1476
if(comp=bp->data)
1477
{
1478
if(!(bp->flags&SH_END_OPTIM))
1479
goto exec;
1480
(*mp->freef)(tp->cx, comp, &Dssdisc);
1481
bp->data = 0;
1482
if(argc<=0)
1483
return(0);
1484
}
1485
memset((void*)&disc,0,sizeof(disc));
1486
disc.header = (Cxheader_t*)tp->type;
1487
disc.optdisc.infof = dssoptinfo;
1488
opt_info.disc = &disc.optdisc;
1489
while((n = optget(argv,optmatch))) switch(n)
1490
{
1491
case 'v':
1492
flag = 'v';
1493
break;
1494
case ':':
1495
errormsg(SH_DICT,2, "%s", opt_info.arg);
1496
case '?':
1497
errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
1498
opt_info.disc = 0;
1499
return(2);
1500
}
1501
opt_info.disc = 0;
1502
argv += opt_info.index;
1503
if(error_info.errors || !(cp= *argv))
1504
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
1505
if(flag)
1506
{
1507
if(!(np = nv_open(*argv, ((Shell_t*)bp->shp)->var_tree, NV_NOADD|NV_VARNAME|NV_NOASSIGN)))
1508
errormsg(SH_DICT,ERROR_exit(3),"%s: variable not set",*argv);
1509
if((fp=nv_hasdisc(np,&mchild_disc)) || (fp=nv_hasdisc(np,&child_disc)))
1510
{
1511
Namval_t *mp = (*fp->disc->typef)(np,fp);
1512
if(mp)
1513
tptr = ((struct type*)(mp->nvfun))->type;
1514
if(!tptr)
1515
fp = 0;
1516
}
1517
else if(fp=nv_hasdisc(np,&type_disc))
1518
tptr = ((struct type*)fp)->type;
1519
valp = getvalue(np, fp, &cval);
1520
}
1521
else
1522
{
1523
valp->string.data = cp;
1524
valp->string.size = strlen(cp);
1525
}
1526
if(!tptr)
1527
tptr = tp->cx->state->type_string;
1528
comp = (*mp->compf)(tp->cx, tp->type, tptr, valp, &Dssdisc);
1529
if(!comp)
1530
return(3);
1531
if(bp->flags&SH_BEGIN_OPTIM)
1532
bp->data = comp;
1533
exec:
1534
if(bp->vnode)
1535
fp = nv_hasdisc(bp->vnode, &child_disc);
1536
valp = getvalue(bp->vnode, fp, &cval);
1537
n = (*mp->execf)(tp->cx, comp, tptr, valp, &Dssdisc);
1538
if(!bp->data)
1539
(*mp->freef)(tp->cx, comp, &Dssdisc);
1540
return(n<0?4:!n);
1541
}
1542
1543
void lib_init(int flag, void* context)
1544
{
1545
Shell_t *shp = ((Shbltin_t*)context)->shp;
1546
Dssstate_t *state;
1547
Dsslib_t *lib;
1548
Namval_t *np,*rp;
1549
struct dsstype *nfp = newof(NiL,struct dsstype,1,0);
1550
const char *name;
1551
char **av,tmp[sizeof(NV_CLASS)+17];
1552
int level,i,len=0,n=0;
1553
state = dssinit(&Dssdisc,errorf);
1554
sfsprintf(tmp, sizeof(tmp), "%s.dss", NV_CLASS);
1555
np = nv_open(tmp, shp->var_tree, NV_VARNAME);
1556
typedict = nv_dict(np);
1557
nfp->fun.disc = &dss_disc;
1558
nv_disc(np,&nfp->fun,NV_FIRST);
1559
nv_adddisc(np,discnames,0);
1560
sfsprintf(tmp, sizeof(tmp), "%s.dss.load", NV_CLASS);
1561
sh_addbuiltin(tmp, loadlib, &Dssdisc);
1562
sfsprintf(tmp, sizeof(tmp), "%s.dss.list", NV_CLASS);
1563
sh_addbuiltin(tmp, listdss, &Dssdisc);
1564
/* create reference variable dss to NV_CLASS.dss */
1565
rp = nv_open("dss", shp->var_tree, NV_IDENT);
1566
nv_unset(rp);
1567
nv_putval(rp,nv_name(np),NV_NOFREE);
1568
nv_setref(rp,shp->var_tree,NV_VARNAME|NV_NOREF);
1569
for(level=0; level <2; level++)
1570
{
1571
char *cp;
1572
n = 0;
1573
for (lib = dsslib(NiL, DSS_VERBOSE, &Dssdisc); lib; lib = (Dsslib_t*)dtnext(state->cx->libraries, lib))
1574
{
1575
int m;
1576
if (!lib->queries)
1577
continue;
1578
for (i = 0; name = lib->queries[i].name; i++)
1579
{
1580
if(strcmp(name,"null")==0)
1581
continue;
1582
if(strcmp(name,"return")==0)
1583
continue;
1584
if(strcmp(name,"print")==0)
1585
continue;
1586
m = strlen(name)+1;
1587
if(level==0)
1588
{
1589
n++;
1590
len += m;
1591
}
1592
else
1593
{
1594
av[n++] = memcpy(cp,name,m);
1595
cp += m;
1596
}
1597
}
1598
if(level==0)
1599
{
1600
av = (char**)malloc((n+1)*sizeof(char*) + len);
1601
cp = (char*)&av[n+1];
1602
}
1603
}
1604
}
1605
nfp->names = av;
1606
nfp->nnames = n;
1607
nfp->sh = shp;
1608
}
1609
1610
SHLIB(dss)
1611
1612