Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libexpr/exgram.h
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-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
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* grammar support routines
24
* stuffed in a header so exparse.y can work
25
* with both yacc and bison
26
* sometimes free stuff can cost a lot
27
*/
28
29
#if !defined(_EXGRAM_H) && ( defined(MINTOKEN) || defined(YYTOKENTYPE) )
30
#define _EXGRAM_H
31
32
#if !defined(_EXPARSE_H)
33
#define _EXPARSE_H
34
#endif
35
36
#include "exlib.h"
37
38
#define exlex() extoken(expr.program)
39
40
#define ALLOCATE(p,x) (x*)exalloc(p,sizeof(x))
41
#define QUALIFY(r,s) ((r)&&(expr.program->disc->flags&EX_QUALIFY)?qualify(r,s):(s))
42
43
static int a2t[] = { 0, FLOATING, INTEGER, STRING };
44
static Switch_t swstate;
45
46
Exstate_t expr;
47
48
/*
49
* allocate and initialize a new expression node in the current program
50
*/
51
52
Exnode_t*
53
exnewnode(Expr_t* p, int op, int binary, int type, Exnode_t* left, Exnode_t* right)
54
{
55
register Exnode_t* x;
56
57
x = ALLOCATE(p, Exnode_t);
58
x->op = op;
59
x->type = type;
60
x->binary = binary;
61
x->local.number = 0;
62
x->local.pointer = 0;
63
x->data.operand.left = left;
64
x->data.operand.right = right;
65
return x;
66
}
67
68
/*
69
* free node x and its children
70
*/
71
72
void
73
exfreenode(Expr_t* p, register Exnode_t* x)
74
{
75
register Print_t* pr;
76
register Exref_t* r;
77
Print_t* pn;
78
Exref_t* rn;
79
int i;
80
81
switch (x->op)
82
{
83
case CALL:
84
if (x->data.call.args)
85
exfreenode(p, x->data.call.args);
86
break;
87
case CONSTANT:
88
break;
89
case DEFAULT:
90
if (x->data.select.next)
91
exfreenode(p, x->data.select.next);
92
break;
93
case DYNAMIC:
94
if (x->data.variable.index)
95
exfreenode(p, x->data.variable.index);
96
if (x->data.variable.symbol->local.pointer)
97
{
98
dtclose((Dt_t*)x->data.variable.symbol->local.pointer);
99
x->data.variable.symbol->local.pointer = 0;
100
}
101
break;
102
case ITERATE:
103
if (x->data.generate.statement)
104
exfreenode(p, x->data.generate.statement);
105
break;
106
case ID:
107
rn = x->data.variable.reference;
108
while (r = rn)
109
{
110
rn = r->next;
111
vmfree(p->vm, r);
112
}
113
if (x->data.variable.index)
114
exfreenode(p, x->data.variable.index);
115
break;
116
case PRINTF:
117
case SPRINTF:
118
if (x->data.print.descriptor)
119
exfreenode(p, x->data.print.descriptor);
120
pn = x->data.print.args;
121
while (pr = pn)
122
{
123
for (i = 0; i < elementsof(pr->param) && pr->param[i]; i++)
124
exfreenode(p, pr->param[i]);
125
if (pr->arg)
126
exfreenode(p, pr->arg);
127
pn = pr->next;
128
vmfree(p->vm, pr);
129
}
130
break;
131
default:
132
if (x->data.operand.left)
133
exfreenode(p, x->data.operand.left);
134
if (x->data.operand.right)
135
exfreenode(p, x->data.operand.right);
136
break;
137
}
138
vmfree(p->vm, x);
139
}
140
141
/*
142
* cast x to type
143
*/
144
145
static char* typename[] =
146
{
147
"external", "integer", "unsigned", "float", "string"
148
};
149
150
static int typecast[5][5] =
151
{
152
0, X2I, X2I, X2F, X2S,
153
I2X, 0, 0, I2F, I2S,
154
I2X, 0, 0, I2F, I2S,
155
F2X, F2I, F2I, 0, F2S,
156
S2X, S2I, S2I, S2F, 0
157
};
158
159
#define TYPEINDEX(t) (((t)>=INTEGER&&(t)<=STRING)?((t)-INTEGER+1):0)
160
#define TYPENAME(t) typename[TYPEINDEX(t)]
161
#define TYPECAST(f,t) typecast[TYPEINDEX(f)][TYPEINDEX(t)]
162
163
#define EXTERNAL(t) ((t)>=F2X)
164
165
Exnode_t*
166
excast(Expr_t* p, register Exnode_t* x, register int type, register Exnode_t* xref, int arg)
167
{
168
register int t2t;
169
char* s;
170
char* e;
171
172
if (x && x->type != type && type && type != VOID)
173
{
174
if (!x->type)
175
{
176
x->type = type;
177
return x;
178
}
179
if (!(t2t = TYPECAST(x->type, type)))
180
return x;
181
if (EXTERNAL(t2t) && !p->disc->convertf)
182
exerror("cannot cast %s to %s", TYPENAME(x->type), TYPENAME(type));
183
if (x->op != CONSTANT)
184
x = exnewnode(p, t2t, 0, type, x, xref);
185
else switch (t2t)
186
{
187
case F2X:
188
case I2X:
189
case S2X:
190
case X2F:
191
case X2I:
192
case X2S:
193
if (xref && xref->op == ID)
194
{
195
if ((*p->disc->convertf)(p, x, type, xref->data.variable.symbol, arg, p->disc) < 0)
196
exerror("%s: cannot cast constant %s to %s", xref->data.variable.symbol->name, TYPENAME(x->type), TYPENAME(type));
197
}
198
else if ((*p->disc->convertf)(p, x, type, NiL, arg, p->disc) < 0)
199
exerror("cannot cast constant %s to %s", TYPENAME(x->type), TYPENAME(type));
200
break;
201
case F2I:
202
x->data.constant.value.integer = x->data.constant.value.floating;
203
break;
204
case F2S:
205
sfprintf(p->tmp, "%g", x->data.constant.value.floating);
206
x->data.constant.value.string = exstash(p->tmp, p->vm);
207
break;
208
case I2F:
209
x->data.constant.value.floating = x->data.constant.value.integer;
210
break;
211
case I2S:
212
sfprintf(p->tmp, "%I*d", sizeof(x->data.constant.value.integer), x->data.constant.value.integer);
213
x->data.constant.value.string = exstash(p->tmp, p->vm);
214
break;
215
case S2F:
216
x->data.constant.value.integer = strtod(x->data.constant.value.string, &e);
217
if (*e)
218
x->data.constant.value.floating = *x->data.constant.value.string != 0;
219
break;
220
case S2I:
221
s = x->data.constant.value.string;
222
x->data.constant.value.integer = strtoll(s, &e, 0);
223
if (*e)
224
x->data.constant.value.integer = *s != 0;
225
break;
226
default:
227
exerror("internal error: %d: unknown cast op", t2t);
228
break;
229
}
230
x->type = type;
231
}
232
return x;
233
}
234
235
#if 0
236
237
/*
238
* convert value v from type from to type to
239
* string data placed in buf
240
*/
241
242
Extype_t
243
exconvert(Expr_t* p, Extype_t v, int from, int to, char* buf, size_t size)
244
{
245
register int t2t;
246
int n;
247
Exnode_t tmp;
248
249
if (from && (t2t = TYPECAST(from, to)))
250
{
251
if (EXTERNAL(t2t) && !p->disc->convertf)
252
exerror("cannot cast %s to %s", TYPENAME(from), TYPENAME(to));
253
switch (t2t)
254
{
255
case F2X:
256
case I2X:
257
case S2X:
258
case X2F:
259
case X2I:
260
case X2S:
261
tmp.type = from;
262
tmp.name = "*INTERNAL*";
263
tmp.data.constant.value = v;
264
if ((*p->disc->convertf)(p, &tmp, to, NiL, -1, p->disc) < 0)
265
exerror("cannot convert %s to %s", TYPENAME(from), TYPENAME(to));
266
if (t2t == X2S)
267
{
268
n = strlen(tmp.data.constant.value.string);
269
if (n >= size)
270
n = size - 1;
271
memcpy(buf, tmp.data.constant.value.string, n);
272
buf[n] = 0;
273
vmfree(p->vm, tmp.data.constant.value.string);
274
tmp.data.constant.value.string = buf;
275
}
276
return tmp.data.constant.value;
277
case F2I:
278
v.integer = (type == UNSIGNED) ? (Sfulong_t)v.floating : v.floating;
279
break;
280
case F2S:
281
sfsprintf(buf, size, "%g", v.floating);
282
v.string = buf;
283
break;
284
case I2F:
285
v.floating = (from == UNSIGNED) ? (Sfulong_t)v.integer : v.integer;
286
break;
287
case I2S:
288
sfsprintf(buf, size, "%I*d", sizeof(v.integer), v.integer);
289
v.string = buf;
290
break;
291
case S2F:
292
v.floating = *v.string != 0;
293
break;
294
case S2I:
295
v.integer = *v.string != 0;
296
break;
297
default:
298
exerror("internal error: %d: unknown conversion op", t2t);
299
break;
300
}
301
}
302
return v;
303
}
304
305
#endif
306
307
/*
308
* force ref . sym qualification
309
*/
310
311
static Exid_t*
312
qualify(register Exref_t* ref, register Exid_t* sym)
313
{
314
register Exid_t* x;
315
char* s;
316
317
while (ref->next)
318
ref = ref->next;
319
sfprintf(expr.program->tmp, "%s.%s", ref->symbol->name, sym->name);
320
s = exstash(expr.program->tmp, NiL);
321
if (!(x = (Exid_t*)dtmatch(expr.program->symbols, s)))
322
{
323
if (x = newof(0, Exid_t, 1, strlen(s) - EX_NAMELEN + 1))
324
{
325
memcpy(x, sym, sizeof(Exid_t) - EX_NAMELEN);
326
strcpy(x->name, s);
327
dtinsert(expr.program->symbols, x);
328
}
329
else
330
{
331
exnospace();
332
x = sym;
333
}
334
}
335
return x;
336
}
337
338
/*
339
* check function call arg types and count
340
* return function identifier node
341
*/
342
343
static Exnode_t*
344
call(Exref_t* ref, register Exid_t* fun, register Exnode_t* args)
345
{
346
register int t;
347
register int type;
348
Exnode_t* x;
349
int num;
350
351
x = exnewnode(expr.program, ID, 0, 0, NiL, NiL);
352
t = fun->type;
353
x->data.variable.symbol = fun = QUALIFY(ref, fun);
354
x->data.variable.reference = ref;
355
num = 0;
356
N(t);
357
while (type = T(t))
358
{
359
if (!args)
360
{
361
exerror("%s: not enough args", fun->name);
362
return args;
363
}
364
num++;
365
if (type != args->data.operand.left->type)
366
args->data.operand.left = excast(expr.program, args->data.operand.left, type, NiL, num);
367
args = args->data.operand.right;
368
N(t);
369
}
370
if (args)
371
exerror("%s: too many args", fun->name);
372
return x;
373
}
374
375
/*
376
* precompile a printf/scanf call
377
*/
378
379
static Print_t*
380
preprint(register Exnode_t* args)
381
{
382
register Print_t* x;
383
register char* s;
384
register int c;
385
int t;
386
int i;
387
int n;
388
char* e;
389
char* f;
390
Print_t* p;
391
Print_t* q;
392
393
if (!args || args->data.operand.left->type != STRING)
394
exerror("format string argument expected");
395
if (args->data.operand.left->op != CONSTANT)
396
{
397
x = ALLOCATE(expr.program, Print_t);
398
memzero(x, sizeof(*x));
399
x->arg = args;
400
return x;
401
}
402
f = args->data.operand.left->data.constant.value.string;
403
args = args->data.operand.right;
404
for (s = f; *s; s++)
405
{
406
sfputc(expr.program->tmp, *s);
407
if (*s == '%')
408
{
409
if (!*++s)
410
exerror("%s: trailing %% in format", f);
411
if (*s != '%')
412
break;
413
if (args)
414
sfputc(expr.program->tmp, '%');
415
}
416
}
417
x = 0;
418
for (;;)
419
{
420
q = ALLOCATE(expr.program, Print_t);
421
if (x)
422
x->next = q;
423
else
424
p = q;
425
x = q;
426
memzero(x, sizeof(*x));
427
if (*s)
428
{
429
i = 0;
430
t = INTEGER;
431
for (;;)
432
{
433
switch (c = *s++)
434
{
435
case 0:
436
exerror("unterminated %%... in format");
437
goto done;
438
case '*':
439
if (i >= elementsof(x->param))
440
{
441
*s = 0;
442
exerror("format %s has too many * arguments", f);
443
goto done;
444
}
445
if (!args)
446
{
447
*s = 0;
448
exerror("format %s * argument expected", f);
449
goto done;
450
}
451
x->param[i++] = args->data.operand.left;
452
args = args->data.operand.right;
453
break;
454
case '(':
455
n = 1;
456
for (;;)
457
{
458
sfputc(expr.program->tmp, c);
459
switch (c = *s++)
460
{
461
case 0:
462
s--;
463
break;
464
case '(':
465
n++;
466
continue;
467
case ')':
468
if (--n <= 0)
469
break;
470
continue;
471
default:
472
continue;
473
}
474
break;
475
}
476
break;
477
case 'c':
478
case 'd':
479
goto specified;
480
case 'e':
481
case 'f':
482
case 'g':
483
t = FLOATING;
484
goto specified;
485
case 'h':
486
exerror("short formats not supported");
487
goto done;
488
case 'l':
489
t = INTEGER;
490
break;
491
case 'o':
492
case 'u':
493
case 'x':
494
case 'T':
495
t = UNSIGNED;
496
goto specified;
497
case 's':
498
case 'S':
499
t = STRING;
500
goto specified;
501
case '[':
502
n = sfstrtell(expr.program->tmp);
503
sfputc(expr.program->tmp, c);
504
e = s;
505
c = *s++;
506
while (c)
507
{
508
sfputc(expr.program->tmp, c);
509
if ((c = *s++) == ']')
510
{
511
t = STRING;
512
goto specified;
513
}
514
}
515
s = e;
516
sfstrseek(expr.program->tmp, n, SEEK_SET);
517
break;
518
default:
519
if (isalpha(c))
520
goto specified;
521
break;
522
}
523
sfputc(expr.program->tmp, c);
524
}
525
specified:
526
sfputc(expr.program->tmp, c);
527
for (e = s; *s; s++)
528
{
529
if (*s == '%')
530
{
531
if (!*++s)
532
{
533
*e = 0;
534
exerror("%s: trailing %% in format", f);
535
goto done;
536
}
537
if (*s != '%')
538
{
539
s--;
540
break;
541
}
542
}
543
sfputc(expr.program->tmp, *s);
544
}
545
if (!args)
546
{
547
*e = 0;
548
exerror("%s format argument expected", f);
549
goto done;
550
}
551
x->arg = args->data.operand.left;
552
switch (t)
553
{
554
case FLOATING:
555
if (x->arg->type != FLOATING)
556
x->arg = exnewnode(expr.program, x->arg->type == STRING ? S2F : INTEGRAL(x->arg->type) ? I2F : X2F, 0, FLOATING, x->arg, x->arg->op == ID ? x->arg : (Exnode_t*)0);
557
break;
558
case INTEGER:
559
case UNSIGNED:
560
if (!INTEGRAL(x->arg->type))
561
x->arg = exnewnode(expr.program, x->arg->type == STRING ? S2I : x->arg->type == FLOATING ? F2I : X2I, 0, INTEGER, x->arg, x->arg->op == ID ? x->arg : (Exnode_t*)0);
562
x->arg->type = t;
563
break;
564
case STRING:
565
if (x->arg->type != STRING)
566
{
567
if (x->arg->op == CONSTANT && x->arg->data.constant.reference && expr.program->disc->convertf)
568
{
569
if ((*expr.program->disc->convertf)(expr.program, x->arg, STRING, x->arg->data.constant.reference, 0, expr.program->disc) < 0)
570
exerror("cannot convert string format argument");
571
else x->arg->data.constant.value.string = vmstrdup(expr.program->vm, x->arg->data.constant.value.string);
572
}
573
else if (!expr.program->disc->convertf || x->arg->op != ID && x->arg->op != DYNAMIC && x->arg->op != F2X && x->arg->op != I2X && x->arg->op != S2X)
574
exerror("string format argument expected");
575
else
576
x->arg = exnewnode(expr.program, x->arg->type == FLOATING ? F2S : INTEGRAL(x->arg->type) ? I2S : X2S, 0, STRING, x->arg, x->arg->op == ID ? x->arg : (Exnode_t*)0);
577
}
578
break;
579
}
580
args = args->data.operand.right;
581
}
582
x->format = exstash(expr.program->tmp, expr.program->vm);
583
if (!*s)
584
break;
585
f = s;
586
}
587
if (args)
588
exerror("too many format arguments");
589
done:
590
sfstrseek(expr.program->tmp, 0, SEEK_SET);
591
return p;
592
}
593
594
/*
595
* push a new input stream and program
596
*/
597
598
int
599
expush(Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
600
{
601
register Exinput_t* in;
602
register char* s;
603
char buf[PATH_MAX];
604
605
if (!(in = newof(0, Exinput_t, 1, 0)))
606
{
607
exnospace();
608
return -1;
609
}
610
if (!p->input)
611
p->input = &expr.null;
612
if (!(in->bp = in->sp = (char*)sp))
613
{
614
if (in->fp = fp)
615
in->close = 0;
616
else if (name)
617
{
618
if (!(s = pathfind(name, p->disc->lib, p->disc->type, buf, sizeof(buf))) || !(in->fp = sfopen(NiL, s, "r")))
619
{
620
exerror("%s: file not found", name);
621
in->bp = in->sp = "";
622
}
623
else
624
{
625
name = (const char*)vmstrdup(p->vm, s);
626
in->close = 1;
627
}
628
}
629
}
630
else in->fp = 0;
631
if (!(in->next = p->input)->next)
632
{
633
p->errors = 0;
634
if (!(p->disc->flags & EX_INTERACTIVE))
635
{
636
if (line >= 0)
637
error_info.line = line;
638
}
639
else if (!error_info.line)
640
error_info.line = 1;
641
}
642
else if (line >= 0)
643
error_info.line = line;
644
setcontext(p);
645
p->eof = 0;
646
p->input = in;
647
in->file = error_info.file;
648
if (line >= 0)
649
error_info.file = (char*)name;
650
in->line = error_info.line;
651
in->nesting = 0;
652
in->unit = !name && !line;
653
p->program = expr.program;
654
expr.program = p;
655
return 0;
656
}
657
658
/*
659
* pop the current input stream
660
*/
661
662
int
663
expop(register Expr_t* p)
664
{
665
register int c;
666
register Exinput_t* in;
667
668
if (!(in = p->input) || !in->next || in->unit)
669
return -1;
670
if (in->nesting)
671
exerror("unbalanced quote or nesting construct");
672
error_info.file = in->file;
673
if (in->next->next)
674
error_info.line = in->line;
675
else
676
{
677
if (p->errors && in->fp && p->linep != p->line)
678
while ((c = sfgetc(in->fp)) != EOF)
679
if (c == '\n')
680
{
681
error_info.line++;
682
break;
683
}
684
if (!(p->disc->flags & EX_INTERACTIVE))
685
error_info.line = in->line;
686
}
687
if (in->fp && in->close)
688
sfclose(in->fp);
689
if (in->pushback)
690
free(in->pushback);
691
p->input = in->next;
692
free(in);
693
setcontext(p);
694
if (p->program)
695
expr.program = p->program;
696
return 0;
697
}
698
699
/*
700
* compile the expression in [sf]p
701
*/
702
703
int
704
excomp(register Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
705
{
706
Exid_t* v;
707
int eof;
708
709
p->more = 0;
710
eof = p->eof;
711
if (!sp && !fp)
712
{
713
if (!p->input)
714
return -1;
715
}
716
else if (expush(p, name, line, sp, fp))
717
return -1;
718
else
719
p->input->unit = line >= 0;
720
exparse();
721
p->input->unit = 0;
722
expop(p);
723
p->eof = eof;
724
if (expr.statics)
725
{
726
for (v = (Exid_t*)dtfirst(p->symbols); v; v = (Exid_t*)dtnext(p->symbols, v))
727
if (v->isstatic)
728
{
729
dtdelete(p->symbols, v);
730
if (!--expr.statics)
731
break;
732
}
733
expr.statics = 0;
734
}
735
return 0;
736
}
737
738
/*
739
* free the program p
740
*/
741
742
void
743
exclose(register Expr_t* p, int all)
744
{
745
register int i;
746
register Exinput_t* in;
747
748
if (p)
749
{
750
if (all)
751
{
752
for (i = 3; i < elementsof(p->file); i++)
753
if (p->file[i])
754
sfclose(p->file[i]);
755
if (p->vm)
756
vmclose(p->vm);
757
if (p->ve)
758
vmclose(p->ve);
759
if (p->symbols)
760
dtclose(p->symbols);
761
if (p->tmp)
762
sfclose(p->tmp);
763
while (in = p->input)
764
{
765
if (in->pushback)
766
free(in->pushback);
767
if (in->fp && in->close)
768
sfclose(in->fp);
769
if (p->input = in->next)
770
free(in);
771
}
772
free(p);
773
}
774
else
775
{
776
vmclear(p->ve);
777
p->main.value = 0;
778
}
779
}
780
}
781
782
#endif
783
784