[BACK]Return to pexpr.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / demos

Annotation of OpenXM_contrib/gmp/demos/pexpr.c, Revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>