Annotation of OpenXM_contrib/gnuplot/parse.c, Revision 1.1.1.3
1.1 maekawa 1: #ifndef lint
1.1.1.3 ! ohara 2: static char *RCSid = "$Id: parse.c,v 1.9.2.4 2002/03/11 16:07:20 lhecking Exp $";
1.1 maekawa 3: #endif
4:
5: /* GNUPLOT - parse.c */
6:
7: /*[
8: * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
9: *
10: * Permission to use, copy, and distribute this software and its
11: * documentation for any purpose with or without fee is hereby granted,
12: * provided that the above copyright notice appear in all copies and
13: * that both that copyright notice and this permission notice appear
14: * in supporting documentation.
15: *
16: * Permission to modify the software is granted, but not the right to
17: * distribute the complete modified source code. Modifications are to
18: * be distributed as patches to the released version. Permission to
19: * distribute binaries produced by compiling modified sources is granted,
20: * provided you
21: * 1. distribute the corresponding source modifications from the
22: * released version in the form of a patch file along with the binaries,
23: * 2. add special version identification to distinguish your version
24: * in addition to the base release version number,
25: * 3. provide your name and address as the primary contact for the
26: * support of your modified version, and
27: * 4. retain our contact information in regard to use of the base
28: * software.
29: * Permission to distribute the released version of the source code along
30: * with corresponding source modifications in the form of a patch file is
31: * granted with same provisions 2 through 4 for binary distributions.
32: *
33: * This software is provided "as is" without express or implied warranty
34: * to the extent permitted by applicable law.
35: ]*/
36:
1.1.1.3 ! ohara 37: #ifdef HAVE_CONFIG_H
! 38: # include "config.h"
! 39: #endif
! 40:
1.1 maekawa 41: #include <signal.h>
1.1.1.3 ! ohara 42: #include <setjmp.h>
! 43:
1.1 maekawa 44: #include "plot.h"
45: #include "help.h"
46:
47: RETSIGTYPE fpe __PROTO((int an_int));
48: static void extend_at __PROTO((void));
49: static union argument *add_action __PROTO((enum operators sf_index));
50: static void express __PROTO((void));
51: static void xterm __PROTO((void));
52: static void aterm __PROTO((void));
53: static void bterm __PROTO((void));
54: static void cterm __PROTO((void));
55: static void dterm __PROTO((void));
56: static void eterm __PROTO((void));
57: static void fterm __PROTO((void));
58: static void gterm __PROTO((void));
59: static void hterm __PROTO((void));
60: static void factor __PROTO((void));
61: static void xterms __PROTO((void));
62: static void aterms __PROTO((void));
63: static void bterms __PROTO((void));
64: static void cterms __PROTO((void));
65: static void dterms __PROTO((void));
66: static void eterms __PROTO((void));
67: static void fterms __PROTO((void));
68: static void gterms __PROTO((void));
69: static void hterms __PROTO((void));
70: static void iterms __PROTO((void));
71: static void unary __PROTO((void));
72:
73: static struct at_type *at = NULL;
74: static int at_size = 0;
75: #if defined(_Windows) && !defined(WIN32)
1.1.1.3 ! ohara 76: static JMP_BUF far fpe_env;
1.1 maekawa 77: #else
1.1.1.3 ! ohara 78: static JMP_BUF fpe_env;
1.1 maekawa 79: #endif
80:
81: #define dummy (struct value *) 0
82:
83: RETSIGTYPE fpe(an_int)
84: int an_int;
85: {
86: #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386)
87: /* thanks to lotto@wjh12.UUCP for telling us about this */
88: _fpreset();
89: #endif
90:
91: #ifdef OS2
92: (void) signal(an_int, SIG_ACK);
93: #else
94: (void) signal(SIGFPE, (sigfunc) fpe);
95: #endif
96: undefined = TRUE;
1.1.1.3 ! ohara 97: LONGJMP(fpe_env, TRUE);
1.1 maekawa 98: }
99:
100:
101: #ifdef apollo
102: #include <apollo/base.h>
103: #include <apollo/pfm.h>
104: #include <apollo/fault.h>
105:
106: /*
107: * On an Apollo, the OS can signal a couple errors that are not mapped into
108: * SIGFPE, namely signalling NaN and branch on an unordered comparison. I
109: * suppose there are others, but none of these are documented, so I handle
110: * them as they arise.
111: *
112: * Anyway, we need to catch these faults and signal SIGFPE.
113: */
114:
115: pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
116: {
117: kill(getpid(), SIGFPE);
118: return pfm_$continue_fault_handling;
119: }
120:
121: apollo_pfm_catch()
122: {
123: status_$t status;
124: pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
125: apollo_sigfpe, &status);
126: pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
127: apollo_sigfpe, &status);
128: }
129: #endif
130:
131:
132: void evaluate_at(at_ptr, val_ptr)
133: struct at_type *at_ptr;
134: struct value *val_ptr;
135: {
136: double temp;
137:
138: undefined = FALSE;
139: errno = 0;
140: reset_stack();
141:
142: #ifndef DOSX286
1.1.1.3 ! ohara 143: if (SETJMP(fpe_env, 1))
1.1 maekawa 144: return; /* just bail out */
145: (void) signal(SIGFPE, (sigfunc) fpe);
146: #endif
147:
148: execute_at(at_ptr);
149:
150: #ifndef DOSX286
151: (void) signal(SIGFPE, SIG_DFL);
152: #endif
153:
154: if (errno == EDOM || errno == ERANGE) {
155: undefined = TRUE;
156: } else if (!undefined) { /* undefined (but not errno) may have been set by matherr */
157: (void) pop(val_ptr);
158: check_stack();
159: /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
160: temp = real(val_ptr);
161: if (temp > VERYLARGE || temp < -VERYLARGE) {
162: undefined = TRUE;
163: }
164: }
165: #if defined(NeXT) || defined(ultrix)
166: /*
167: * linux was able to fit curves which NeXT gave up on -- traced it to
168: * silently returning NaN for the undefined cases and plowing ahead
169: * I can force that behavior this way. (0.0/0.0 generates NaN)
170: */
171: if (undefined && (errno == EDOM || errno == ERANGE)) { /* corey@cac */
172: undefined = FALSE;
173: errno = 0;
174: Gcomplex(val_ptr, 0.0 / 0.0, 0.0 / 0.0);
175: }
176: #endif /* NeXT || ultrix */
177: }
178:
179:
180: struct value *
181: const_express(valptr)
182: struct value *valptr;
183: {
184: register int tkn = c_token;
185:
186: if (END_OF_COMMAND)
187: int_error("constant expression required", c_token);
188:
189: /* div - no dummy variables in a constant expression */
190: dummy_func = NULL;
191:
192: evaluate_at(temp_at(), valptr); /* run it and send answer back */
193: if (undefined) {
194: int_error("undefined value", tkn);
195: }
196: return (valptr);
197: }
198:
199:
200: /* if dummy_dunc == NULL on entry, do not attempt to compile dummy variables
201: * - div
202: */
203: struct at_type *
204: temp_at()
205: {
206: /* build a static action table and return its
207: * pointer */
208:
209: if (at != NULL) {
210: free(at);
211: at = NULL;
212: }
213: at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
214:
215: at->a_count = 0; /* reset action table !!! */
216: at_size = MAX_AT_LEN;
217: express();
218: return (at);
219: }
220:
221:
222: /* build an action table, put it in dynamic memory, and return its pointer */
223:
224: struct at_type *
225: perm_at()
226: {
227: register struct at_type *at_ptr;
228: unsigned int len;
229:
230: (void) temp_at();
231: len = sizeof(struct at_type) +
232: (int) (at->a_count - MAX_AT_LEN) * (int) sizeof(struct at_entry);
233: at_ptr = (struct at_type *) gp_realloc(at, (unsigned long) len, "perm_at");
234: at = NULL; /* invalidate at pointer */
235: return (at_ptr);
236: }
237:
238: static void extend_at()
239: {
240: int newsize = sizeof(struct at_type) + at_size * sizeof(struct at_entry);
241:
242: at = gp_realloc(at, newsize, "extend_at");
243: at_size += MAX_AT_LEN;
244: FPRINTF((stderr, "Extending at size to %d\n", at_size));
245: }
246:
247: /* moved from eval.c, the function is only called from this module */
248: static union argument *
249: add_action(sf_index)
250: enum operators sf_index; /* index of p-code function */
251: {
252: if (at->a_count >= at_size) {
253: extend_at();
254: }
255: at->actions[at->a_count].index = sf_index;
256: return (&(at->actions[at->a_count++].arg));
257: }
258:
259:
260: static void express()
261: { /* full expressions */
262: xterm();
263: xterms();
264: }
265:
266: static void xterm()
267: { /* ? : expressions */
268: aterm();
269: aterms();
270: }
271:
272:
273: static void aterm()
274: {
275: bterm();
276: bterms();
277: }
278:
279:
280: static void bterm()
281: {
282: cterm();
283: cterms();
284: }
285:
286:
287: static void cterm()
288: {
289: dterm();
290: dterms();
291: }
292:
293:
294: static void dterm()
295: {
296: eterm();
297: eterms();
298: }
299:
300:
301: static void eterm()
302: {
303: fterm();
304: fterms();
305: }
306:
307:
308: static void fterm()
309: {
310: gterm();
311: gterms();
312: }
313:
314:
315: static void gterm()
316: {
317: hterm();
318: hterms();
319: }
320:
321:
322: static void hterm()
323: {
324: unary(); /* - things */
325: iterms(); /* * / % */
326: }
327:
328:
329: static void factor()
330: {
331: if (equals(c_token, "(")) {
332: c_token++;
333: express();
334: if (!equals(c_token, ")"))
335: int_error("')' expected", c_token);
336: c_token++;
337: } else if (equals(c_token, "$")) {
338: struct value a;
339: if (!isanumber(++c_token))
340: int_error("Column number expected", c_token);
341: convert(&a, c_token++);
342: if (a.type != INTGR || a.v.int_val < 0)
343: int_error("Positive integer expected", c_token);
344: add_action(DOLLARS)->v_arg = a;
345: } else if (isanumber(c_token)) {
346: /* work around HP 9000S/300 HP-UX 9.10 cc limitation ... */
1.1.1.3 ! ohara 347: /* HBB 20010724: use this code for all platforms, then */
! 348:
1.1 maekawa 349: union argument *foo = add_action(PUSHC);
350: convert(&(foo->v_arg), c_token);
351: c_token++;
352: } else if (isletter(c_token)) {
353: if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) {
354: enum operators value = standard(c_token);
355: if (value) { /* it's a standard function */
356: c_token += 2;
357: express();
358: if (equals(c_token, ",")) {
359: while (equals(c_token, ",")) {
360: c_token += 1;
361: express();
362: }
363: }
364: if (!equals(c_token, ")"))
365: int_error("')' expected", c_token);
366: c_token++;
367: (void) add_action(value);
368: } else {
369: enum operators call_type = (int) CALL;
370: int tok = c_token;
371: c_token += 2;
372: express();
373: if (equals(c_token, ",")) {
374: struct value num_params;
375: num_params.type = INTGR;
376: num_params.v.int_val = 1;
377: while (equals(c_token, ",")) {
378: num_params.v.int_val += 1;
379: c_token += 1;
380: express();
381: }
382: add_action(PUSHC)->v_arg = num_params;
383: call_type = (int) CALLN;
384: }
385: if (!equals(c_token, ")"))
386: int_error("')' expected", c_token);
387: c_token++;
388: add_action(call_type)->udf_arg = add_udf(tok);
389: }
390: /* dummy_func==NULL is a flag to say no dummy variables active */
391: } else if (dummy_func) {
392: if (equals(c_token, c_dummy_var[0])) {
393: c_token++;
394: add_action(PUSHD1)->udf_arg = dummy_func;
395: } else if (equals(c_token, c_dummy_var[1])) {
396: c_token++;
397: add_action(PUSHD2)->udf_arg = dummy_func;
398: } else {
399: int i, param = 0;
400: for (i = 2; i < MAX_NUM_VAR; i++) {
401: if (equals(c_token, c_dummy_var[i])) {
402: struct value num_params;
403: num_params.type = INTGR;
404: num_params.v.int_val = i;
405: param = 1;
406: c_token++;
407: add_action(PUSHC)->v_arg = num_params;
408: add_action(PUSHD)->udf_arg = dummy_func;
409: break;
410: }
411: }
412: if (!param) { /* defined variable */
413: add_action(PUSH)->udv_arg = add_udv(c_token);
414: c_token++;
415: }
416: }
417: /* its a variable, with no dummies active - div */
418: } else {
419: add_action(PUSH)->udv_arg = add_udv(c_token);
420: c_token++;
421: }
422: }
423: /* end if letter */
424: else
425: int_error("invalid expression ", c_token);
426:
427: /* add action code for ! (factorial) operator */
428: while (equals(c_token, "!")) {
429: c_token++;
430: (void) add_action(FACTORIAL);
431: }
432: /* add action code for ** operator */
433: if (equals(c_token, "**")) {
434: c_token++;
435: unary();
436: (void) add_action(POWER);
437: }
438: }
439:
440:
1.1.1.3 ! ohara 441: /* HBB 20010309: Here and below: can't store pointers into the middle
! 442: * of at->actions[]. That array may be realloc()ed by add_action() or
! 443: * express() calls!. Access via index savepc1/savepc2, instead. */
1.1 maekawa 444:
1.1.1.3 ! ohara 445: static void
! 446: xterms()
1.1 maekawa 447: {
448: /* create action code for ? : expressions */
449:
450: if (equals(c_token, "?")) {
451: register int savepc1, savepc2;
1.1.1.3 ! ohara 452:
1.1 maekawa 453: c_token++;
454: savepc1 = at->a_count;
1.1.1.3 ! ohara 455: add_action(JTERN);
1.1 maekawa 456: express();
457: if (!equals(c_token, ":"))
458: int_error("expecting ':'", c_token);
1.1.1.3 ! ohara 459:
1.1 maekawa 460: c_token++;
461: savepc2 = at->a_count;
1.1.1.3 ! ohara 462: add_action(JUMP);
! 463: at->actions[savepc1].arg.j_arg = at->a_count - savepc1;
1.1 maekawa 464: express();
1.1.1.3 ! ohara 465: at->actions[savepc2].arg.j_arg = at->a_count - savepc2;
1.1 maekawa 466: }
467: }
468:
1.1.1.3 ! ohara 469: static void
! 470: aterms()
1.1 maekawa 471: {
472: /* create action codes for || operator */
473:
474: while (equals(c_token, "||")) {
475: register int savepc;
1.1.1.3 ! ohara 476:
1.1 maekawa 477: c_token++;
478: savepc = at->a_count;
1.1.1.3 ! ohara 479: add_action(JUMPNZ); /* short-circuit if already TRUE */
1.1 maekawa 480: aterm();
1.1.1.3 ! ohara 481: /* offset for jump */
! 482: at->actions[savepc].arg.j_arg = at->a_count - savepc;
1.1 maekawa 483: (void) add_action(BOOLE);
484: }
485: }
486:
487:
1.1.1.3 ! ohara 488: static void
! 489: bterms()
1.1 maekawa 490: {
491: /* create action code for && operator */
492:
493: while (equals(c_token, "&&")) {
494: register int savepc;
1.1.1.3 ! ohara 495:
1.1 maekawa 496: c_token++;
497: savepc = at->a_count;
1.1.1.3 ! ohara 498: add_action(JUMPZ); /* short-circuit if already FALSE */
1.1 maekawa 499: bterm();
1.1.1.3 ! ohara 500: at->actions[savepc].arg.j_arg = at->a_count - savepc; /* offset for jump */
1.1 maekawa 501: (void) add_action(BOOLE);
502: }
503: }
504:
505:
506: static void cterms()
507: {
508: /* create action code for | operator */
509:
510: while (equals(c_token, "|")) {
511: c_token++;
512: cterm();
513: (void) add_action(BOR);
514: }
515: }
516:
517:
518: static void dterms()
519: {
520: /* create action code for ^ operator */
521:
522: while (equals(c_token, "^")) {
523: c_token++;
524: dterm();
525: (void) add_action(XOR);
526: }
527: }
528:
529:
530: static void eterms()
531: {
532: /* create action code for & operator */
533:
534: while (equals(c_token, "&")) {
535: c_token++;
536: eterm();
537: (void) add_action(BAND);
538: }
539: }
540:
541:
542: static void fterms()
543: {
544: /* create action codes for == and !=
545: * operators */
546:
547: while (TRUE) {
548: if (equals(c_token, "==")) {
549: c_token++;
550: fterm();
551: (void) add_action(EQ);
552: } else if (equals(c_token, "!=")) {
553: c_token++;
554: fterm();
555: (void) add_action(NE);
556: } else
557: break;
558: }
559: }
560:
561:
562: static void gterms()
563: {
564: /* create action code for < > >= or <=
565: * operators */
566:
567: while (TRUE) {
568: /* I hate "else if" statements */
569: if (equals(c_token, ">")) {
570: c_token++;
571: gterm();
572: (void) add_action(GT);
573: } else if (equals(c_token, "<")) {
574: c_token++;
575: gterm();
576: (void) add_action(LT);
577: } else if (equals(c_token, ">=")) {
578: c_token++;
579: gterm();
580: (void) add_action(GE);
581: } else if (equals(c_token, "<=")) {
582: c_token++;
583: gterm();
584: (void) add_action(LE);
585: } else
586: break;
587: }
588:
589: }
590:
591:
592:
593: static void hterms()
594: {
595: /* create action codes for + and - operators */
596:
597: while (TRUE) {
598: if (equals(c_token, "+")) {
599: c_token++;
600: hterm();
601: (void) add_action(PLUS);
602: } else if (equals(c_token, "-")) {
603: c_token++;
604: hterm();
605: (void) add_action(MINUS);
606: } else
607: break;
608: }
609: }
610:
611:
612: static void iterms()
613: {
614: /* add action code for * / and % operators */
615:
616: while (TRUE) {
617: if (equals(c_token, "*")) {
618: c_token++;
619: unary();
620: (void) add_action(MULT);
621: } else if (equals(c_token, "/")) {
622: c_token++;
623: unary();
624: (void) add_action(DIV);
625: } else if (equals(c_token, "%")) {
626: c_token++;
627: unary();
628: (void) add_action(MOD);
629: } else
630: break;
631: }
632: }
633:
634:
635: static void unary()
636: {
637: /* add code for unary operators */
638:
639: if (equals(c_token, "!")) {
640: c_token++;
641: unary();
642: (void) add_action(LNOT);
643: } else if (equals(c_token, "~")) {
644: c_token++;
645: unary();
646: (void) add_action(BNOT);
647: } else if (equals(c_token, "-")) {
648: c_token++;
649: unary();
650: (void) add_action(UMINUS);
651: } else if (equals(c_token, "+")) { /* unary + is no-op */
652: c_token++;
653: unary();
654: } else
655: factor();
656: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>