home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 334_02 / parse.c < prev    next >
Text File  |  1991-02-05  |  10KB  |  532 lines

  1. /* GNUPLOT - parse.c */
  2. /*
  3.  * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
  4.  *
  5.  * Permission to use, copy, and distribute this software and its
  6.  * documentation for any purpose with or without fee is hereby granted, 
  7.  * provided that the above copyright notice appear in all copies and 
  8.  * that both that copyright notice and this permission notice appear 
  9.  * in supporting documentation.
  10.  *
  11.  * Permission to modify the software is granted, but not the right to
  12.  * distribute the modified code.  Modifications are to be distributed 
  13.  * as patches to released version.
  14.  *  
  15.  * This software  is provided "as is" without express or implied warranty.
  16.  * 
  17.  *
  18.  * AUTHORS
  19.  * 
  20.  *   Original Software:
  21.  *     Thomas Williams,  Colin Kelley.
  22.  * 
  23.  *   Gnuplot 2.0 additions:
  24.  *       Russell Lang, Dave Kotz, John Campbell.
  25.  * 
  26.  * send your comments or suggestions to (pixar!info-gnuplot@sun.com).
  27.  * 
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <setjmp.h>
  32. #include <signal.h>
  33. #include <errno.h>
  34. #include <math.h>
  35. #include "plot.h"
  36.  
  37. #ifndef vms
  38. #ifndef __ZTC__
  39. extern int errno;
  40. #endif
  41. #endif
  42.  
  43. extern int num_tokens,c_token;
  44. extern struct lexical_unit token[];
  45. extern char c_dummy_var[];            /* name of current dummy variable */
  46. extern struct udft_entry *dummy_func;    /* pointer to dummy variable's func */
  47.  
  48. struct value *pop(),*integer(),*complex();
  49. struct at_type *temp_at(), *perm_at();
  50. struct udft_entry *add_udf();
  51. struct udvt_entry *add_udv();
  52. union argument *add_action();
  53.  
  54. struct at_type at;
  55. static jmp_buf fpe_env;
  56.  
  57. #define dummy (struct value *) 0
  58.  
  59. #ifdef __TURBOC__
  60. void fpe()
  61. #else
  62. #ifdef __ZTC__
  63. void fpe(an_int)
  64. int an_int;
  65. #else
  66. fpe()
  67. #endif
  68. #endif
  69. {
  70. #ifdef PC    /* thanks to lotto@wjh12.UUCP for telling us about this  */
  71.     _fpreset();
  72. #endif
  73.     (void) signal(SIGFPE, fpe);
  74.     undefined = TRUE;
  75.     longjmp(fpe_env, TRUE);
  76. }
  77.  
  78.  
  79. #ifdef apollo
  80. #include <apollo/base.h>
  81. #include <apollo/pfm.h>
  82. #include <apollo/fault.h>
  83.  
  84. /*
  85.   On an Apollo, the OS can signal a couple errors that are not mapped
  86.   into SIGFPE, namely signalling NaN and branch on an unordered
  87.   comparison.  I suppose there are others, but none of these are documented,
  88.   so I handle them as they arise.
  89.  
  90.   Anyway, we need to catch these faults and signal SIGFPE.
  91. */
  92.  
  93. pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t& fault_rec)
  94. {
  95.     kill(getpid(), SIGFPE);
  96.     return pfm_$continue_fault_handling;
  97. }
  98.  
  99. apollo_pfm_catch()
  100. {
  101.     status_$t status;
  102.     pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
  103.                  apollo_sigfpe, &status);
  104.     pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
  105.                  apollo_sigfpe, &status);
  106. }
  107. #endif
  108.  
  109.  
  110. evaluate_at(at_ptr,val_ptr)
  111. struct at_type *at_ptr;
  112. struct value *val_ptr;
  113. {
  114.     double temp, real();
  115.  
  116.     undefined = FALSE;
  117.     errno = 0;
  118.     reset_stack();
  119.     if (setjmp(fpe_env))
  120.         return;                /* just bail out */
  121.     (void) signal(SIGFPE, fpe);    /* catch core dumps on FPEs */
  122.  
  123.     execute_at(at_ptr);
  124.  
  125.     (void) signal(SIGFPE, SIG_DFL);
  126.  
  127.     if (errno == EDOM || errno == ERANGE) {
  128.         undefined = TRUE;
  129.     } else {
  130.         (void) pop(val_ptr);
  131.         check_stack();
  132.     }
  133. /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
  134.     temp = real(val_ptr);
  135.     if (temp > VERYLARGE || temp < -VERYLARGE) {
  136.         undefined = TRUE;
  137.     }
  138. }
  139.  
  140.  
  141. struct value *
  142. const_express(valptr)
  143. struct value *valptr;
  144. {
  145. register int tkn = c_token;
  146.     if (END_OF_COMMAND)
  147.         int_error("constant expression required",c_token);
  148.     evaluate_at(temp_at(),valptr);    /* run it and send answer back */
  149.     if (undefined) {
  150.         int_error("undefined value",tkn);
  151.     }
  152.     return(valptr);
  153. }
  154.  
  155.  
  156. struct at_type *
  157. temp_at()    /* build a static action table and return its pointer */
  158. {
  159.     at.a_count = 0;        /* reset action table !!! */
  160.     express();
  161.     return(&at);
  162. }
  163.  
  164.  
  165. /* build an action table, put it in dynamic memory, and return its pointer */
  166.  
  167. struct at_type *
  168. perm_at()
  169. {
  170. register struct at_type *at_ptr;
  171. register unsigned int len;
  172.  
  173.     (void) temp_at();
  174.     len = sizeof(struct at_type) -
  175.         (MAX_AT_LEN - at.a_count)*sizeof(struct at_entry);
  176.     at_ptr = (struct at_type *) alloc(len, "action table");
  177.      (void) memcpy(at_ptr,&at,len);
  178.     return(at_ptr);
  179. }
  180.  
  181.  
  182. #ifdef NOCOPY
  183. /*
  184.  * cheap and slow version of memcpy() in case you don't have one
  185.  */
  186. memcpy(dest,src,len)
  187. char *dest,*src;
  188. unsigned int len;
  189. {
  190.     while (len--)
  191.         *dest++ = *src++;
  192. }
  193. #endif /* NOCOPY */
  194.  
  195.  
  196. express()  /* full expressions */
  197. {
  198.     xterm();
  199.     xterms();
  200. }
  201.  
  202. xterm()  /* ? : expressions */
  203. {
  204.     aterm();
  205.     aterms();
  206. }
  207.  
  208.  
  209. aterm()
  210. {
  211.     bterm();
  212.     bterms();
  213. }
  214.  
  215.  
  216. bterm()
  217. {
  218.     cterm();
  219.     cterms();
  220. }
  221.  
  222.  
  223. cterm()
  224. {
  225.     dterm();
  226.     dterms();
  227. }
  228.  
  229.  
  230. dterm()
  231. {    
  232.     eterm();
  233.     eterms();
  234. }
  235.  
  236.  
  237. eterm()
  238. {
  239.     fterm();
  240.     fterms();
  241. }
  242.  
  243.  
  244. fterm()
  245. {
  246.     gterm();
  247.     gterms();
  248. }
  249.  
  250.  
  251. gterm()
  252. {
  253.     hterm();
  254.     hterms();
  255. }
  256.  
  257.  
  258. hterm()
  259. {
  260.     unary(); /* - things */
  261.     iterms(); /* * / % */
  262. }
  263.  
  264.  
  265. factor()
  266. {
  267. register int value;
  268.  
  269.     if (equals(c_token,"(")) {
  270.         c_token++;
  271.         express();
  272.         if (!equals(c_token,")"))
  273.             int_error("')' expected",c_token);
  274.         c_token++;
  275.     }
  276.     else if (isnumber(c_token)) {
  277.         convert(&(add_action(PUSHC)->v_arg),c_token);
  278.         c_token++;
  279.     }
  280.     else if (isletter(c_token)) {
  281.         if ((c_token+1 < num_tokens)  && equals(c_token+1,"(")) {
  282.             value = standard(c_token);
  283.             if (value) {    /* it's a standard function */
  284.                 c_token += 2;
  285.                 express();
  286.                 if (!equals(c_token,")"))
  287.                     int_error("')' expected",c_token);
  288.                 c_token++;
  289.                 (void) add_action(value);
  290.             }
  291.             else {
  292.                 value = c_token;
  293.                 c_token += 2;
  294.                 express();
  295.                 if (!equals(c_token,")"))
  296.                     int_error("')' expected",c_token);
  297.                 c_token++;
  298.                 add_action(CALL)->udf_arg = add_udf(value);
  299.             }
  300.         }
  301.         else {
  302.             if (equals(c_token,c_dummy_var)) {
  303.                 c_token++;
  304.                 add_action(PUSHD)->udf_arg = dummy_func;
  305.             }
  306.             else {
  307.                 add_action(PUSH)->udv_arg = add_udv(c_token);
  308.                 c_token++;
  309.             }
  310.         }
  311.     } /* end if letter */
  312.     else
  313.         int_error("invalid expression ",c_token);
  314.  
  315.     /* add action code for ! (factorial) operator */
  316.     while (equals(c_token,"!")) {
  317.         c_token++;
  318.         (void) add_action(FACTORIAL);
  319.     }
  320.     /* add action code for ** operator */
  321.     if (equals(c_token,"**")) {
  322.             c_token++;
  323.             unary();
  324.             (void) add_action(POWER);
  325.     }
  326.  
  327. }
  328.  
  329.  
  330.  
  331. xterms()
  332. {  /* create action code for ? : expressions */
  333.  
  334.     if (equals(c_token,"?")) {
  335.         register int savepc1, savepc2;
  336.         register union argument *argptr1,*argptr2;
  337.         c_token++;
  338.         savepc1 = at.a_count;
  339.         argptr1 = add_action(JTERN);
  340.         express();
  341.         if (!equals(c_token,":"))
  342.             int_error("expecting ':'",c_token);
  343.         c_token++;
  344.         savepc2 = at.a_count;
  345.         argptr2 = add_action(JUMP);
  346.         argptr1->j_arg = at.a_count - savepc1;
  347.         express();
  348.         argptr2->j_arg = at.a_count - savepc2;
  349.     }
  350. }
  351.  
  352.  
  353. aterms()
  354. {  /* create action codes for || operator */
  355.  
  356.     while (equals(c_token,"||")) {
  357.         register int savepc;
  358.         register union argument *argptr;
  359.         c_token++;
  360.         savepc = at.a_count;
  361.         argptr = add_action(JUMPNZ);    /* short-circuit if already TRUE */
  362.         aterm();
  363.         argptr->j_arg = at.a_count - savepc;/* offset for jump */
  364.         (void) add_action(BOOL);
  365.     }
  366. }
  367.  
  368.  
  369. bterms()
  370. { /* create action code for && operator */
  371.  
  372.     while (equals(c_token,"&&")) {
  373.         register int savepc;
  374.         register union argument *argptr;
  375.         c_token++;
  376.         savepc = at.a_count;
  377.         argptr = add_action(JUMPZ);    /* short-circuit if already FALSE */
  378.         bterm();
  379.         argptr->j_arg = at.a_count - savepc;/* offset for jump */
  380.         (void) add_action(BOOL);
  381.     }
  382. }
  383.  
  384.  
  385. cterms()
  386. { /* create action code for | operator */
  387.  
  388.     while (equals(c_token,"|")) {
  389.         c_token++;
  390.         cterm();
  391.         (void) add_action(BOR);
  392.     }
  393. }
  394.  
  395.  
  396. dterms()
  397. { /* create action code for ^ operator */
  398.  
  399.     while (equals(c_token,"^")) {
  400.         c_token++;
  401.         dterm();
  402.         (void) add_action(XOR);
  403.     }
  404. }
  405.  
  406.  
  407. eterms()
  408. { /* create action code for & operator */
  409.  
  410.     while (equals(c_token,"&")) {
  411.         c_token++;
  412.         eterm();
  413.         (void) add_action(BAND);
  414.     }
  415. }
  416.  
  417.  
  418. fterms()
  419. { /* create action codes for == and != operators */
  420.  
  421.     while (TRUE) {
  422.         if (equals(c_token,"==")) {
  423.             c_token++;
  424.             fterm();
  425.             (void) add_action(EQ);
  426.         }
  427.         else if (equals(c_token,"!=")) {
  428.             c_token++;
  429.             fterm();
  430.             (void) add_action(NE);
  431.         }
  432.         else break;
  433.     }
  434. }
  435.  
  436.  
  437. gterms()
  438. { /* create action code for < > >= or <= operators */
  439.     
  440.     while (TRUE) {
  441.         /* I hate "else if" statements */
  442.         if (equals(c_token,">")) {
  443.             c_token++;
  444.             gterm();
  445.             (void) add_action(GT);
  446.         }
  447.         else if (equals(c_token,"<")) {
  448.             c_token++;
  449.             gterm();
  450.             (void) add_action(LT);
  451.         }        
  452.         else if (equals(c_token,">=")) {
  453.             c_token++;
  454.             gterm();
  455.             (void) add_action(GE);
  456.         }
  457.         else if (equals(c_token,"<=")) {
  458.             c_token++;
  459.             gterm();
  460.             (void) add_action(LE);
  461.         }
  462.         else break;
  463.     }
  464.  
  465. }
  466.  
  467.  
  468.  
  469. hterms()
  470. { /* create action codes for + and - operators */
  471.  
  472.     while (TRUE) {
  473.             if (equals(c_token,"+")) {
  474.                 c_token++;
  475.                 hterm();
  476.                 (void) add_action(PLUS);
  477.             }
  478.             else if (equals(c_token,"-")) {
  479.                 c_token++;
  480.                 hterm();
  481.                 (void) add_action(MINUS);
  482.             }
  483.             else break;
  484.     }
  485. }
  486.  
  487.  
  488. iterms()
  489. { /* add action code for * / and % operators */
  490.  
  491.     while (TRUE) {
  492.             if (equals(c_token,"*")) {
  493.                 c_token++;
  494.                 unary();
  495.                 (void) add_action(MULT);
  496.             }
  497.             else if (equals(c_token,"/")) {
  498.                 c_token++;
  499.                 unary();
  500.                 (void) add_action(DIV);
  501.             }
  502.             else if (equals(c_token,"%")) {
  503.                 c_token++;
  504.                 unary();
  505.                 (void) add_action(MOD);
  506.             }
  507.             else break;
  508.     }
  509. }
  510.  
  511.  
  512. unary()
  513. { /* add code for unary operators */
  514.     if (equals(c_token,"!")) {
  515.         c_token++;
  516.         unary();
  517.         (void) add_action(LNOT);
  518.     }
  519.     else if (equals(c_token,"~")) {
  520.         c_token++;
  521.         unary();
  522.         (void) add_action(BNOT);
  523.     }
  524.     else if (equals(c_token,"-")) {
  525.         c_token++;
  526.         unary();
  527.         (void) add_action(UMINUS);
  528.     }
  529.     else
  530.         factor();
  531. }
  532.