Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/tw/expr.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-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
* Glenn Fowler
23
* AT&T Research
24
*
25
* tw expression definitions
26
*/
27
28
#include "tw.h"
29
30
#include <ctype.h>
31
#include <tm.h>
32
#include <sfdisc.h>
33
#include <sum.h>
34
35
#define STAT(f,b) ((state.ftwflags&FTW_PHYSICAL)?lstat(f,b):pathstat(f,b))
36
37
typedef struct Exsum_s
38
{
39
Sum_t* sum;
40
Sfio_t* buf;
41
} Exsum_t;
42
43
static Exid_t symbols[] =
44
{
45
EXID("AGAIN", CONSTANT, C_AGAIN, INTEGER, 0),
46
EXID("BLK", CONSTANT, C_BLK, INTEGER, 0),
47
EXID("C", CONSTANT, C_C, INTEGER, 0),
48
EXID("CHR", CONSTANT, C_CHR, INTEGER, 0),
49
EXID("CTG", CONSTANT, C_CTG, INTEGER, 0),
50
EXID("D", CONSTANT, C_D, INTEGER, 0),
51
EXID("DC", CONSTANT, C_DC, INTEGER, 0),
52
EXID("DIR", CONSTANT, C_DIR, INTEGER, 0),
53
EXID("DOOR", CONSTANT, C_DOOR, INTEGER, 0),
54
EXID("DNR", CONSTANT, C_DNR, INTEGER, 0),
55
EXID("DNX", CONSTANT, C_DNX, INTEGER, 0),
56
EXID("FIFO", CONSTANT, C_FIFO, INTEGER, 0),
57
EXID("FMT", CONSTANT, C_FMT, INTEGER, 0),
58
EXID("FOLLOW", CONSTANT, C_FOLLOW, INTEGER, 0),
59
EXID("LNK", CONSTANT, C_LNK, INTEGER, 0),
60
EXID("NOPOST", CONSTANT, C_NOPOST, INTEGER, 0),
61
EXID("NR", CONSTANT, C_NR, INTEGER, 0),
62
EXID("NS", CONSTANT, C_NS, INTEGER, 0),
63
EXID("NX", CONSTANT, C_NX, INTEGER, 0),
64
EXID("REG", CONSTANT, C_REG, INTEGER, 0),
65
EXID("SKIP", CONSTANT, C_SKIP, INTEGER, 0),
66
EXID("SOCK", CONSTANT, C_SOCK, INTEGER, 0),
67
EXID("args", ID, F_args, INTEGER, 0),
68
EXID("atime", ID, F_atime, T_DATE, 0),
69
EXID("blksize", ID, F_blksize, INTEGER, 0),
70
EXID("blocks", ID, F_blocks, INTEGER, 0),
71
EXID("checksum",ID, F_checksum, STRING, 0),
72
EXID("cmdarg", FUNCTION, X_cmdarg, I|A(1,S), 0),
73
EXID("cmdflush",FUNCTION, X_cmdflush, I, 0),
74
EXID("ctime", ID, F_ctime, T_DATE, 0),
75
EXID("date_t", DECLARE, T_DATE, T_DATE, 0),
76
EXID("dev", ID, F_dev, INTEGER, 0),
77
EXID("fstype", ID, F_fstype, STRING, 0),
78
EXID("gid", ID, F_gid, T_GID, 0),
79
EXID("gid_t", DECLARE, T_GID, T_GID, 0),
80
EXID("gidok", ID, F_gidok, INTEGER, 0),
81
EXID("info", ID, F_info, INTEGER, 0),
82
EXID("ino", ID, F_ino, INTEGER, 0),
83
EXID("level", ID, F_level, INTEGER, 0),
84
EXID("local", ID, F_local, INTEGER, 0),
85
EXID("magic", ID, F_magic, STRING, 0),
86
EXID("md5sum", ID, F_md5sum, STRING, 0),
87
EXID("mime", ID, F_mime, STRING, 0),
88
EXID("mode", ID, F_mode, T_MODE, 0),
89
EXID("mode_t", DECLARE, T_MODE, T_MODE, 0),
90
EXID("mtime", ID, F_mtime, T_DATE, 0),
91
EXID("name", ID, F_name, STRING, 0),
92
EXID("nlink", ID, F_nlink, INTEGER, 0),
93
EXID("parent", ID, F_parent, INTEGER, 0),
94
EXID("path", ID, F_path, STRING, 0),
95
EXID("perm", ID, F_perm, T_PERM, 0),
96
EXID("perm_t", DECLARE, T_PERM, T_PERM, 0),
97
EXID("rdev", ID, F_rdev, INTEGER, 0),
98
EXID("size", ID, F_size, INTEGER, 0),
99
EXID("status", ID, F_status, INTEGER, 0),
100
EXID("sum", FUNCTION, X_sum, S|A(1,S), 0),
101
EXID("symlink", ID, F_symlink, STRING, 0),
102
EXID("type", ID, F_type, INTEGER, 0),
103
EXID("uid", ID, F_uid, T_UID, 0),
104
EXID("uid_t", DECLARE, T_UID, T_UID, 0),
105
EXID("uidok", ID, F_uidok, INTEGER, 0),
106
EXID("url", ID, F_url, STRING, 0),
107
EXID("view", ID, F_view, INTEGER, 0),
108
EXID("visit", ID, F_visit, INTEGER, 0),
109
EXID(0, 0, 0, 0, 0)
110
};
111
112
/*
113
* dereference ftw
114
*/
115
116
static Ftw_t*
117
deref(register Ftw_t* ftw, Exid_t* sym, register Exref_t* ref)
118
{
119
register char* path;
120
121
path = ftw->path;
122
while (ref)
123
{
124
if (!ftw || ref->symbol->index != F_parent)
125
{
126
if (ftw && !ref->next && MEMINDEX(sym->index)) break;
127
error(3, "%s: invalid %s.%s reference", path, ref->symbol->name, sym->name);
128
}
129
ref = ref->next;
130
ftw = ftw->parent;
131
}
132
return ftw;
133
}
134
135
/*
136
* return sum() for path
137
*/
138
139
static char*
140
sum(Exsum_t* sum, const char* path)
141
{
142
Sfio_t* sp;
143
char* s;
144
int r;
145
146
suminit(sum->sum);
147
if (!(sp = sfopen(NiL, path, "r")))
148
goto bad;
149
while (s = (char*)sfreserve(sp, SF_UNBOUND, 0))
150
sumblock(sum->sum, s, sfvalue(sp));
151
r = !!sfvalue(sp);
152
if (sfclose(sp) || r)
153
goto bad;
154
sumdone(sum->sum);
155
sumprint(sum->sum, sum->buf, 0, 0);
156
return sfstruse(sum->buf);
157
bad:
158
return "*******READ-ERROR*******";
159
}
160
161
/*
162
* format urlized path
163
*/
164
165
static char*
166
fmturl(register const char* path)
167
{
168
register unsigned char* p;
169
register char* s;
170
register int n;
171
register int c;
172
char* r;
173
174
static const char hex[] = "0123456789ABCDEF";
175
176
n = 0;
177
p = (unsigned char*)path;
178
while (c = *p++)
179
if (!(isalnum(c) || c == '_' || c == '-' || c == '+' || c == '=' || c == '/' || c == '.'))
180
n++;
181
r = s = fmtbuf(n * 2 + (p - (unsigned char*)path));
182
p = (unsigned char*)path;
183
while (c = *p++)
184
if (!(isalnum(c) || c == '_' || c == '-' || c == '+' || c == '=' || c == '/' || c == '.'))
185
{
186
*s++ = '%';
187
*s++ = hex[(c>>4)&0xF];
188
*s++ = hex[c&0xF];
189
}
190
else
191
*s++ = c;
192
*s = 0;
193
return r;
194
}
195
196
/*
197
* return value for symbol sym
198
*/
199
200
static Extype_t
201
getval(Expr_t* pgm, Exnode_t* node, Exid_t* sym, Exref_t* ref, void* env, int elt, Exdisc_t* disc)
202
{
203
register struct stat* st;
204
register Ftw_t* ftw;
205
Extype_t v;
206
Local_t* lp;
207
Sfio_t* fp;
208
Fileid_t id;
209
Visit_t* vp;
210
Exsum_t* sp;
211
212
static char text[PATH_MAX];
213
214
NoP(pgm);
215
NoP(node);
216
NoP(disc);
217
if (elt >= EX_SCALAR)
218
{
219
ftw = (Ftw_t*)env;
220
if (ref && !(ftw = deref(ftw, sym, ref)))
221
{
222
v.integer = 0;
223
return v;
224
}
225
st = &ftw->statb;
226
}
227
switch (sym->index)
228
{
229
case F_args:
230
v.integer = state.args;
231
break;
232
case F_atime:
233
v.integer = st->st_atime;
234
break;
235
case F_blocks:
236
v.integer = iblocks(st);
237
break;
238
case F_blksize:
239
#ifdef stat_blksize
240
v.integer = st->st_blksize;
241
#else
242
v.integer = 1024;
243
#endif
244
break;
245
case F_checksum:
246
v.string = sum((Exsum_t*)node->local.pointer, PATH(ftw));
247
goto string;
248
case F_ctime:
249
v.integer = st->st_ctime;
250
break;
251
case F_dev:
252
v.integer = st->st_dev;
253
break;
254
case F_fstype:
255
v.string = fmtfs(st);
256
goto string;
257
case F_gid:
258
v.integer = st->st_gid;
259
break;
260
case F_gidok:
261
v.integer = !isdigit(*fmtgid(st->st_gid));
262
break;
263
case F_info:
264
v.integer = ftw->info;
265
break;
266
case F_ino:
267
v.integer = st->st_ino;
268
break;
269
case F_level:
270
v.integer = ftw->level;
271
break;
272
case F_local:
273
if (state.localmem)
274
error(3, "%s: reference invalid when members declared", sym->name);
275
else
276
v.integer = ftw->local.number;
277
break;
278
case F_magic:
279
fp = sfopen(NiL, PATH(ftw), "r");
280
v.string = magictype(state.magic, fp, PATH(ftw), st);
281
if (fp)
282
sfclose(fp);
283
goto string;
284
case F_md5sum:
285
v.string = sum((Exsum_t*)node->local.pointer, PATH(ftw));
286
break;
287
case F_mime:
288
fp = sfopen(NiL, PATH(ftw), "r");
289
state.magicdisc.flags |= MAGIC_MIME;
290
v.string = magictype(state.magic, fp, PATH(ftw), st);
291
state.magicdisc.flags &= ~MAGIC_MIME;
292
if (fp)
293
sfclose(fp);
294
goto string;
295
case F_mode:
296
v.integer = st->st_mode;
297
break;
298
case F_mtime:
299
v.integer = st->st_mtime;
300
break;
301
case F_name:
302
v.string = ftw->name;
303
goto string;
304
case F_nlink:
305
v.integer = st->st_nlink;
306
break;
307
case F_path:
308
v.string = ftw->path;
309
goto string;
310
case F_perm:
311
v.integer = st->st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
312
break;
313
case F_rdev:
314
v.integer = idevice(st);
315
break;
316
case F_size:
317
v.integer = st->st_size;
318
break;
319
case F_status:
320
v.integer = ftw->status;
321
break;
322
case F_symlink:
323
if (!S_ISLNK(st->st_mode) || pathgetlink(PATH(ftw), text, sizeof(text)) < 0)
324
text[0] = 0;
325
v.string = text;
326
goto string;
327
case F_type:
328
if (S_ISREG(st->st_mode)) v.integer = C_REG;
329
else if (S_ISDIR(st->st_mode)) v.integer = C_DIR;
330
else if (S_ISLNK(st->st_mode)) v.integer = C_LNK;
331
else if (S_ISBLK(st->st_mode)) v.integer = C_BLK;
332
else if (S_ISCHR(st->st_mode)) v.integer = C_CHR;
333
else if (S_ISFIFO(st->st_mode)) v.integer = C_FIFO;
334
#ifdef S_ISCTG
335
else if (S_ISCTG(st->st_mode)) v.integer = C_CTG;
336
#endif
337
#ifdef S_ISSOCK
338
else if (S_ISSOCK(st->st_mode)) v.integer = C_SOCK;
339
#endif
340
#ifdef S_ISDOOR
341
else if (S_ISDOOR(st->st_mode)) v.integer = C_DOOR;
342
#endif
343
else v.integer = 0;
344
break;
345
case F_uid:
346
v.integer = st->st_uid;
347
break;
348
case F_uidok:
349
v.integer = !isdigit(*fmtuid(st->st_uid));
350
break;
351
case F_url:
352
v.string = fmturl(ftw->path ? ftw->path : ftw->name);
353
goto string;
354
case F_view:
355
v.integer = iview(st);
356
break;
357
case F_visit:
358
if (state.visitmem)
359
error(3, "%s: reference invalid when members declared", sym->name);
360
id.di[0] = st->st_dev;
361
id.di[1] = st->st_ino;
362
if (vp = (Visit_t*)dtmatch(state.vistab, &id))
363
v = vp->value[0];
364
else
365
v = exzero(INTEGER);
366
break;
367
case X_cmdarg:
368
cmdarg(state.cmd, ((Extype_t*)env)[0].string, strlen(((Extype_t*)env)[0].string));
369
v.integer = 1;
370
break;
371
case X_cmdflush:
372
cmdflush(state.cmd);
373
v.integer = 1;
374
break;
375
case X_sum:
376
sp = (Exsum_t*)node->local.pointer;
377
if (!sp->sum && !(sp->sum = sumopen(((Extype_t*)env)[0].string)))
378
error(ERROR_SYSTEM|3, "%s checksum initialization error", ((Extype_t*)env)[0].string);
379
ftw = (Ftw_t*)(((Extype_t*)env)[-1].string);
380
v.string = sum(sp, PATH(ftw));
381
break;
382
default:
383
switch (MEMINDEX(sym->index))
384
{
385
case F_local:
386
v = (lp = (Local_t*)ftw->local.pointer) ? lp->value[MEMOFFSET(sym->index)] : exzero(sym->type);
387
break;
388
case F_visit:
389
id.di[0] = st->st_dev;
390
id.di[1] = st->st_ino;
391
v = (vp = (Visit_t*)dtmatch(state.vistab, &id)) ? vp->value[MEMOFFSET(sym->index)] : exzero(sym->type);
392
break;
393
default:
394
error(3, "%s: invalid identifier reference [ index=%d memindex=%d memoffset=%d ]", sym->name, sym->index, MEMINDEX(sym->index), MEMOFFSET(sym->index));
395
break;
396
}
397
break;
398
}
399
return v;
400
string:
401
if (!state.compiled && v.string)
402
v.string = strdup(v.string);
403
return v;
404
}
405
406
/*
407
* initialize the visit table
408
*/
409
410
static void
411
initvisit(Exid_t* sym)
412
{
413
Dtdisc_t* disc;
414
415
if (!state.vistab)
416
{
417
if (!(disc = newof(0, Dtdisc_t, 1, 0)))
418
error(ERROR_SYSTEM|3, "out of space [visit table]");
419
disc->key = offsetof(Visit_t, id);
420
disc->size = sizeof(Fileid_t);
421
if (!(state.vistab = dtopen(disc, Dtset)))
422
error(3, "%s: cannot allocate file identifier hash table", sym->name);
423
}
424
}
425
426
/*
427
* sym referenced in expression
428
*/
429
430
static Extype_t
431
refval(Expr_t* pgm, Exnode_t* node, Exid_t* sym, Exref_t* ref, char* str, int elt, Exdisc_t* disc)
432
{
433
Ftw_t ftwbuf;
434
Extype_t v;
435
Exsum_t* sp;
436
char* m;
437
438
if (elt >= 0)
439
error(3, "%s: arrays not supported", sym->name);
440
if (str)
441
{
442
if (STAT(str, &ftwbuf.statb))
443
memzero(&ftwbuf.statb, sizeof(ftwbuf.statb));
444
return getval(pgm, node, sym, ref, &ftwbuf, elt, disc);
445
}
446
v = exzero(sym->type);
447
switch (sym->index)
448
{
449
case MEMBER:
450
while (ref)
451
{
452
switch (ref->symbol->index)
453
{
454
case F_parent:
455
break;
456
case F_local:
457
if (!ref->next)
458
{
459
sym->index = MEMMAKE(ref->symbol->index, state.localmem++);
460
break;
461
}
462
/*FALLTHROUGH*/
463
case F_visit:
464
if (!ref->next)
465
{
466
if (!state.vistab)
467
initvisit(sym);
468
sym->index = MEMMAKE(ref->symbol->index, state.visitmem++);
469
break;
470
}
471
/*FALLTHROUGH*/
472
default:
473
error(3, "invalid %s.%s reference", ref->symbol->name, sym->name);
474
break;
475
}
476
ref = ref->next;
477
}
478
break;
479
case C_AGAIN:
480
v.integer = FTW_AGAIN;
481
break;
482
case C_BLK:
483
case C_CHR:
484
case C_DIR:
485
case C_DOOR:
486
case C_FIFO:
487
case C_LNK:
488
case C_REG:
489
case C_SOCK:
490
v.integer = sym->index;
491
break;
492
case C_C:
493
v.integer = FTW_C;
494
break;
495
case C_D:
496
v.integer = FTW_D;
497
break;
498
case C_DC:
499
v.integer = FTW_DC;
500
break;
501
case C_DNR:
502
v.integer = FTW_DNR;
503
break;
504
case C_DNX:
505
v.integer = FTW_DNX;
506
break;
507
case C_DP:
508
v.integer = FTW_DP;
509
break;
510
case C_FOLLOW:
511
v.integer = FTW_FOLLOW;
512
break;
513
case C_NOPOST:
514
v.integer = FTW_NOPOST;
515
break;
516
case C_NR:
517
v.integer = FTW_NR;
518
break;
519
case C_NS:
520
v.integer = FTW_NS;
521
break;
522
case C_NX:
523
v.integer = FTW_NX;
524
break;
525
case C_SKIP:
526
v.integer = FTW_SKIP;
527
break;
528
case F_info:
529
state.info = 1;
530
break;
531
case F_magic:
532
case F_mime:
533
if (!state.magic)
534
{
535
state.magicdisc.version = MAGIC_VERSION;
536
state.magicdisc.flags = 0;
537
state.magicdisc.errorf = errorf;
538
if (!(state.magic = magicopen(&state.magicdisc)) || magicload(state.magic, NiL, 0))
539
error(3, "%s: cannot load magic file", MAGIC_FILE);
540
}
541
break;
542
case F_visit:
543
if (!state.vistab)
544
initvisit(sym);
545
break;
546
case F_atime:
547
case F_blksize:
548
case F_blocks:
549
case F_ctime:
550
case F_dev:
551
case F_fstype:
552
case F_gid:
553
case F_gidok:
554
case F_ino:
555
case F_mode:
556
case F_mtime:
557
case F_nlink:
558
case F_perm:
559
case F_rdev:
560
case F_size:
561
case F_symlink:
562
case F_type:
563
case F_uid:
564
case F_uidok:
565
state.ftwflags &= ~FTW_DELAY;
566
break;
567
case X_cmdarg:
568
state.cmdflags &= ~CMD_IMPLICIT;
569
break;
570
case F_checksum:
571
m = "ast4";
572
goto sum;
573
case F_md5sum:
574
m = "md5sum";
575
goto sum;
576
case X_sum:
577
m = 0;
578
sum:
579
if (!(sp = newof(0, Exsum_t, 1, 0)) || !(sp->buf = sfstropen()))
580
error(ERROR_SYSTEM|3, "out of space [sum]");
581
node->local.pointer = (char*)sp;
582
if (m && !(sp->sum = sumopen(m)))
583
error(ERROR_SYSTEM|3, "sum(\"%s\") initialization error", m);
584
break;
585
}
586
return v;
587
}
588
589
/*
590
* set value for symbol sym to val
591
*/
592
593
static int
594
setval(Expr_t* pgm, Exnode_t* node, Exid_t* sym, Exref_t* ref, void* env, int elt, Extype_t val, Exdisc_t* disc)
595
{
596
register Ftw_t* ftw;
597
Fileid_t id;
598
Visit_t* vp;
599
Local_t* lp;
600
601
NoP(pgm);
602
NoP(node);
603
NoP(disc);
604
if (elt >= 0)
605
error(3, "%s: arrays not supported", sym->name);
606
if (!(ftw = (Ftw_t*)env) || ref && !(ftw = deref(ftw, sym, ref))) return -1;
607
switch (sym->index)
608
{
609
case F_local:
610
if (state.localmem) error(3, "%s: reference invalid when members declared", sym->name);
611
else ftw->local.number = val.integer;
612
break;
613
case F_status:
614
ftw->status = val.integer;
615
break;
616
case F_visit:
617
if (state.visitmem)
618
error(3, "%s: reference invalid when members declared", sym->name);
619
id.di[0] = ftw->statb.st_dev;
620
id.di[1] = ftw->statb.st_ino;
621
if (!(vp = (Visit_t*)dtmatch(state.vistab, &id)))
622
{
623
if (!(vp = newof(0, Visit_t, 1, 0)))
624
error(ERROR_SYSTEM|3, "out of space [visit]");
625
vp->id = id;
626
dtinsert(state.vistab, vp);
627
}
628
vp->value[0] = val;
629
break;
630
default:
631
switch (MEMINDEX(sym->index))
632
{
633
case F_local:
634
if (!(lp = (Local_t*)ftw->local.pointer))
635
{
636
if (state.local)
637
{
638
lp = state.local;
639
state.local = state.local->next;
640
memzero(lp, sizeof(Local_t) + sizeof(Extype_t) * (state.localmem - 1));
641
}
642
else if (!(lp = newof(0, Local_t, 1, sizeof(Extype_t) * (state.localmem - 1))))
643
error(3, "out of space");
644
lp = (Local_t*)ftw->local.pointer;
645
}
646
lp->value[MEMOFFSET(sym->index)] = val;
647
break;
648
case F_visit:
649
id.di[0] = ftw->statb.st_dev;
650
id.di[1] = ftw->statb.st_ino;
651
if (!(vp = (Visit_t*)dtmatch(state.vistab, &id)))
652
{
653
if (!(vp = newof(0, Visit_t, 1, sizeof(Extype_t) * (state.visitmem - 1))))
654
error(3, "out of space [visit]");
655
vp->id = id;
656
dtinsert(state.vistab, vp);
657
}
658
vp->value[MEMOFFSET(sym->index)] = val;
659
break;
660
default:
661
return -1;
662
}
663
break;
664
}
665
return 0;
666
}
667
668
/*
669
* match str against pat
670
*/
671
672
static int
673
matchval(Expr_t* pgm, Exnode_t* xstr, const char* str, Exnode_t* xpat, const char* pat, void* env, Exdisc_t* disc)
674
{
675
return strgrpmatch(str, pat, NiL, 0, STR_MAXIMAL|STR_LEFT|STR_RIGHT|((Ftw_t*)env)->ignorecase);
676
}
677
678
/*
679
* convert operands
680
*/
681
682
static int
683
convert(Expr_t* prog, register Exnode_t* x, int type, register Exid_t* xref, int arg, Exdisc_t* disc)
684
{
685
register Sflong_t n;
686
time_t t;
687
char* s;
688
689
static char buf[64];
690
691
NoP(prog);
692
NoP(disc);
693
if (type < 0200)
694
{
695
if (x->type == FLOATING)
696
n = x->data.constant.value.floating;
697
else if (x->type == INTEGER)
698
n = x->data.constant.value.integer;
699
else switch (type)
700
{
701
case T_DATE:
702
n = tmdate(x->data.constant.value.string, &s, NiL);
703
if (*s)
704
goto ignored;
705
break;
706
case T_GID:
707
if ((n = strgid(x->data.constant.value.string)) < 0 && !arg)
708
error(1, "%s: %s not found", xref->name, x->data.constant.value.string);
709
break;
710
case T_MODE:
711
case T_PERM:
712
n = strperm(x->data.constant.value.string, &s, 0);
713
break;
714
case T_UID:
715
if ((n = struid(x->data.constant.value.string)) < 0 && !arg)
716
error(1, "%s: %s not found", xref->name, x->data.constant.value.string);
717
break;
718
}
719
x->data.constant.value.integer = n;
720
type = INTEGER;
721
}
722
else
723
{
724
n = x->data.constant.value.integer;
725
switch (type)
726
{
727
case FLOATING:
728
x->data.constant.value.floating = n;
729
break;
730
case STRING:
731
switch (x->type)
732
{
733
case T_DATE:
734
t = n;
735
tmfmt(s = buf, sizeof(buf), "%?%QL", &t);
736
break;
737
case T_GID:
738
s = fmtgid((gid_t)n);
739
break;
740
case T_MODE:
741
s = fmtmode((mode_t)n, 0);
742
break;
743
case T_PERM:
744
s = fmtmode((mode_t)n, 0) + 1;
745
break;
746
case T_UID:
747
s = fmtuid((uid_t)n);
748
break;
749
default:
750
sfsprintf(s = buf, sizeof(buf), "%ld", n);
751
break;
752
}
753
if (!state.compiled && s)
754
s = strdup(s);
755
if (!(x->data.constant.value.string = s))
756
return -1;
757
break;
758
}
759
}
760
x->type = type;
761
return 0;
762
ignored:
763
if (xref)
764
error(1, "%s: `%s' ignored in conversion", xref->name, s);
765
else
766
error(1, "`%s' ignored in conversion", s);
767
x->type = type;
768
return 0;
769
}
770
771
/*
772
* initialize the expression state
773
*/
774
775
static void
776
init(void)
777
{
778
if (!state.program)
779
{
780
state.expr.version = EX_VERSION;
781
state.expr.flags = EX_CHARSTRING|EX_FATAL;
782
state.expr.symbols = symbols;
783
state.expr.convertf = convert;
784
state.expr.errorf = errorf;
785
state.expr.getf = getval;
786
state.expr.reff = refval;
787
state.expr.setf = setval;
788
state.expr.matchf = matchval;
789
if (!(state.program = exopen(&state.expr)))
790
error(3, "expression allocation error");
791
}
792
}
793
794
/*
795
* compile the tw expression in s
796
*/
797
798
void
799
compile(char* s, int file)
800
{
801
Sfio_t* sp;
802
803
if (!state.program)
804
init();
805
state.compiled = 0;
806
if (file)
807
{
808
if (!(sp = sfopen(NiL, s, "r")))
809
error(3|ERROR_SYSTEM, "%s: cannot read", s);
810
else if (excomp(state.program, s, 1, NiL, sp))
811
error(3, "%s: expression compile error", s);
812
else
813
sfclose(sp);
814
}
815
else if (excomp(state.program, NiL, 0, s, NiL))
816
error(3, "expression compile error");
817
state.compiled = 1;
818
if (error_info.trace)
819
exdump(state.program, NiL, sfstdout);
820
}
821
822
/*
823
* evaluate x w.r.t. ftw
824
*/
825
826
long
827
eval(Exnode_t* x, Ftw_t* ftw)
828
{
829
Extype_t v;
830
831
v = exeval(state.program, x, ftw);
832
return v.integer;
833
}
834
835
/*
836
* return integer value for id
837
*/
838
839
long
840
getnum(Exid_t* sym, Ftw_t* ftw)
841
{
842
Extype_t v;
843
844
v = getval(NiL, NiL, sym, NiL, ftw, 0, NiL);
845
return v.integer;
846
}
847
848
/*
849
* sfkeyprintf() lookup
850
*/
851
852
static int
853
key(void* handle, register Sffmt_t* fp, const char* arg, char** ps, Sflong_t* pn)
854
{
855
Ftw_t* ftw = (Ftw_t*)handle;
856
Exid_t* sym;
857
Extype_t v;
858
859
if (!fp->t_str)
860
return 0;
861
if (!(sym = (Exid_t*)dtmatch(state.program->symbols, fp->t_str)))
862
{
863
error(3, "%s: unknown format key", fp->t_str);
864
return 0;
865
}
866
v = getval(NiL, NiL, sym, NiL, ftw, 0, NiL);
867
if ((sym->type & (F|I|S)) == S)
868
*ps = v.string;
869
else
870
*pn = v.integer;
871
return 1;
872
}
873
874
ssize_t
875
print(Sfio_t* sp, Ftw_t* ftw, const char* format)
876
{
877
if (!state.program)
878
{
879
init();
880
state.compiled = 1;
881
}
882
return sfkeyprintf(sp, ftw, format, key, NiL);
883
}
884
885