1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
4 **********/
5
6 /*
7 * A simple operator-precedence parser for algebraic expressions.
8 * This also handles relational and logical expressions.
9 */
10
11 #include "ngspice/ngspice.h"
12 #include "ngspice/bool.h"
13 #include "ngspice/fteparse.h"
14 #include "ngspice/fteext.h"
15 #include "ngspice/sim.h"
16
17 #include "evaluate.h"
18 #include "parse.h"
19 #include "parse-bison.h"
20 #include "parse-bison-y.h"
21
22
23 static bool checkvalid(struct pnode *pn);
24
25 #ifdef OLD_BISON
26 extern int PPparse(char **, struct pnode **);
27 #endif
28
29 void db_print_pnode_tree(struct pnode *p, char *print);
30
31
ft_getpnames_from_string(const char * sz,bool check)32 struct pnode *ft_getpnames_from_string(const char *sz, bool check)
33 {
34 struct pnode *pn;
35
36 /* The first argument to PPparse is not const char **, but it does not
37 * appear to modify the string that is being parsed */
38 if (PPparse((char **) &sz, &pn) != 0) {
39 return (struct pnode *) NULL;
40 }
41
42 /* If validation is requested, do it and return NULL on failure. The
43 * structure must also be freed if the check fails since it is not
44 * being returned. */
45 if (check && !checkvalid(pn)) {
46 free_pnode(pn);
47 return (struct pnode *) NULL;
48 }
49
50 return pn;
51 } /* end of function ft_getpnames_from_string */
52
53
54
55 struct pnode *
ft_getpnames(const wordlist * wl,bool check)56 ft_getpnames(const wordlist *wl, bool check)
57 {
58 /* Validate input */
59 if (!wl) {
60 (void) fprintf(cp_err, "Warning: NULL arithmetic expression\n");
61 return (struct pnode *) NULL;
62 }
63
64 /* Convert the list to a string, then parse the string */
65 const char * const sz = wl_flatten(wl);
66 struct pnode * const pn = ft_getpnames_from_string(sz, check);
67 txfree((void *) sz);
68
69 return pn; /* Return the parsed result */
70 } /* end of function ft_getpnames */
71
72
73
74 /* See if there are any variables around which have length 0 and are
75 * not named 'list'. There should really be another flag for this...
76 */
77
78 static bool
checkvalid(struct pnode * pn)79 checkvalid(struct pnode *pn)
80 {
81 while (pn) {
82 if (pn->pn_value) {
83 if ((pn->pn_value->v_length == 0) &&
84 !eq(pn->pn_value->v_name, "list")) {
85 if (eq(pn->pn_value->v_name, "all"))
86 fprintf(cp_err,
87 "Error: %s: no matching vectors.\n",
88 pn->pn_value->v_name);
89 else
90 fprintf(cp_err,
91 "Error(parse.c--checkvalid): %s: zero length vector.\n",
92 pn->pn_value->v_name);
93 return (FALSE);
94 }
95 } else if (pn->pn_func || (pn->pn_op && (pn->pn_op->op_arity == 1))) {
96 if (!checkvalid(pn->pn_left))
97 return (FALSE);
98 } else if (pn->pn_op && (pn->pn_op->op_arity == 2)) {
99 if (!checkvalid(pn->pn_left))
100 return (FALSE);
101 if (!checkvalid(pn->pn_right))
102 return (FALSE);
103 } else {
104 fprintf(cp_err,
105 "checkvalid: Internal Error: bad node\n");
106 }
107 pn = pn->pn_next;
108 }
109 return (TRUE);
110 }
111
112
113 /* Some auxiliary functions for building the parse tree. */
114
115 static struct op ops[] = {
116 { PT_OP_PLUS, "+", 2, {(void(*)(void)) op_plus} },
117 { PT_OP_MINUS, "-", 2, {(void(*)(void)) op_minus} },
118 { PT_OP_TIMES, "*", 2, {(void(*)(void)) op_times} },
119 { PT_OP_MOD, "%", 2, {(void(*)(void)) op_mod} },
120 { PT_OP_DIVIDE, "/", 2, {(void(*)(void)) op_divide} },
121 { PT_OP_COMMA, ",", 2, {(void(*)(void)) op_comma} },
122 { PT_OP_POWER, "^", 2, {(void(*)(void)) op_power} },
123 { PT_OP_EQ, "=", 2, {(void(*)(void)) op_eq} },
124 { PT_OP_GT, ">", 2, {(void(*)(void)) op_gt} },
125 { PT_OP_LT, "<", 2, {(void(*)(void)) op_lt} },
126 { PT_OP_GE, ">=", 2, {(void(*)(void)) op_ge} },
127 { PT_OP_LE, "<=", 2, {(void(*)(void)) op_le} },
128 { PT_OP_NE, "<>", 2, {(void(*)(void)) op_ne} },
129 { PT_OP_AND, "&", 2, {(void(*)(void)) op_and} },
130 { PT_OP_OR, "|", 2, {(void(*)(void)) op_or} },
131 { PT_OP_INDX, "[", 2, {(void(*)(void)) op_ind} },
132 { PT_OP_RANGE, "[[", 2, {(void(*)(void)) op_range} },
133 { PT_OP_TERNARY, "?:", 2, {NULL} },
134 { 0, NULL, 0, {NULL} }
135 };
136
137
138 static struct op uops[] = {
139 { PT_OP_UMINUS, "-", 1, {(void(*)(void)) op_uminus} },
140 { PT_OP_NOT, "~", 1, {(void(*)(void)) op_not} },
141 { 0, NULL, 0, {NULL} }
142 };
143
144
145 /* We have 'v' declared as a function, because if we don't then the defines
146 * we do for vm(), etc won't work. This is caught in evaluate(). Bad kludge.
147 */
148
149 typedef void* cx_function_t(void*, short int, int, int*, short int*);
150
151 struct func ft_funcs[] = {
152 { "mag", cx_mag },
153 { "magnitude", cx_mag },
154 { "cph", cx_cph }, /* SJdV */
155 { "cphase", cx_cph }, /* SJdV Continious phase*/
156 { "unwrap", cx_unwrap },
157 { "ph", cx_ph },
158 { "phase", cx_ph },
159 { "j", cx_j },
160 { "real", cx_real },
161 { "re", cx_real },
162 { "imag", cx_imag },
163 { "im", cx_imag },
164 { "conj", cx_conj },
165 { "db", cx_db },
166 { "log", cx_log },
167 { "log10", cx_log10 },
168 { "ln", cx_log },
169 { "exp", cx_exp },
170 { "abs", cx_mag },
171 { "sqrt", cx_sqrt },
172 { "sin", cx_sin },
173 { "cos", cx_cos },
174 { "tan", cx_tan },
175 { "sinh", cx_sinh },
176 { "cosh", cx_cosh },
177 { "tanh", cx_tanh },
178 { "atan", cx_atan },
179 { "sortorder", cx_sortorder },
180 { "norm", cx_norm },
181 { "rnd", cx_rnd },
182 { "sunif", cx_sunif },
183 { "poisson", cx_poisson },
184 { "exponential", cx_exponential },
185 { "sgauss", cx_sgauss },
186 { "pos", cx_pos },
187 { "nint", cx_nint },
188 { "floor", cx_floor },
189 { "ceil", cx_ceil },
190 { "mean", cx_mean },
191 { "stddev", cx_stddev },
192 { "avg", cx_avg }, /* A.Roldan 03/06/05 incremental average new function */
193 { "group_delay", (cx_function_t*) cx_group_delay }, /* A.Roldan 10/06/05 group delay new function */
194 { "vector", cx_vector },
195 { "unitvec", cx_unitvec },
196 { "length", cx_length },
197 { "vecmin", cx_min },
198 { "minimum", cx_min },
199 { "vecmax", cx_max },
200 { "maximum", cx_max },
201 { "vecd", cx_d },
202 { "interpolate", (cx_function_t*) cx_interpolate },
203 { "deriv", (cx_function_t*) cx_deriv },
204 { "fft", (cx_function_t*) cx_fft },
205 { "ifft", (cx_function_t*) cx_ifft },
206 { "v", NULL },
207 { NULL, NULL }
208 };
209
210 struct func func_uminus = { "minus", cx_uminus };
211
212 struct func func_not = { "not", cx_not };
213
214
215 /* Binary operator node. */
PP_mkbnode(int opnum,struct pnode * arg1,struct pnode * arg2)216 struct pnode *PP_mkbnode(int opnum, struct pnode *arg1, struct pnode *arg2)
217 {
218 struct op *o;
219 struct pnode *p;
220
221 for (o = &ops[0]; o->op_name; o++) {
222 if (o->op_num == opnum) {
223 break;
224 }
225 }
226
227 if (!o->op_name) {
228 fprintf(cp_err, "PP_mkbnode: Internal Error: no such op num %d\n",
229 opnum);
230 }
231
232 p = alloc_pnode();
233
234 p->pn_op = o;
235
236 p->pn_left = arg1;
237 if (p->pn_left) {
238 p->pn_left->pn_use++;
239 }
240
241 p->pn_right = arg2;
242 if (p->pn_right) {
243 p->pn_right->pn_use++;
244 }
245
246 return p;
247 } /* end of function PP_mkbnode */
248
249
250
251 /* Unary operator node. */
PP_mkunode(int op,struct pnode * arg)252 struct pnode *PP_mkunode(int op, struct pnode *arg)
253 {
254 struct pnode *p;
255 struct op *o;
256
257 p = alloc_pnode();
258
259 for (o = uops; o->op_name; o++) {
260 if (o->op_num == op) {
261 break;
262 }
263 }
264
265 if (!o->op_name) {
266 fprintf(cp_err, "PP_mkunode: Internal Error: no such op num %d\n",
267 op);
268 }
269
270 p->pn_op = o;
271
272 p->pn_left = arg;
273 if (p->pn_left) {
274 p->pn_left->pn_use++;
275 }
276
277 return p;
278 } /* end of function PP_mkunode */
279
280
281
282 /* Function node. We have to worry about a lot of things here. Something
283 * like f(a) could be three things -- a call to a standard function, which
284 * is easiest to deal with, a variable name, in which case we do the
285 * kludge with 0-length lists, or it could be a user-defined function,
286 * in which case we have to figure out which one it is, substitute for
287 * the arguments, and then return a copy of the expression that it was
288 * defined to be.
289 */
PP_mkfnode(const char * func,struct pnode * arg)290 struct pnode *PP_mkfnode(const char *func, struct pnode *arg)
291 {
292 struct func *f;
293 struct pnode *p, *q;
294 struct dvec *d;
295 char buf[BSIZE_SP];
296
297 (void) strcpy(buf, func);
298 strtolower(buf); /* Make sure the case is ok. */
299
300 for (f = &ft_funcs[0]; f->fu_name; f++) {
301 if (eq(f->fu_name, buf)) {
302 break;
303 }
304 }
305
306 if (f->fu_name == NULL) { /* not found yet */
307 /* Give the user-defined functions a try. */
308 q = ft_substdef(func, arg);
309 if (q) { /* found */
310 /* remove only the old comma operator pnode, no longer used */
311 if (arg->pn_op && arg->pn_op->op_num == PT_OP_COMMA) {
312 free_pnode(arg);
313 }
314 return q;
315 }
316 }
317
318 if ((f->fu_name == NULL) && arg->pn_value) {
319 /* Kludge -- maybe it is really a variable name. */
320 (void) sprintf(buf, "%s(%s)", func, arg->pn_value->v_name);
321 free_pnode(arg);
322 d = vec_get(buf);
323 if (d == NULL) {
324 /* Well, too bad. */
325 fprintf(cp_err, "Error: no such function as %s.\n",
326 func);
327 return (struct pnode *) NULL;
328 }
329 /* (void) strcpy(buf, d->v_name); XXX */
330 return PP_mksnode(buf);
331 }
332 else if (f->fu_name == NULL) {
333 fprintf(cp_err, "Error: no function as %s with that arity.\n",
334 func);
335 free_pnode(arg);
336 return (struct pnode *) NULL;
337 }
338
339 if (!f->fu_func && arg->pn_op && arg->pn_op->op_num == PT_OP_COMMA) {
340 p = PP_mkbnode(PT_OP_MINUS, PP_mkfnode(func, arg->pn_left),
341 PP_mkfnode(func, arg->pn_right));
342 free_pnode(arg);
343 return p;
344 }
345
346 p = alloc_pnode();
347
348 p->pn_func = f;
349
350 p->pn_left = arg;
351 if (p->pn_left) {
352 p->pn_left->pn_use++;
353 }
354
355 return p;
356 } /* end of function PP_mkfnode */
357
358
359
360 /* Number node. */
PP_mknnode(double number)361 struct pnode *PP_mknnode(double number)
362 {
363 struct pnode *p;
364 struct dvec *v;
365
366 /* We don't use printnum because it screws up PP_mkfnode above. We have
367 * to be careful to deal properly with node numbers that are quite
368 * large...
369 */
370 v = dvec_alloc(number <= INT_MAX
371 ? tprintf("%d", (int) number)
372 : tprintf("%G", number),
373 SV_NOTYPE,
374 VF_REAL,
375 1, NULL);
376
377 v->v_realdata[0] = number;
378
379 vec_new(v);
380
381 p = alloc_pnode();
382 p->pn_value = v;
383 return (p);
384 } /* end of function PP_mknnode */
385
386
387
388 /* String node. */
PP_mksnode(const char * string)389 struct pnode *PP_mksnode(const char *string)
390 {
391 struct dvec *v, *nv, *vs, *newv = NULL, *end = NULL;
392 struct pnode *p;
393
394 p = alloc_pnode();
395 v = vec_get(string);
396 if (v == NULL) {
397 nv = dvec_alloc(copy(string),
398 SV_NOTYPE,
399 0,
400 0, NULL);
401 p->pn_value = nv;
402 return p;
403 }
404
405 /* It's not obvious that we should be doing this, but... */
406 for (vs = v; vs; vs = vs->v_link2) {
407 nv = vec_copy(vs);
408 vec_new(nv);
409 if (end) {
410 end->v_link2 = nv;
411 }
412 else {
413 newv = end = nv;
414 }
415 end = nv;
416 }
417 p->pn_value = newv;
418
419 /* va: tfree v in case of @xxx[par], because vec_get created a new vec and
420 nobody will free it elsewhere */
421 /*if (v && v->v_name && *v->v_name == '@' && isreal(v) && v->v_realdata) {
422 vec_free(v);
423 } */
424 /* The two lines above have been commented out to prevent deletion of @xxx[par]
425 after execution of only a single command like plot @xxx[par] or write. We need to
426 monitor if this will lead to excessive memory usage. h_vogt 090221 */
427 return p;
428 } /* end of function PP_mksnode */
429
430
431
alloc_pnode(void)432 struct pnode *alloc_pnode(void)
433 {
434 struct pnode *pn = TMALLOC(struct pnode, 1);
435
436 pn->pn_use = 0;
437 pn->pn_name = NULL;
438
439 // fixme, thats actually a union ...
440 pn->pn_value = NULL;
441 pn->pn_func = NULL;
442 pn->pn_op = NULL;
443
444 pn->pn_left = NULL;
445 pn->pn_right = NULL;
446 pn->pn_next = NULL;
447
448 return pn;
449 } /* end of function alloc_pnode */
450
451
452
453 /* Don't call this directly, always use the free_pnode() macro.
454 The linked pnodes do not necessarily form a perfect tree as some nodes get
455 reused. Hence, in this recursive walk through the 'tree', we only free
456 nodes that have their pn_use value at zero. Nodes that have pn_use values
457 above zero have the link severed and their pn_use value decremented.
458 In addition, we don't walk past nodes with pn_use values avoid zero, just
459 in case we have a circular reference (This probably does not happen in
460 practice, but it does no harm playing safe.) */
free_pnode_x(struct pnode * t)461 void free_pnode_x(struct pnode *t)
462 {
463 if (!t) {
464 return;
465 }
466
467 /* Don't walk past nodes used elsewhere. We decrement the pn_use value here,
468 but the link gets severed by the action of the free_pnode() macro */
469 if (t->pn_use > 1) {
470 t->pn_use--;
471 }
472 else {
473 /* pn_use is now 1, so its safe to free the pnode */
474 free_pnode(t->pn_left);
475 free_pnode(t->pn_right);
476 free_pnode(t->pn_next);
477 tfree(t->pn_name); /* va: it is a copy() of original string, can be free'd */
478 if (t->pn_use == 1 && t->pn_value && !(t->pn_value->v_flags & VF_PERMANENT)) {
479 vec_free(t->pn_value); /* patch by Stefan Jones */
480 }
481 txfree(t);
482 }
483 } /* end of function free_pnode_x */
484
485
486
db_print_func(FILE * fdst,struct func * f)487 static void db_print_func(FILE *fdst, struct func *f)
488 {
489 if (!f) {
490 fprintf(fdst, "nil");
491 return;
492 }
493
494 fprintf(fdst, "(func :fu_name %s :fu_func %p)", f->fu_name, f->fu_func);
495 } /* end of function db_print_func */
496
497
498
db_print_op(FILE * fdst,struct op * op)499 static void db_print_op(FILE *fdst, struct op *op)
500 {
501 if (!op) {
502 fprintf(fdst, "nil");
503 return;
504 }
505
506 fprintf(fdst, "(op :op_num %d :op_name %s :op_arity %d :op_func %p)",
507 op->op_num, op->op_name, op->op_arity, op->op_func.anonymous);
508 } /* end of function db_print_op */
509
510
511
db_print_dvec(FILE * fdst,struct dvec * d)512 static void db_print_dvec(FILE *fdst, struct dvec *d)
513 {
514 if (!d) {
515 fprintf(fdst, "nil");
516 return;
517 }
518
519 fprintf(fdst, "(dvec :v_name %s :v_type %d :v_flags %d :v_length %d ...)",
520 d->v_name, d->v_type, d->v_flags, d->v_length);
521 } /* end of function db_print_dvec */
522
523
524
db_print_pnode(FILE * fdst,struct pnode * p)525 static void db_print_pnode(FILE *fdst, struct pnode *p)
526 {
527 if (!p) {
528 fprintf(fdst, "nil\n");
529 return;
530 }
531
532 if (!p->pn_name && p->pn_value && !p->pn_func && !p->pn_op &&
533 !p->pn_left && !p->pn_right && !p->pn_next) {
534 fprintf(fdst, "(pnode-value :pn_use %d", p->pn_use);
535 fprintf(fdst, " :pn_value "); db_print_dvec(fdst, p->pn_value);
536 fprintf(fdst, ")\n");
537 return;
538 }
539
540 if (!p->pn_name && !p->pn_value && p->pn_func && !p->pn_op &&
541 !p->pn_right && !p->pn_next) {
542 fprintf(fdst, "(pnode-func :pn_use %d", p->pn_use);
543 fprintf(fdst, "\n :pn_func "); db_print_func(fdst, p->pn_func);
544 fprintf(fdst, "\n :pn_left "); db_print_pnode(fdst, p->pn_left);
545 fprintf(fdst, ")\n");
546 return;
547 }
548
549 if (!p->pn_name && !p->pn_value && !p->pn_func && p->pn_op &&
550 !p->pn_next) {
551 fprintf(fdst, "(pnode-op :pn_use %d", p->pn_use);
552 fprintf(fdst, "\n :pn_op "); db_print_op(fdst, p->pn_op);
553 fprintf(fdst, "\n :pn_left "); db_print_pnode(fdst, p->pn_left);
554 fprintf(fdst, "\n :pn_right "); db_print_pnode(fdst, p->pn_right);
555 fprintf(fdst, ")\n");
556 return;
557 }
558
559 fprintf(fdst, "(pnode :pn_name \"%s\" pn_use %d", p->pn_name, p->pn_use);
560 fprintf(fdst, "\n :pn_value "); db_print_dvec(fdst, p->pn_value);
561 fprintf(fdst, "\n :pn_func "); db_print_func(fdst, p->pn_func);
562 fprintf(fdst, "\n :pn_op "); db_print_op(fdst, p->pn_op);
563 fprintf(fdst, "\n :pn_left "); db_print_pnode(fdst, p->pn_left);
564 fprintf(fdst, "\n :pn_right "); db_print_pnode(fdst, p->pn_right);
565 fprintf(fdst, "\n :pn_next "); db_print_pnode(fdst, p->pn_next);
566 fprintf(fdst, "\n)\n");
567 } /* end of function db_print_pnode */
568
569
570
db_print_pnode_tree(struct pnode * p,char * print)571 void db_print_pnode_tree(struct pnode *p, char *print)
572 {
573 #if 1
574 NG_IGNORE(print);
575 db_print_pnode(stdout, p);
576 #else
577 char *buf;
578 size_t buf_size;
579 FILE *db_stream = open_memstream(&buf, &buf_size);
580 db_print_pnode(db_stream, p);
581 fclose(db_stream);
582 if (print)
583 printf("%s:%d: %s {%s}\n%s\n", __FILE__, __LINE__, __func__, print, buf);
584 tfree(buf);
585 #endif
586 } /* end of function db_print_pnode_tree */
587
588
589
PPlex(YYSTYPE * lvalp,struct PPltype * llocp,char ** line)590 int PPlex(YYSTYPE *lvalp, struct PPltype *llocp, char **line)
591 {
592 static char *specials = " \t%()-^+*,/|&<>~=";
593 char *sbuf = *line;
594 int token;
595
596 while ((*sbuf == ' ') || (*sbuf == '\t')) {
597 sbuf++;
598 }
599
600 llocp->start = sbuf;
601
602 #define lexer_return(token_, length) \
603 do { token = token_; sbuf += length; goto done; } while(0)
604
605 if ((sbuf[0] == 'g') && (sbuf[1] == 't') &&
606 strchr(specials, sbuf[2])) {
607 lexer_return('>', 2);
608 }
609 else if ((sbuf[0] == 'l') && (sbuf[1] == 't') &&
610 strchr(specials, sbuf[2])) {
611 lexer_return('<', 2);
612 }
613 else if ((sbuf[0] == 'g') && (sbuf[1] == 'e') &&
614 strchr(specials, sbuf[2])) {
615 lexer_return(TOK_GE, 2);
616 }
617 else if ((sbuf[0] == 'l') && (sbuf[1] == 'e') &&
618 strchr(specials, sbuf[2])) {
619 lexer_return(TOK_LE, 2);
620 }
621 else if ((sbuf[0] == 'n') && (sbuf[1] == 'e') &&
622 strchr(specials, sbuf[2])) {
623 lexer_return(TOK_NE, 2);
624 }
625 else if ((sbuf[0] == 'e') && (sbuf[1] == 'q') &&
626 strchr(specials, sbuf[2])) {
627 lexer_return('=', 2);
628 }
629 else if ((sbuf[0] == 'o') && (sbuf[1] == 'r') &&
630 strchr(specials, sbuf[2])) {
631 lexer_return('|', 2);
632 }
633 else if ((sbuf[0] == 'a') && (sbuf[1] == 'n') &&
634 (sbuf[2] == 'd') && strchr(specials, sbuf[3])) {
635 lexer_return('&', 3);
636 }
637 else if ((sbuf[0] == 'n') && (sbuf[1] == 'o') &&
638 (sbuf[2] == 't') && strchr(specials, sbuf[3])) {
639 lexer_return('~', 3);
640 }
641
642 switch (*sbuf) {
643
644 case '[':
645 case ']':
646 lexer_return(*sbuf, 1);
647
648 case '>':
649 case '<': {
650 /* Workaround, The Frontend makes "<>" into "< >" */
651 size_t j = 1;
652 while (isspace_c(sbuf[j]))
653 j++;
654 if (((sbuf[j] == '<') || (sbuf[j] == '>')) && (sbuf[0] != sbuf[j])) {
655 /* Allow both <> and >< for NE. */
656 lexer_return(TOK_NE, j + 1);
657 }
658 else if (sbuf[1] == '=') {
659 lexer_return((sbuf[0] == '>') ? TOK_GE : TOK_LE, 2);
660 }
661 else {
662 lexer_return(*sbuf, 1);
663 }
664 }
665
666 case '?':
667 case ':':
668 case ',':
669 case '+':
670 case '-':
671 case '*':
672 case '%':
673 case '/':
674 case '^':
675 case '(':
676 case ')':
677 case '=':
678 case '&':
679 case '|':
680 case '~':
681 lexer_return(*sbuf, 1);
682
683 case '\0':
684 lexer_return(*sbuf, 0);
685
686 case '"': {
687 char *start = ++sbuf;
688 while (*sbuf && (*sbuf != '"'))
689 sbuf++;
690 lvalp->str = copy_substring(start, sbuf);
691 if (*sbuf) {
692 sbuf++;
693 }
694 lexer_return(TOK_STR, 0);
695 }
696
697 default: {
698 char *s = sbuf;
699 double val;
700
701 if (ft_numparse(&s, FALSE, &val) >= 0 &&
702 (!s || *s != ':')) {
703 sbuf = s;
704 lvalp->num = val;
705 lexer_return(TOK_NUM, 0);
706 }
707 else {
708 int atsign = 0;
709 char *start = sbuf;
710 /* It is bad how we have to recognise '[' -- sometimes
711 * it is part of a word, when it defines a parameter
712 * name, and otherwise it isn't.
713 *
714 * what is valid here ?
715 * foo dc1.foo dc1.@m1[vth]
716 * vthing#branch
717 * i(vthing)
718 */
719 for (; *sbuf && !strchr(specials, *sbuf); sbuf++)
720 if (*sbuf == '@') {
721 atsign = 1;
722 }
723 else if (!atsign && *sbuf == '[') {
724 break;
725 }
726 else if (*sbuf == ']') {
727 if (atsign) {
728 sbuf++;
729 }
730 break;
731 }
732 /* keep the identifier i(vss) as a single token, even as dc1.i(vss) */
733 else if (prefix("i(v", sbuf)) {
734 if (get_r_paren(&sbuf) == 1) {
735 fprintf(stderr, "Error: missing ')' in token\n %s\n", start);
736 break;
737 }
738 sbuf--;
739 }
740
741 lvalp->str = copy_substring(start, sbuf);
742 lexer_return(TOK_STR, 0);
743 }
744 }
745 } /* end of switch over characters */
746
747 done:
748 if (ft_parsedb) {
749 if (token == TOK_STR) {
750 fprintf(stderr, "lexer: TOK_STR, \"%s\"\n", lvalp->str);
751 }
752 else if (token == TOK_NUM) {
753 fprintf(stderr, "lexer: TOK_NUM, %G\n", lvalp->num);
754 }
755 else {
756 fprintf(stderr, "lexer: token %d\n", token);
757 }
758 }
759
760 *line = sbuf;
761 llocp->stop = sbuf;
762 return token;
763 } /* end of function PPlex */
764
765
766
767