pexpr.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:30k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. /* Program for computing integer expressions using the GNU Multiple Precision
  2.    Arithmetic Library.
  3. Copyright 1997, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
  4. This program is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU General Public License as published by the Free Software
  6. Foundation; either version 3 of the License, or (at your option) any later
  7. version.
  8. This program is distributed in the hope that it will be useful, but WITHOUT ANY
  9. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  10. PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License along with
  12. this program.  If not, see http://www.gnu.org/licenses/.  */
  13. /* This expressions evaluator works by building an expression tree (using a
  14.    recursive descent parser) which is then evaluated.  The expression tree is
  15.    useful since we want to optimize certain expressions (like a^b % c).
  16.    Usage: pexpr [options] expr ...
  17.    (Assuming you called the executable `pexpr' of course.)
  18.    Command line options:
  19.    -b        print output in binary
  20.    -o        print output in octal
  21.    -d        print output in decimal (the default)
  22.    -x        print output in hexadecimal
  23.    -b<NUM>   print output in base NUM
  24.    -t        print timing information
  25.    -html     output html
  26.    -wml      output wml
  27.    -split    split long lines each 80th digit
  28. */
  29. /* Define LIMIT_RESOURCE_USAGE if you want to make sure the program doesn't
  30.    use up extensive resources (cpu, memory).  Useful for the GMP demo on the
  31.    GMP web site, since we cannot load the server too much.  */
  32. #include "pexpr-config.h"
  33. #include <string.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <setjmp.h>
  37. #include <signal.h>
  38. #include <ctype.h>
  39. #include <time.h>
  40. #include <sys/types.h>
  41. #include <sys/time.h>
  42. #if HAVE_SYS_RESOURCE_H
  43. #include <sys/resource.h>
  44. #endif
  45. #include "gmp.h"
  46. /* SunOS 4 and HPUX 9 don't define a canonical SIGSTKSZ, use a default. */
  47. #ifndef SIGSTKSZ
  48. #define SIGSTKSZ  4096
  49. #endif
  50. #define TIME(t,func)
  51.   do { int __t0, __tmp;
  52.     __t0 = cputime ();
  53.     {func;}
  54.     __tmp = cputime () - __t0;
  55.     (t) = __tmp;
  56.   } while (0)
  57. /* GMP version 1.x compatibility.  */
  58. #if ! (__GNU_MP_VERSION >= 2)
  59. typedef MP_INT __mpz_struct;
  60. typedef __mpz_struct mpz_t[1];
  61. typedef __mpz_struct *mpz_ptr;
  62. #define mpz_fdiv_q mpz_div
  63. #define mpz_fdiv_r mpz_mod
  64. #define mpz_tdiv_q_2exp mpz_div_2exp
  65. #define mpz_sgn(Z) ((Z)->size < 0 ? -1 : (Z)->size > 0)
  66. #endif
  67. /* GMP version 2.0 compatibility.  */
  68. #if ! (__GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1)
  69. #define mpz_swap(a,b) 
  70.   do { __mpz_struct __t; __t = *a; *a = *b; *b = __t;} while (0)
  71. #endif
  72. jmp_buf errjmpbuf;
  73. enum op_t {NOP, LIT, NEG, NOT, PLUS, MINUS, MULT, DIV, MOD, REM, INVMOD, POW,
  74.    AND, IOR, XOR, SLL, SRA, POPCNT, HAMDIST, GCD, LCM, SQRT, ROOT, FAC,
  75.    LOG, LOG2, FERMAT, MERSENNE, FIBONACCI, RANDOM, NEXTPRIME, BINOM,
  76.    TIMING};
  77. /* Type for the expression tree.  */
  78. struct expr
  79. {
  80.   enum op_t op;
  81.   union
  82.   {
  83.     struct {struct expr *lhs, *rhs;} ops;
  84.     mpz_t val;
  85.   } operands;
  86. };
  87. typedef struct expr *expr_t;
  88. void cleanup_and_exit __GMP_PROTO ((int));
  89. char *skipspace __GMP_PROTO ((char *));
  90. void makeexp __GMP_PROTO ((expr_t *, enum op_t, expr_t, expr_t));
  91. void free_expr __GMP_PROTO ((expr_t));
  92. char *expr __GMP_PROTO ((char *, expr_t *));
  93. char *term __GMP_PROTO ((char *, expr_t *));
  94. char *power __GMP_PROTO ((char *, expr_t *));
  95. char *factor __GMP_PROTO ((char *, expr_t *));
  96. int match __GMP_PROTO ((char *, char *));
  97. int matchp __GMP_PROTO ((char *, char *));
  98. int cputime __GMP_PROTO ((void));
  99. void mpz_eval_expr __GMP_PROTO ((mpz_ptr, expr_t));
  100. void mpz_eval_mod_expr __GMP_PROTO ((mpz_ptr, expr_t, mpz_ptr));
  101. char *error;
  102. int flag_print = 1;
  103. int print_timing = 0;
  104. int flag_html = 0;
  105. int flag_wml = 0;
  106. int flag_splitup_output = 0;
  107. char *newline = "";
  108. gmp_randstate_t rstate;
  109. /* cputime() returns user CPU time measured in milliseconds.  */
  110. #if ! HAVE_CPUTIME
  111. #if HAVE_GETRUSAGE
  112. int
  113. cputime (void)
  114. {
  115.   struct rusage rus;
  116.   getrusage (0, &rus);
  117.   return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
  118. }
  119. #else
  120. #if HAVE_CLOCK
  121. int
  122. cputime (void)
  123. {
  124.   if (CLOCKS_PER_SEC < 100000)
  125.     return clock () * 1000 / CLOCKS_PER_SEC;
  126.   return clock () / (CLOCKS_PER_SEC / 1000);
  127. }
  128. #else
  129. int
  130. cputime (void)
  131. {
  132.   return 0;
  133. }
  134. #endif
  135. #endif
  136. #endif
  137. int
  138. stack_downwards_helper (char *xp)
  139. {
  140.   char  y;
  141.   return &y < xp;
  142. }
  143. int
  144. stack_downwards_p (void)
  145. {
  146.   char  x;
  147.   return stack_downwards_helper (&x);
  148. }
  149. void
  150. setup_error_handler (void)
  151. {
  152. #if HAVE_SIGACTION
  153.   struct sigaction act;
  154.   act.sa_handler = cleanup_and_exit;
  155.   sigemptyset (&(act.sa_mask));
  156. #define SIGNAL(sig)  sigaction (sig, &act, NULL)
  157. #else
  158.   struct { int sa_flags; } act;
  159. #define SIGNAL(sig)  signal (sig, cleanup_and_exit)
  160. #endif
  161.   act.sa_flags = 0;
  162.   /* Set up a stack for signal handling.  A typical cause of error is stack
  163.      overflow, and in such situation a signal can not be delivered on the
  164.      overflown stack.  */
  165. #if HAVE_SIGALTSTACK
  166.   {
  167.     /* AIX uses stack_t, MacOS uses struct sigaltstack, various other
  168.        systems have both. */
  169. #if HAVE_STACK_T
  170.     stack_t s;
  171. #else
  172.     struct sigaltstack s;
  173. #endif
  174.     s.ss_sp = malloc (SIGSTKSZ);
  175.     s.ss_size = SIGSTKSZ;
  176.     s.ss_flags = 0;
  177.     if (sigaltstack (&s, NULL) != 0)
  178.       perror("sigaltstack");
  179.     act.sa_flags = SA_ONSTACK;
  180.   }
  181. #else
  182. #if HAVE_SIGSTACK
  183.   {
  184.     struct sigstack s;
  185.     s.ss_sp = malloc (SIGSTKSZ);
  186.     if (stack_downwards_p ())
  187.       s.ss_sp += SIGSTKSZ;
  188.     s.ss_onstack = 0;
  189.     if (sigstack (&s, NULL) != 0)
  190.       perror("sigstack");
  191.     act.sa_flags = SA_ONSTACK;
  192.   }
  193. #else
  194. #endif
  195. #endif
  196. #ifdef LIMIT_RESOURCE_USAGE
  197.   {
  198.     struct rlimit limit;
  199.     limit.rlim_cur = limit.rlim_max = 0;
  200.     setrlimit (RLIMIT_CORE, &limit);
  201.     limit.rlim_cur = 3;
  202.     limit.rlim_max = 4;
  203.     setrlimit (RLIMIT_CPU, &limit);
  204.     limit.rlim_cur = limit.rlim_max = 16 * 1024 * 1024;
  205.     setrlimit (RLIMIT_DATA, &limit);
  206.     getrlimit (RLIMIT_STACK, &limit);
  207.     limit.rlim_cur = 4 * 1024 * 1024;
  208.     setrlimit (RLIMIT_STACK, &limit);
  209.     SIGNAL (SIGXCPU);
  210.   }
  211. #endif /* LIMIT_RESOURCE_USAGE */
  212.   SIGNAL (SIGILL);
  213.   SIGNAL (SIGSEGV);
  214. #ifdef SIGBUS /* not in mingw */
  215.   SIGNAL (SIGBUS);
  216. #endif
  217.   SIGNAL (SIGFPE);
  218.   SIGNAL (SIGABRT);
  219. }
  220. int
  221. main (int argc, char **argv)
  222. {
  223.   struct expr *e;
  224.   int i;
  225.   mpz_t r;
  226.   int errcode = 0;
  227.   char *str;
  228.   int base = 10;
  229.   setup_error_handler ();
  230.   gmp_randinit (rstate, GMP_RAND_ALG_LC, 128);
  231.   {
  232. #if HAVE_GETTIMEOFDAY
  233.     struct timeval tv;
  234.     gettimeofday (&tv, NULL);
  235.     gmp_randseed_ui (rstate, tv.tv_sec + tv.tv_usec);
  236. #else
  237.     time_t t;
  238.     time (&t);
  239.     gmp_randseed_ui (rstate, t);
  240. #endif
  241.   }
  242.   mpz_init (r);
  243.   while (argc > 1 && argv[1][0] == '-')
  244.     {
  245.       char *arg = argv[1];
  246.       if (arg[1] >= '0' && arg[1] <= '9')
  247. break;
  248.       if (arg[1] == 't')
  249. print_timing = 1;
  250.       else if (arg[1] == 'b' && arg[2] >= '0' && arg[2] <= '9')
  251. {
  252.   base = atoi (arg + 2);
  253.   if (base < 2 || base > 62)
  254.     {
  255.       fprintf (stderr, "error: invalid output basen");
  256.       exit (-1);
  257.     }
  258. }
  259.       else if (arg[1] == 'b' && arg[2] == 0)
  260. base = 2;
  261.       else if (arg[1] == 'x' && arg[2] == 0)
  262. base = 16;
  263.       else if (arg[1] == 'X' && arg[2] == 0)
  264. base = -16;
  265.       else if (arg[1] == 'o' && arg[2] == 0)
  266. base = 8;
  267.       else if (arg[1] == 'd' && arg[2] == 0)
  268. base = 10;
  269.       else if (arg[1] == 'v' && arg[2] == 0)
  270. {
  271.   printf ("pexpr linked to gmp %sn", __gmp_version);
  272. }
  273.       else if (strcmp (arg, "-html") == 0)
  274. {
  275.   flag_html = 1;
  276.   newline = "<br>";
  277. }
  278.       else if (strcmp (arg, "-wml") == 0)
  279. {
  280.   flag_wml = 1;
  281.   newline = "<br/>";
  282. }
  283.       else if (strcmp (arg, "-split") == 0)
  284. {
  285.   flag_splitup_output = 1;
  286. }
  287.       else if (strcmp (arg, "-noprint") == 0)
  288. {
  289.   flag_print = 0;
  290. }
  291.       else
  292. {
  293.   fprintf (stderr, "error: unknown option `%s'n", arg);
  294.   exit (-1);
  295. }
  296.       argv++;
  297.       argc--;
  298.     }
  299.   for (i = 1; i < argc; i++)
  300.     {
  301.       int s;
  302.       int jmpval;
  303.       /* Set up error handler for parsing expression.  */
  304.       jmpval = setjmp (errjmpbuf);
  305.       if (jmpval != 0)
  306. {
  307.   fprintf (stderr, "error: %s%sn", error, newline);
  308.   fprintf (stderr, "       %s%sn", argv[i], newline);
  309.   if (! flag_html)
  310.     {
  311.       /* ??? Dunno how to align expression position with arrow in
  312.  HTML ??? */
  313.       fprintf (stderr, "       ");
  314.       for (s = jmpval - (long) argv[i]; --s >= 0; )
  315. putc (' ', stderr);
  316.       fprintf (stderr, "^n");
  317.     }
  318.   errcode |= 1;
  319.   continue;
  320. }
  321.       str = expr (argv[i], &e);
  322.       if (str[0] != 0)
  323. {
  324.   fprintf (stderr,
  325.    "error: garbage where end of expression expected%sn",
  326.    newline);
  327.   fprintf (stderr, "       %s%sn", argv[i], newline);
  328.   if (! flag_html)
  329.     {
  330.       /* ??? Dunno how to align expression position with arrow in
  331.  HTML ??? */
  332.       fprintf (stderr, "        ");
  333.       for (s = str - argv[i]; --s; )
  334. putc (' ', stderr);
  335.       fprintf (stderr, "^n");
  336.     }
  337.   errcode |= 1;
  338.   free_expr (e);
  339.   continue;
  340. }
  341.       /* Set up error handler for evaluating expression.  */
  342.       if (setjmp (errjmpbuf))
  343. {
  344.   fprintf (stderr, "error: %s%sn", error, newline);
  345.   fprintf (stderr, "       %s%sn", argv[i], newline);
  346.   if (! flag_html)
  347.     {
  348.       /* ??? Dunno how to align expression position with arrow in
  349.  HTML ??? */
  350.       fprintf (stderr, "       ");
  351.       for (s = str - argv[i]; --s >= 0; )
  352. putc (' ', stderr);
  353.       fprintf (stderr, "^n");
  354.     }
  355.   errcode |= 2;
  356.   continue;
  357. }
  358.       if (print_timing)
  359. {
  360.   int t;
  361.   TIME (t, mpz_eval_expr (r, e));
  362.   printf ("computation took %d ms%sn", t, newline);
  363. }
  364.       else
  365. mpz_eval_expr (r, e);
  366.       if (flag_print)
  367. {
  368.   size_t out_len;
  369.   char *tmp, *s;
  370.   out_len = mpz_sizeinbase (r, base >= 0 ? base : -base) + 2;
  371. #ifdef LIMIT_RESOURCE_USAGE
  372.   if (out_len > 100000)
  373.     {
  374.       printf ("result is about %ld digits, not printing it%sn",
  375.       (long) out_len - 3, newline);
  376.       exit (-2);
  377.     }
  378. #endif
  379.   tmp = malloc (out_len);
  380.   if (print_timing)
  381.     {
  382.       int t;
  383.       printf ("output conversion ");
  384.       TIME (t, mpz_get_str (tmp, base, r));
  385.       printf ("took %d ms%sn", t, newline);
  386.     }
  387.   else
  388.     mpz_get_str (tmp, base, r);
  389.   out_len = strlen (tmp);
  390.   if (flag_splitup_output)
  391.     {
  392.       for (s = tmp; out_len > 80; s += 80)
  393. {
  394.   fwrite (s, 1, 80, stdout);
  395.   printf ("%sn", newline);
  396.   out_len -= 80;
  397. }
  398.       fwrite (s, 1, out_len, stdout);
  399.     }
  400.   else
  401.     {
  402.       fwrite (tmp, 1, out_len, stdout);
  403.     }
  404.   free (tmp);
  405.   printf ("%sn", newline);
  406. }
  407.       else
  408. {
  409.   printf ("result is approximately %ld digits%sn",
  410.   (long) mpz_sizeinbase (r, base >= 0 ? base : -base),
  411.   newline);
  412. }
  413.       free_expr (e);
  414.     }
  415.   exit (errcode);
  416. }
  417. char *
  418. expr (char *str, expr_t *e)
  419. {
  420.   expr_t e2;
  421.   str = skipspace (str);
  422.   if (str[0] == '+')
  423.     {
  424.       str = term (str + 1, e);
  425.     }
  426.   else if (str[0] == '-')
  427.     {
  428.       str = term (str + 1, e);
  429.       makeexp (e, NEG, *e, NULL);
  430.     }
  431.   else if (str[0] == '~')
  432.     {
  433.       str = term (str + 1, e);
  434.       makeexp (e, NOT, *e, NULL);
  435.     }
  436.   else
  437.     {
  438.       str = term (str, e);
  439.     }
  440.   for (;;)
  441.     {
  442.       str = skipspace (str);
  443.       switch (str[0])
  444. {
  445. case 'p':
  446.   if (match ("plus", str))
  447.     {
  448.       str = term (str + 4, &e2);
  449.       makeexp (e, PLUS, *e, e2);
  450.     }
  451.   else
  452.     return str;
  453.   break;
  454. case 'm':
  455.   if (match ("minus", str))
  456.     {
  457.       str = term (str + 5, &e2);
  458.       makeexp (e, MINUS, *e, e2);
  459.     }
  460.   else
  461.     return str;
  462.   break;
  463. case '+':
  464.   str = term (str + 1, &e2);
  465.   makeexp (e, PLUS, *e, e2);
  466.   break;
  467. case '-':
  468.   str = term (str + 1, &e2);
  469.   makeexp (e, MINUS, *e, e2);
  470.   break;
  471. default:
  472.   return str;
  473. }
  474.     }
  475. }
  476. char *
  477. term (char *str, expr_t *e)
  478. {
  479.   expr_t e2;
  480.   str = power (str, e);
  481.   for (;;)
  482.     {
  483.       str = skipspace (str);
  484.       switch (str[0])
  485. {
  486. case 'm':
  487.   if (match ("mul", str))
  488.     {
  489.       str = power (str + 3, &e2);
  490.       makeexp (e, MULT, *e, e2);
  491.       break;
  492.     }
  493.   if (match ("mod", str))
  494.     {
  495.       str = power (str + 3, &e2);
  496.       makeexp (e, MOD, *e, e2);
  497.       break;
  498.     }
  499.   return str;
  500. case 'd':
  501.   if (match ("div", str))
  502.     {
  503.       str = power (str + 3, &e2);
  504.       makeexp (e, DIV, *e, e2);
  505.       break;
  506.     }
  507.   return str;
  508. case 'r':
  509.   if (match ("rem", str))
  510.     {
  511.       str = power (str + 3, &e2);
  512.       makeexp (e, REM, *e, e2);
  513.       break;
  514.     }
  515.   return str;
  516. case 'i':
  517.   if (match ("invmod", str))
  518.     {
  519.       str = power (str + 6, &e2);
  520.       makeexp (e, REM, *e, e2);
  521.       break;
  522.     }
  523.   return str;
  524. case 't':
  525.   if (match ("times", str))
  526.     {
  527.       str = power (str + 5, &e2);
  528.       makeexp (e, MULT, *e, e2);
  529.       break;
  530.     }
  531.   if (match ("thru", str))
  532.     {
  533.       str = power (str + 4, &e2);
  534.       makeexp (e, DIV, *e, e2);
  535.       break;
  536.     }
  537.   if (match ("through", str))
  538.     {
  539.       str = power (str + 7, &e2);
  540.       makeexp (e, DIV, *e, e2);
  541.       break;
  542.     }
  543.   return str;
  544. case '*':
  545.   str = power (str + 1, &e2);
  546.   makeexp (e, MULT, *e, e2);
  547.   break;
  548. case '/':
  549.   str = power (str + 1, &e2);
  550.   makeexp (e, DIV, *e, e2);
  551.   break;
  552. case '%':
  553.   str = power (str + 1, &e2);
  554.   makeexp (e, MOD, *e, e2);
  555.   break;
  556. default:
  557.   return str;
  558. }
  559.     }
  560. }
  561. char *
  562. power (char *str, expr_t *e)
  563. {
  564.   expr_t e2;
  565.   str = factor (str, e);
  566.   while (str[0] == '!')
  567.     {
  568.       str++;
  569.       makeexp (e, FAC, *e, NULL);
  570.     }
  571.   str = skipspace (str);
  572.   if (str[0] == '^')
  573.     {
  574.       str = power (str + 1, &e2);
  575.       makeexp (e, POW, *e, e2);
  576.     }
  577.   return str;
  578. }
  579. int
  580. match (char *s, char *str)
  581. {
  582.   char *ostr = str;
  583.   int i;
  584.   for (i = 0; s[i] != 0; i++)
  585.     {
  586.       if (str[i] != s[i])
  587. return 0;
  588.     }
  589.   str = skipspace (str + i);
  590.   return str - ostr;
  591. }
  592. int
  593. matchp (char *s, char *str)
  594. {
  595.   char *ostr = str;
  596.   int i;
  597.   for (i = 0; s[i] != 0; i++)
  598.     {
  599.       if (str[i] != s[i])
  600. return 0;
  601.     }
  602.   str = skipspace (str + i);
  603.   if (str[0] == '(')
  604.     return str - ostr + 1;
  605.   return 0;
  606. }
  607. struct functions
  608. {
  609.   char *spelling;
  610.   enum op_t op;
  611.   int arity; /* 1 or 2 means real arity; 0 means arbitrary.  */
  612. };
  613. struct functions fns[] =
  614. {
  615.   {"sqrt", SQRT, 1},
  616. #if __GNU_MP_VERSION >= 2
  617.   {"root", ROOT, 2},
  618.   {"popc", POPCNT, 1},
  619.   {"hamdist", HAMDIST, 2},
  620. #endif
  621.   {"gcd", GCD, 0},
  622. #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
  623.   {"lcm", LCM, 0},
  624. #endif
  625.   {"and", AND, 0},
  626.   {"ior", IOR, 0},
  627. #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
  628.   {"xor", XOR, 0},
  629. #endif
  630.   {"plus", PLUS, 0},
  631.   {"pow", POW, 2},
  632.   {"minus", MINUS, 2},
  633.   {"mul", MULT, 0},
  634.   {"div", DIV, 2},
  635.   {"mod", MOD, 2},
  636.   {"rem", REM, 2},
  637. #if __GNU_MP_VERSION >= 2
  638.   {"invmod", INVMOD, 2},
  639. #endif
  640.   {"log", LOG, 2},
  641.   {"log2", LOG2, 1},
  642.   {"F", FERMAT, 1},
  643.   {"M", MERSENNE, 1},
  644.   {"fib", FIBONACCI, 1},
  645.   {"Fib", FIBONACCI, 1},
  646.   {"random", RANDOM, 1},
  647.   {"nextprime", NEXTPRIME, 1},
  648.   {"binom", BINOM, 2},
  649.   {"binomial", BINOM, 2},
  650.   {"fac", FAC, 1},
  651.   {"fact", FAC, 1},
  652.   {"factorial", FAC, 1},
  653.   {"time", TIMING, 1},
  654.   {"", NOP, 0}
  655. };
  656. char *
  657. factor (char *str, expr_t *e)
  658. {
  659.   expr_t e1, e2;
  660.   str = skipspace (str);
  661.   if (isalpha (str[0]))
  662.     {
  663.       int i;
  664.       int cnt;
  665.       for (i = 0; fns[i].op != NOP; i++)
  666. {
  667.   if (fns[i].arity == 1)
  668.     {
  669.       cnt = matchp (fns[i].spelling, str);
  670.       if (cnt != 0)
  671. {
  672.   str = expr (str + cnt, &e1);
  673.   str = skipspace (str);
  674.   if (str[0] != ')')
  675.     {
  676.       error = "expected `)'";
  677.       longjmp (errjmpbuf, (int) (long) str);
  678.     }
  679.   makeexp (e, fns[i].op, e1, NULL);
  680.   return str + 1;
  681. }
  682.     }
  683. }
  684.       for (i = 0; fns[i].op != NOP; i++)
  685. {
  686.   if (fns[i].arity != 1)
  687.     {
  688.       cnt = matchp (fns[i].spelling, str);
  689.       if (cnt != 0)
  690. {
  691.   str = expr (str + cnt, &e1);
  692.   str = skipspace (str);
  693.   if (str[0] != ',')
  694.     {
  695.       error = "expected `,' and another operand";
  696.       longjmp (errjmpbuf, (int) (long) str);
  697.     }
  698.   str = skipspace (str + 1);
  699.   str = expr (str, &e2);
  700.   str = skipspace (str);
  701.   if (fns[i].arity == 0)
  702.     {
  703.       while (str[0] == ',')
  704. {
  705.   makeexp (&e1, fns[i].op, e1, e2);
  706.   str = skipspace (str + 1);
  707.   str = expr (str, &e2);
  708.   str = skipspace (str);
  709. }
  710.     }
  711.   if (str[0] != ')')
  712.     {
  713.       error = "expected `)'";
  714.       longjmp (errjmpbuf, (int) (long) str);
  715.     }
  716.   makeexp (e, fns[i].op, e1, e2);
  717.   return str + 1;
  718. }
  719.     }
  720. }
  721.     }
  722.   if (str[0] == '(')
  723.     {
  724.       str = expr (str + 1, e);
  725.       str = skipspace (str);
  726.       if (str[0] != ')')
  727. {
  728.   error = "expected `)'";
  729.   longjmp (errjmpbuf, (int) (long) str);
  730. }
  731.       str++;
  732.     }
  733.   else if (str[0] >= '0' && str[0] <= '9')
  734.     {
  735.       expr_t res;
  736.       char *s, *sc;
  737.       res = malloc (sizeof (struct expr));
  738.       res -> op = LIT;
  739.       mpz_init (res->operands.val);
  740.       s = str;
  741.       while (isalnum (str[0]))
  742. str++;
  743.       sc = malloc (str - s + 1);
  744.       memcpy (sc, s, str - s);
  745.       sc[str - s] = 0;
  746.       mpz_set_str (res->operands.val, sc, 0);
  747.       *e = res;
  748.       free (sc);
  749.     }
  750.   else
  751.     {
  752.       error = "operand expected";
  753.       longjmp (errjmpbuf, (int) (long) str);
  754.     }
  755.   return str;
  756. }
  757. char *
  758. skipspace (char *str)
  759. {
  760.   while (str[0] == ' ')
  761.     str++;
  762.   return str;
  763. }
  764. /* Make a new expression with operation OP and right hand side
  765.    RHS and left hand side lhs.  Put the result in R.  */
  766. void
  767. makeexp (expr_t *r, enum op_t op, expr_t lhs, expr_t rhs)
  768. {
  769.   expr_t res;
  770.   res = malloc (sizeof (struct expr));
  771.   res -> op = op;
  772.   res -> operands.ops.lhs = lhs;
  773.   res -> operands.ops.rhs = rhs;
  774.   *r = res;
  775.   return;
  776. }
  777. /* Free the memory used by expression E.  */
  778. void
  779. free_expr (expr_t e)
  780. {
  781.   if (e->op != LIT)
  782.     {
  783.       free_expr (e->operands.ops.lhs);
  784.       if (e->operands.ops.rhs != NULL)
  785. free_expr (e->operands.ops.rhs);
  786.     }
  787.   else
  788.     {
  789.       mpz_clear (e->operands.val);
  790.     }
  791. }
  792. /* Evaluate the expression E and put the result in R.  */
  793. void
  794. mpz_eval_expr (mpz_ptr r, expr_t e)
  795. {
  796.   mpz_t lhs, rhs;
  797.   switch (e->op)
  798.     {
  799.     case LIT:
  800.       mpz_set (r, e->operands.val);
  801.       return;
  802.     case PLUS:
  803.       mpz_init (lhs); mpz_init (rhs);
  804.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  805.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  806.       mpz_add (r, lhs, rhs);
  807.       mpz_clear (lhs); mpz_clear (rhs);
  808.       return;
  809.     case MINUS:
  810.       mpz_init (lhs); mpz_init (rhs);
  811.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  812.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  813.       mpz_sub (r, lhs, rhs);
  814.       mpz_clear (lhs); mpz_clear (rhs);
  815.       return;
  816.     case MULT:
  817.       mpz_init (lhs); mpz_init (rhs);
  818.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  819.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  820.       mpz_mul (r, lhs, rhs);
  821.       mpz_clear (lhs); mpz_clear (rhs);
  822.       return;
  823.     case DIV:
  824.       mpz_init (lhs); mpz_init (rhs);
  825.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  826.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  827.       mpz_fdiv_q (r, lhs, rhs);
  828.       mpz_clear (lhs); mpz_clear (rhs);
  829.       return;
  830.     case MOD:
  831.       mpz_init (rhs);
  832.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  833.       mpz_abs (rhs, rhs);
  834.       mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs);
  835.       mpz_clear (rhs);
  836.       return;
  837.     case REM:
  838.       /* Check if lhs operand is POW expression and optimize for that case.  */
  839.       if (e->operands.ops.lhs->op == POW)
  840. {
  841.   mpz_t powlhs, powrhs;
  842.   mpz_init (powlhs);
  843.   mpz_init (powrhs);
  844.   mpz_init (rhs);
  845.   mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs);
  846.   mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs);
  847.   mpz_eval_expr (rhs, e->operands.ops.rhs);
  848.   mpz_powm (r, powlhs, powrhs, rhs);
  849.   if (mpz_cmp_si (rhs, 0L) < 0)
  850.     mpz_neg (r, r);
  851.   mpz_clear (powlhs);
  852.   mpz_clear (powrhs);
  853.   mpz_clear (rhs);
  854.   return;
  855. }
  856.       mpz_init (lhs); mpz_init (rhs);
  857.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  858.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  859.       mpz_fdiv_r (r, lhs, rhs);
  860.       mpz_clear (lhs); mpz_clear (rhs);
  861.       return;
  862. #if __GNU_MP_VERSION >= 2
  863.     case INVMOD:
  864.       mpz_init (lhs); mpz_init (rhs);
  865.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  866.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  867.       mpz_invert (r, lhs, rhs);
  868.       mpz_clear (lhs); mpz_clear (rhs);
  869.       return;
  870. #endif
  871.     case POW:
  872.       mpz_init (lhs); mpz_init (rhs);
  873.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  874.       if (mpz_cmpabs_ui (lhs, 1) <= 0)
  875. {
  876.   /* For 0^rhs and 1^rhs, we just need to verify that
  877.      rhs is well-defined.  For (-1)^rhs we need to
  878.      determine (rhs mod 2).  For simplicity, compute
  879.      (rhs mod 2) for all three cases.  */
  880.   expr_t two, et;
  881.   two = malloc (sizeof (struct expr));
  882.   two -> op = LIT;
  883.   mpz_init_set_ui (two->operands.val, 2L);
  884.   makeexp (&et, MOD, e->operands.ops.rhs, two);
  885.   e->operands.ops.rhs = et;
  886. }
  887.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  888.       if (mpz_cmp_si (rhs, 0L) == 0)
  889. /* x^0 is 1 */
  890. mpz_set_ui (r, 1L);
  891.       else if (mpz_cmp_si (lhs, 0L) == 0)
  892. /* 0^y (where y != 0) is 0 */
  893. mpz_set_ui (r, 0L);
  894.       else if (mpz_cmp_ui (lhs, 1L) == 0)
  895. /* 1^y is 1 */
  896. mpz_set_ui (r, 1L);
  897.       else if (mpz_cmp_si (lhs, -1L) == 0)
  898. /* (-1)^y just depends on whether y is even or odd */
  899. mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L);
  900.       else if (mpz_cmp_si (rhs, 0L) < 0)
  901. /* x^(-n) is 0 */
  902. mpz_set_ui (r, 0L);
  903.       else
  904. {
  905.   unsigned long int cnt;
  906.   unsigned long int y;
  907.   /* error if exponent does not fit into an unsigned long int.  */
  908.   if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
  909.     goto pow_err;
  910.   y = mpz_get_ui (rhs);
  911.   /* x^y == (x/(2^c))^y * 2^(c*y) */
  912. #if __GNU_MP_VERSION >= 2
  913.   cnt = mpz_scan1 (lhs, 0);
  914. #else
  915.   cnt = 0;
  916. #endif
  917.   if (cnt != 0)
  918.     {
  919.       if (y * cnt / cnt != y)
  920. goto pow_err;
  921.       mpz_tdiv_q_2exp (lhs, lhs, cnt);
  922.       mpz_pow_ui (r, lhs, y);
  923.       mpz_mul_2exp (r, r, y * cnt);
  924.     }
  925.   else
  926.     mpz_pow_ui (r, lhs, y);
  927. }
  928.       mpz_clear (lhs); mpz_clear (rhs);
  929.       return;
  930.     pow_err:
  931.       error = "result of `pow' operator too large";
  932.       mpz_clear (lhs); mpz_clear (rhs);
  933.       longjmp (errjmpbuf, 1);
  934.     case GCD:
  935.       mpz_init (lhs); mpz_init (rhs);
  936.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  937.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  938.       mpz_gcd (r, lhs, rhs);
  939.       mpz_clear (lhs); mpz_clear (rhs);
  940.       return;
  941. #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
  942.     case LCM:
  943.       mpz_init (lhs); mpz_init (rhs);
  944.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  945.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  946.       mpz_lcm (r, lhs, rhs);
  947.       mpz_clear (lhs); mpz_clear (rhs);
  948.       return;
  949. #endif
  950.     case AND:
  951.       mpz_init (lhs); mpz_init (rhs);
  952.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  953.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  954.       mpz_and (r, lhs, rhs);
  955.       mpz_clear (lhs); mpz_clear (rhs);
  956.       return;
  957.     case IOR:
  958.       mpz_init (lhs); mpz_init (rhs);
  959.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  960.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  961.       mpz_ior (r, lhs, rhs);
  962.       mpz_clear (lhs); mpz_clear (rhs);
  963.       return;
  964. #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
  965.     case XOR:
  966.       mpz_init (lhs); mpz_init (rhs);
  967.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  968.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  969.       mpz_xor (r, lhs, rhs);
  970.       mpz_clear (lhs); mpz_clear (rhs);
  971.       return;
  972. #endif
  973.     case NEG:
  974.       mpz_eval_expr (r, e->operands.ops.lhs);
  975.       mpz_neg (r, r);
  976.       return;
  977.     case NOT:
  978.       mpz_eval_expr (r, e->operands.ops.lhs);
  979.       mpz_com (r, r);
  980.       return;
  981.     case SQRT:
  982.       mpz_init (lhs);
  983.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  984.       if (mpz_sgn (lhs) < 0)
  985. {
  986.   error = "cannot take square root of negative numbers";
  987.   mpz_clear (lhs);
  988.   longjmp (errjmpbuf, 1);
  989. }
  990.       mpz_sqrt (r, lhs);
  991.       return;
  992. #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
  993.     case ROOT:
  994.       mpz_init (lhs); mpz_init (rhs);
  995.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  996.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  997.       if (mpz_sgn (rhs) <= 0)
  998. {
  999.   error = "cannot take non-positive root orders";
  1000.   mpz_clear (lhs); mpz_clear (rhs);
  1001.   longjmp (errjmpbuf, 1);
  1002. }
  1003.       if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0)
  1004. {
  1005.   error = "cannot take even root orders of negative numbers";
  1006.   mpz_clear (lhs); mpz_clear (rhs);
  1007.   longjmp (errjmpbuf, 1);
  1008. }
  1009.       {
  1010. unsigned long int nth = mpz_get_ui (rhs);
  1011. if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
  1012.   {
  1013.     /* If we are asked to take an awfully large root order, cheat and
  1014.        ask for the largest order we can pass to mpz_root.  This saves
  1015.        some error prone special cases.  */
  1016.     nth = ~(unsigned long int) 0;
  1017.   }
  1018. mpz_root (r, lhs, nth);
  1019.       }
  1020.       mpz_clear (lhs); mpz_clear (rhs);
  1021.       return;
  1022. #endif
  1023.     case FAC:
  1024.       mpz_eval_expr (r, e->operands.ops.lhs);
  1025.       if (mpz_size (r) > 1)
  1026. {
  1027.   error = "result of `!' operator too large";
  1028.   longjmp (errjmpbuf, 1);
  1029. }
  1030.       mpz_fac_ui (r, mpz_get_ui (r));
  1031.       return;
  1032. #if __GNU_MP_VERSION >= 2
  1033.     case POPCNT:
  1034.       mpz_eval_expr (r, e->operands.ops.lhs);
  1035.       { long int cnt;
  1036. cnt = mpz_popcount (r);
  1037. mpz_set_si (r, cnt);
  1038.       }
  1039.       return;
  1040.     case HAMDIST:
  1041.       { long int cnt;
  1042. mpz_init (lhs); mpz_init (rhs);
  1043. mpz_eval_expr (lhs, e->operands.ops.lhs);
  1044. mpz_eval_expr (rhs, e->operands.ops.rhs);
  1045. cnt = mpz_hamdist (lhs, rhs);
  1046. mpz_clear (lhs); mpz_clear (rhs);
  1047. mpz_set_si (r, cnt);
  1048.       }
  1049.       return;
  1050. #endif
  1051.     case LOG2:
  1052.       mpz_eval_expr (r, e->operands.ops.lhs);
  1053.       { unsigned long int cnt;
  1054. if (mpz_sgn (r) <= 0)
  1055.   {
  1056.     error = "logarithm of non-positive number";
  1057.     longjmp (errjmpbuf, 1);
  1058.   }
  1059. cnt = mpz_sizeinbase (r, 2);
  1060. mpz_set_ui (r, cnt - 1);
  1061.       }
  1062.       return;
  1063.     case LOG:
  1064.       { unsigned long int cnt;
  1065. mpz_init (lhs); mpz_init (rhs);
  1066. mpz_eval_expr (lhs, e->operands.ops.lhs);
  1067. mpz_eval_expr (rhs, e->operands.ops.rhs);
  1068. if (mpz_sgn (lhs) <= 0)
  1069.   {
  1070.     error = "logarithm of non-positive number";
  1071.     mpz_clear (lhs); mpz_clear (rhs);
  1072.     longjmp (errjmpbuf, 1);
  1073.   }
  1074. if (mpz_cmp_ui (rhs, 256) >= 0)
  1075.   {
  1076.     error = "logarithm base too large";
  1077.     mpz_clear (lhs); mpz_clear (rhs);
  1078.     longjmp (errjmpbuf, 1);
  1079.   }
  1080. cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs));
  1081. mpz_set_ui (r, cnt - 1);
  1082. mpz_clear (lhs); mpz_clear (rhs);
  1083.       }
  1084.       return;
  1085.     case FERMAT:
  1086.       {
  1087. unsigned long int t;
  1088. mpz_init (lhs);
  1089. mpz_eval_expr (lhs, e->operands.ops.lhs);
  1090. t = (unsigned long int) 1 << mpz_get_ui (lhs);
  1091. if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0)
  1092.   {
  1093.     error = "too large Mersenne number index";
  1094.     mpz_clear (lhs);
  1095.     longjmp (errjmpbuf, 1);
  1096.   }
  1097. mpz_set_ui (r, 1);
  1098. mpz_mul_2exp (r, r, t);
  1099. mpz_add_ui (r, r, 1);
  1100. mpz_clear (lhs);
  1101.       }
  1102.       return;
  1103.     case MERSENNE:
  1104.       mpz_init (lhs);
  1105.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  1106.       if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0)
  1107. {
  1108.   error = "too large Mersenne number index";
  1109.   mpz_clear (lhs);
  1110.   longjmp (errjmpbuf, 1);
  1111. }
  1112.       mpz_set_ui (r, 1);
  1113.       mpz_mul_2exp (r, r, mpz_get_ui (lhs));
  1114.       mpz_sub_ui (r, r, 1);
  1115.       mpz_clear (lhs);
  1116.       return;
  1117.     case FIBONACCI:
  1118.       { mpz_t t;
  1119. unsigned long int n, i;
  1120. mpz_init (lhs);
  1121. mpz_eval_expr (lhs, e->operands.ops.lhs);
  1122. if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0)
  1123.   {
  1124.     error = "Fibonacci index out of range";
  1125.     mpz_clear (lhs);
  1126.     longjmp (errjmpbuf, 1);
  1127.   }
  1128. n = mpz_get_ui (lhs);
  1129. mpz_clear (lhs);
  1130. #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1
  1131. mpz_fib_ui (r, n);
  1132. #else
  1133. mpz_init_set_ui (t, 1);
  1134. mpz_set_ui (r, 1);
  1135. if (n <= 2)
  1136.   mpz_set_ui (r, 1);
  1137. else
  1138.   {
  1139.     for (i = 3; i <= n; i++)
  1140.       {
  1141. mpz_add (t, t, r);
  1142. mpz_swap (t, r);
  1143.       }
  1144.   }
  1145. mpz_clear (t);
  1146. #endif
  1147.       }
  1148.       return;
  1149.     case RANDOM:
  1150.       {
  1151. unsigned long int n;
  1152. mpz_init (lhs);
  1153. mpz_eval_expr (lhs, e->operands.ops.lhs);
  1154. if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0)
  1155.   {
  1156.     error = "random number size out of range";
  1157.     mpz_clear (lhs);
  1158.     longjmp (errjmpbuf, 1);
  1159.   }
  1160. n = mpz_get_ui (lhs);
  1161. mpz_clear (lhs);
  1162. mpz_urandomb (r, rstate, n);
  1163.       }
  1164.       return;
  1165.     case NEXTPRIME:
  1166.       {
  1167. mpz_eval_expr (r, e->operands.ops.lhs);
  1168. mpz_nextprime (r, r);
  1169.       }
  1170.       return;
  1171.     case BINOM:
  1172.       mpz_init (lhs); mpz_init (rhs);
  1173.       mpz_eval_expr (lhs, e->operands.ops.lhs);
  1174.       mpz_eval_expr (rhs, e->operands.ops.rhs);
  1175.       {
  1176. unsigned long int k;
  1177. if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0)
  1178.   {
  1179.     error = "k too large in (n over k) expression";
  1180.     mpz_clear (lhs); mpz_clear (rhs);
  1181.     longjmp (errjmpbuf, 1);
  1182.   }
  1183. k = mpz_get_ui (rhs);
  1184. mpz_bin_ui (r, lhs, k);
  1185.       }
  1186.       mpz_clear (lhs); mpz_clear (rhs);
  1187.       return;
  1188.     case TIMING:
  1189.       {
  1190. int t0;
  1191. t0 = cputime ();
  1192. mpz_eval_expr (r, e->operands.ops.lhs);
  1193. printf ("time: %dn", cputime () - t0);
  1194.       }
  1195.       return;
  1196.     default:
  1197.       abort ();
  1198.     }
  1199. }
  1200. /* Evaluate the expression E modulo MOD and put the result in R.  */
  1201. void
  1202. mpz_eval_mod_expr (mpz_ptr r, expr_t e, mpz_ptr mod)
  1203. {
  1204.   mpz_t lhs, rhs;
  1205.   switch (e->op)
  1206.     {
  1207.       case POW:
  1208. mpz_init (lhs); mpz_init (rhs);
  1209. mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
  1210. mpz_eval_expr (rhs, e->operands.ops.rhs);
  1211. mpz_powm (r, lhs, rhs, mod);
  1212. mpz_clear (lhs); mpz_clear (rhs);
  1213. return;
  1214.       case PLUS:
  1215. mpz_init (lhs); mpz_init (rhs);
  1216. mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
  1217. mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
  1218. mpz_add (r, lhs, rhs);
  1219. if (mpz_cmp_si (r, 0L) < 0)
  1220.   mpz_add (r, r, mod);
  1221. else if (mpz_cmp (r, mod) >= 0)
  1222.   mpz_sub (r, r, mod);
  1223. mpz_clear (lhs); mpz_clear (rhs);
  1224. return;
  1225.       case MINUS:
  1226. mpz_init (lhs); mpz_init (rhs);
  1227. mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
  1228. mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
  1229. mpz_sub (r, lhs, rhs);
  1230. if (mpz_cmp_si (r, 0L) < 0)
  1231.   mpz_add (r, r, mod);
  1232. else if (mpz_cmp (r, mod) >= 0)
  1233.   mpz_sub (r, r, mod);
  1234. mpz_clear (lhs); mpz_clear (rhs);
  1235. return;
  1236.       case MULT:
  1237. mpz_init (lhs); mpz_init (rhs);
  1238. mpz_eval_mod_expr (lhs, e->operands.ops.lhs, mod);
  1239. mpz_eval_mod_expr (rhs, e->operands.ops.rhs, mod);
  1240. mpz_mul (r, lhs, rhs);
  1241. mpz_mod (r, r, mod);
  1242. mpz_clear (lhs); mpz_clear (rhs);
  1243. return;
  1244.       default:
  1245. mpz_init (lhs);
  1246. mpz_eval_expr (lhs, e);
  1247. mpz_mod (r, lhs, mod);
  1248. mpz_clear (lhs);
  1249. return;
  1250.     }
  1251. }
  1252. void
  1253. cleanup_and_exit (int sig)
  1254. {
  1255.   switch (sig) {
  1256. #ifdef LIMIT_RESOURCE_USAGE
  1257.   case SIGXCPU:
  1258.     printf ("expression took too long to evaluate%sn", newline);
  1259.     break;
  1260. #endif
  1261.   case SIGFPE:
  1262.     printf ("divide by zero%sn", newline);
  1263.     break;
  1264.   default:
  1265.     printf ("expression required too much memory to evaluate%sn", newline);
  1266.     break;
  1267.   }
  1268.   exit (-2);
  1269. }