4
* grammar support routines
5
* stuffed in a header so exparse.y can work
6
* with both yacc and bison
7
* sometimes free stuff can cost a lot
10
#if defined(MINTOKEN) && !defined(_EXGRAM_H)
13
#if !defined(_EXPARSE_H)
20
#define exlex() extoken(expr.program)
22
#define ALLOCATE(p,x) (x*)exalloc(p,sizeof(x))
23
#define QUALIFY(r,s) ((r)&&(expr.program->disc->flags&EX_QUALIFY)?qualify(r,s):(s))
25
static int a2t[] = { 0, FLOATING, INTEGER, STRING };
26
static Switch_t swstate;
33
if (expr.program->disc->types)
34
return expr.program->disc->types[t&TMASK];
40
* allocate and initialize a new expression node in the current program
44
exnewnode(Expr_t* p, int op, int binary, int type, Exnode_t* left, Exnode_t* right)
48
x = ALLOCATE(p, Exnode_t);
54
x->data.operand.left = left;
55
x->data.operand.right = right;
60
* free node x and its children
64
exfreenode(Expr_t* p, register Exnode_t* x)
75
if (x->data.call.args)
76
exfreenode(p, x->data.call.args);
81
if (x->data.select.next)
82
exfreenode(p, x->data.select.next);
85
if (x->data.variable.index)
86
exfreenode(p, x->data.variable.index);
87
if (x->data.variable.symbol->local.pointer)
89
dtclose((Dt_t*)x->data.variable.symbol->local.pointer);
90
x->data.variable.symbol->local.pointer = 0;
94
if (x->data.generate.statement)
95
exfreenode(p, x->data.generate.statement);
98
rn = x->data.variable.reference;
104
if (x->data.variable.index)
105
exfreenode(p, x->data.variable.index);
109
if (x->data.print.descriptor)
110
exfreenode(p, x->data.print.descriptor);
111
pn = x->data.print.args;
114
for (i = 0; i < elementsof(pr->param) && pr->param[i]; i++)
115
exfreenode(p, pr->param[i]);
117
exfreenode(p, pr->arg);
123
if (x->data.operand.left)
124
exfreenode(p, x->data.operand.left);
125
if (x->data.operand.right)
126
exfreenode(p, x->data.operand.right);
134
* Create variable from s[idx].refs
135
* If s is DYNAMIC, refs is non-empty and dyna represents s[idx].
136
* The rightmost element in s[idx].refs becomes the dominant symbol,
137
* and the prefix gets stored in refs. (This format is used to simplify
141
makeVar (Expr_t* prog, Exid_t* s, Exnode_t* idx, Exnode_t* dyna, Exref_t* refs)
147
/* parse components */
150
sym = refs->next->symbol;
151
refs->next->symbol = refs->symbol;
153
else sym = refs->symbol;
159
if (sym->type) kind = sym->type;
162
nn = exnewnode(prog, ID, 0, kind, NiL, NiL);
163
nn->data.variable.symbol = sym;
164
nn->data.variable.reference = refs;
165
nn->data.variable.index = 0;
166
nn->data.variable.dyna = dyna;
167
if (!prog->disc->getf)
168
exerror("%s: identifier references not supported", sym->name);
169
else if (expr.program->disc->reff)
170
(*expr.program->disc->reff)(prog, nn, nn->data.variable.symbol, refs, NiL, EX_SCALAR, prog->disc);
179
static char* typename[] =
181
"external", "integer", "unsigned", "float", "string"
184
static int typecast[5][5] =
186
0, X2I, X2I, X2F, X2S,
189
F2X, F2I, F2I, 0, F2S,
190
S2X, S2I, S2I, S2F, 0
193
#define TYPEINDEX(t) (((t)>=INTEGER&&(t)<=STRING)?((t)-INTEGER+1):0)
194
#define TYPENAME(t) typename[TYPEINDEX(t)]
195
#define TYPECAST(f,t) typecast[TYPEINDEX(f)][TYPEINDEX(t)]
197
#define EXTERNAL(t) ((t)>=F2X)
200
excast(Expr_t* p, register Exnode_t* x, register int type, register Exnode_t* xref, int arg)
206
if (x && x->type != type && type && type != VOID)
213
if (!(t2t = TYPECAST(x->type, type)))
215
if (EXTERNAL(t2t) && !p->disc->convertf)
216
exerror("cannot cast %s to %s", TYPENAME(x->type), TYPENAME(type));
217
if (x->op != CONSTANT)
218
x = exnewnode(p, t2t, 0, type, x, xref);
227
if (xref && xref->op == ID)
229
if ((*p->disc->convertf)(p, x, type, xref->data.variable.symbol, arg, p->disc) < 0)
230
exerror("%s: cannot cast constant %s to %s", xref->data.variable.symbol->name, TYPENAME(x->type), TYPENAME(type));
232
else if ((*p->disc->convertf)(p, x, type, NiL, arg, p->disc) < 0)
233
exerror("cannot cast constant %s to %s", TYPENAME(x->type), TYPENAME(type));
236
x->data.constant.value.integer = x->data.constant.value.floating;
239
sfprintf(p->tmp, "%g", x->data.constant.value.floating);
240
x->data.constant.value.string = vmstrdup(p->vm, sfstruse(p->tmp));
243
x->data.constant.value.floating = x->data.constant.value.integer;
246
sfprintf(p->tmp, "%I*d", sizeof(x->data.constant.value.integer), x->data.constant.value.integer);
247
x->data.constant.value.string = vmstrdup(p->vm, sfstruse(p->tmp));
250
x->data.constant.value.integer = strtod(x->data.constant.value.string, &e);
252
x->data.constant.value.floating = *x->data.constant.value.string != 0;
255
s = x->data.constant.value.string;
256
x->data.constant.value.integer = strtoll(s, &e, 0);
258
x->data.constant.value.integer = *s != 0;
261
exerror("internal error: %d: unknown cast op", t2t);
270
* force ref . sym qualification
274
qualify(register Exref_t* ref, register Exid_t* sym)
281
sfprintf(expr.program->tmp, "%s.%s", ref->symbol->name, sym->name);
282
s = sfstruse(expr.program->tmp);
283
if (!(x = (Exid_t*)dtmatch(expr.program->symbols, s)))
285
if (x = newof(0, Exid_t, 1, strlen(s) - EX_NAMELEN + 1))
287
memcpy(x, sym, sizeof(Exid_t) - EX_NAMELEN);
289
dtinsert(expr.program->symbols, x);
293
exerror("out of space [qualify]");
301
* check function call arg types and count
302
* return function identifier node
306
call(Exref_t* ref, register Exid_t* fun, register Exnode_t* args)
313
x = exnewnode(expr.program, ID, 0, 0, NiL, NiL);
315
x->data.variable.symbol = fun = QUALIFY(ref, fun);
316
x->data.variable.reference = ref;
323
exerror("%s: not enough args", fun->name);
327
if (type != args->data.operand.left->type)
328
args->data.operand.left = excast(expr.program, args->data.operand.left, type, x, num);
329
args = args->data.operand.right;
333
exerror("%s: too many args", fun->name);
338
* precompile a printf call
342
preprint(register Exnode_t* args)
355
if (!args || args->data.operand.left->type != STRING)
356
exerror("format string argument expected");
357
if (args->data.operand.left->op != CONSTANT)
359
x = ALLOCATE(expr.program, Print_t);
360
memzero(x, sizeof(*x));
364
f = args->data.operand.left->data.constant.value.string;
365
args = args->data.operand.right;
368
sfputc(expr.program->tmp, *s);
372
exerror("%s: trailing %% in printf format", f);
380
q = ALLOCATE(expr.program, Print_t);
386
memzero(x, sizeof(*x));
396
exerror("unterminated %%... in printf format");
399
if (i >= elementsof(x->param))
402
exerror("printf format %s has too many * arguments", f);
408
exerror("printf format %s * argument expected", f);
411
x->param[i++] = args->data.operand.left;
412
args = args->data.operand.right;
418
sfputc(expr.program->tmp, c);
446
exerror("short printf formats not supported");
466
sfputc(expr.program->tmp, c);
469
sfputc(expr.program->tmp, c);
477
exerror("%s: trailing %% in printf format", f);
486
sfputc(expr.program->tmp, *s);
491
exerror("%s printf argument expected", f);
494
x->arg = args->data.operand.left;
498
if (x->arg->type != FLOATING)
499
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);
503
if (!INTEGRAL(x->arg->type))
504
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);
508
if (x->arg->type != STRING)
510
if (x->arg->op == CONSTANT && x->arg->data.constant.reference && expr.program->disc->convertf)
512
if ((*expr.program->disc->convertf)(expr.program, x->arg, STRING, x->arg->data.constant.reference, 0, expr.program->disc) < 0)
513
exerror("cannot convert string printf argument");
514
else x->arg->data.constant.value.string = vmstrdup(expr.program->vm, x->arg->data.constant.value.string);
516
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)
517
exerror("string printf argument expected");
519
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);
523
args = args->data.operand.right;
525
x->format = vmstrdup(expr.program->vm, sfstruse(expr.program->tmp));
531
exerror("too many printf arguments");
533
sfstrset(expr.program->tmp, 0);
538
* push a new input stream and program
542
expush(Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
544
register Exinput_t* in;
548
if (!(in = newof(0, Exinput_t, 1, 0)))
550
exerror("out of space [push]");
554
p->input = &expr.null;
555
if (!(in->bp = in->sp = (char*)sp))
561
if (!(s = pathfind(name, p->disc->lib, p->disc->type, buf, sizeof(buf))) || !(in->fp = sfopen(NiL, s, "r")))
563
exerror("%s: file not found", name);
564
in->bp = in->sp = "";
568
name = (const char*)vmstrdup(p->vm, s);
574
if (!(in->next = p->input)->next)
577
if (!(p->disc->flags & EX_INTERACTIVE))
580
error_info.line = line;
582
else if (!error_info.line)
586
error_info.line = line;
590
in->file = error_info.file;
592
error_info.file = (char*)name;
593
in->line = error_info.line;
595
in->unit = !name && !line;
596
p->program = expr.program;
602
* pop the current input stream
606
expop(register Expr_t* p)
609
register Exinput_t* in;
611
if (!(in = p->input) || !in->next || in->unit)
614
exerror("unbalanced quote or nesting construct");
615
error_info.file = in->file;
617
error_info.line = in->line;
620
if (p->errors && in->fp && p->linep != p->line)
621
while ((c = sfgetc(in->fp)) != EOF)
627
if (!(p->disc->flags & EX_INTERACTIVE))
628
error_info.line = in->line;
630
if (in->fp && in->close)
638
expr.program = p->program;
643
* compile the expression in [sf]p
647
excomp(register Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
658
else if (expush(p, name, line, sp, fp))
660
else p->input->unit = line >= 0;
673
exclose(register Expr_t* p, int all)
676
register Exinput_t* in;
682
for (i = 3; i < elementsof(p->file); i++)
693
while (in = p->input)
697
if (in->fp && in->close)
699
if (p->input = in->next)