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