home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / calc-2.9.0 / part02 < prev    next >
Text File  |  1993-12-07  |  61KB  |  2,429 lines

  1. Newsgroups: comp.sources.unix
  2. From: dbell@canb.auug.org.au (David I. Bell)
  3. Subject: v27i129: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part02/19
  4. References: <1.755316719.21314@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: dbell@canb.auug.org.au (David I. Bell)
  9. Posting-Number: Volume 27, Issue 129
  10. Archive-Name: calc-2.9.0/part02
  11.  
  12. #!/bin/sh
  13. # this is part 2 of a multipart archive
  14. # do not concatenate these parts, unpack them in order with /bin/sh
  15. # file calc2.9.0/alloc.c continued
  16. #
  17. CurArch=2
  18. if test ! -r s2_seq_.tmp
  19. then echo "Please unpack part 1 first!"
  20.      exit 1; fi
  21. ( read Scheck
  22.   if test "$Scheck" != $CurArch
  23.   then echo "Please unpack part $Scheck next!"
  24.        exit 1;
  25.   else exit 0; fi
  26. ) < s2_seq_.tmp || exit 1
  27. echo "x - Continuing file calc2.9.0/alloc.c"
  28. sed 's/^X//' << 'SHAR_EOF' >> calc2.9.0/alloc.c
  29. X
  30. X    assert(bucket >= QUANTUM_NBITS, 1);
  31. X    assert(bucket < NBUCKETS, 2);
  32. X    assert(!nextf[bucket], 3);
  33. X#ifndef NO_SBRK
  34. X    /*
  35. X     * Insure memory is allocated on a page boundary.
  36. X     * Should make getpageize() call?
  37. X     */
  38. X#define PAGE_SIZE (1<<10)
  39. X    siz = (u_int)sbrk(0);
  40. X    if(siz & (PAGE_SIZE-1))
  41. X        sbrk(PAGE_SIZE - (siz & (PAGE_SIZE-1)));
  42. X#endif
  43. X
  44. X    /* take 2k unless the block is bigger than that */
  45. X    rnu = (bucket <= 11) ? 11 : bucket;
  46. X    assert(rnu >= bucket, 4);
  47. X    nblks = 1L << (rnu - bucket); /* how many blocks to get */
  48. X    siz = 1L << rnu;
  49. X
  50. X#ifndef NO_SBRK
  51. X    op = (union overhead *)sbrk(siz);
  52. X    /* no more room! */
  53. X    if ((int)op == -1)
  54. X        return;
  55. X    /*
  56. X     * Round up to minimum allocation size boundary
  57. X     * and deduct from block count to reflect.
  58. X     */
  59. X    if((int)op & (QUANTUM-1))
  60. X    {
  61. X        op = (union overhead *)(((int)op + QUANTUM) &~ (QUANTUM-1));
  62. X        nblks--;
  63. X    }
  64. X#else
  65. X    op = (union overhead *)malloc(siz);
  66. X    /* no more room! */
  67. X    if (!op)
  68. X        return;
  69. X#endif
  70. X    /*
  71. X     * Add new memory allocated to the
  72. X     * free list for this hash bucket.
  73. X     */
  74. X    nextf[bucket] = op;
  75. X    siz = 1L << bucket;
  76. X    while (--nblks)
  77. X    {
  78. X        op->ov_next = (union overhead *)((caddr_t)op + siz);
  79. X        op = op->ov_next;
  80. X    }
  81. X}
  82. X
  83. X
  84. X/*
  85. X * NAME
  86. X *    mem_alloc - memory allocator
  87. X *
  88. X * SYNOPSIS
  89. X *    char *
  90. X *    mem_alloc()
  91. X *
  92. X * DESCRIPTION
  93. X *    Mem_alloc is used to allocate memory large enought to fit the requested
  94. X *    size, and on a boundary suitable for placing any value.
  95. X *
  96. X * RETURNS
  97. X *    char *, pointer to base of dynamic memory allocated
  98. X *
  99. X * CAVEAT
  100. X *    Use mem_free() when you are finished with the space.
  101. X */
  102. Xchar *
  103. Xmem_alloc(nbytes)
  104. X    register unsigned long int nbytes;
  105. X{
  106. X    register union overhead *p;
  107. X    register int    bucket;
  108. X    register unsigned long int shiftr;
  109. X
  110. X    if (nbytes > ((unsigned int) -1))
  111. X        return NULL;
  112. X    assert((watchloc == NULL) || (watchloc->ov_magic == MAGIC), 12);
  113. X    /*
  114. X     * Convert amount of memory requested into
  115. X     * closest block size stored in hash buckets
  116. X     * which satisfies request.  Account for
  117. X     * space used per block for accounting.
  118. X     */
  119. X    nbytes = (nbytes + sizeof (union overhead) + RSLOP + (QUANTUM-1)) &~ (QUANTUM-1);
  120. X    shiftr = (nbytes - 1) >> QUANTUM_NBITS;
  121. X    /* apart from this loop, this is O(1) */
  122. X    bucket = QUANTUM_NBITS;
  123. X    while(shiftr)
  124. X    {
  125. X        shiftr >>= 1;
  126. X        bucket++;
  127. X    }
  128. X
  129. X    /*
  130. X     * If nothing in hash bucket right now,
  131. X     * request more memory from the system.
  132. X     */
  133. X    if (!nextf[bucket])
  134. X        morecore(bucket);
  135. X    if (!(p = nextf[bucket]))
  136. X        return (char*)0;
  137. X    /* remove from linked list */
  138. X    nextf[bucket] = p->ov_next;
  139. X    p->ov_magic = MAGIC;
  140. X    p->ov_index = bucket;
  141. X#ifdef MSTATS
  142. X    nmalloc[bucket]++;
  143. X#endif
  144. X#ifdef RCHECK
  145. X    /*
  146. X     * Record allocated size of block and
  147. X     * bound space with magic numbers
  148. X     */
  149. X    if (nbytes <= (1L<<16))
  150. X        p->ov_size = nbytes - 1;
  151. X    p->ov_rmagic = RMAGIC;
  152. X    *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
  153. X#endif
  154. X    return ((char *)(p + 1));
  155. X}
  156. X
  157. X
  158. X/*
  159. X * NAME
  160. X *    mem_free - free memory
  161. X *
  162. X * SYNOPSIS
  163. X *    int
  164. X *    mem_free(cp)
  165. X *    char * cp;
  166. X *
  167. X * DESCRIPTION
  168. X *    Mem_free is used to release space allocated by mem_alloc
  169. X *    or mem_realloc.
  170. X *
  171. X * RETURNS
  172. X *    int
  173. X *
  174. X * CAVEAT
  175. X *    do not pass mem_free() an argument that was returned by mem_alloc()
  176. X *    or mem_realloc().
  177. X */
  178. Xint
  179. Xmem_free(cp)
  180. X    char *    cp;
  181. X{
  182. X    register u_int    bucket;
  183. X    register union overhead *op;
  184. X
  185. X    assert((watchloc == NULL) || (watchloc->ov_magic == MAGIC), 13);
  186. X    if (!cp)
  187. X        return;
  188. X    op = (union overhead *)cp - 1;
  189. X    assert(op->ov_magic == MAGIC, 5);    /* make sure it was in use */
  190. X    assert(op->ov_index < NBUCKETS, 6);
  191. X    assert(op->ov_index >= QUANTUM_NBITS, 7);
  192. X#ifdef RCHECK
  193. X    assert(op->ov_index > 16 || op->ov_size == (1L<<op->ov_index)-1, 8);
  194. X    assert(op->ov_rmagic == RMAGIC, 9);
  195. X    assert(op->ov_index > 16 || *(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC, 10);
  196. X#endif
  197. X#ifndef DEBUG
  198. X    if(op->ov_magic != MAGIC)
  199. X        return;        /* sanity */
  200. X#endif
  201. X    bucket = op->ov_index;
  202. X    op->ov_next = nextf[bucket];
  203. X    nextf[bucket] = op;
  204. X#ifdef MSTATS
  205. X    nmalloc[bucket]--;
  206. X#endif
  207. X}
  208. X
  209. X
  210. X/*
  211. X * NAME
  212. X *    findbucket - find a bucket
  213. X *
  214. X * SYNOPSIS
  215. X *    int
  216. X *    findbucket(freep, srchlen)
  217. X *    union overhead * freep;
  218. X *    int srchlen;
  219. X *
  220. X * DESCRIPTION
  221. X *    Findbucket is used to find the bucket a free block is in.
  222. X *    Search ``srchlen'' elements of each free list for a block whose
  223. X *    header starts at ``freep''.  If srchlen is -1 search the whole list.
  224. X *
  225. X * RETURNS
  226. X *    bucket number, or -1 if not found.
  227. X */
  228. Xstatic int
  229. Xfindbucket(freep, srchlen)
  230. X    union overhead *    freep;
  231. X    int    srchlen;
  232. X{
  233. X    register union overhead *p;
  234. X    register int    i, j;
  235. X
  236. X    for (i = 0; i < NBUCKETS; i++)
  237. X    {
  238. X        j = 0;
  239. X        for (p = nextf[i]; p && j != srchlen; p = p->ov_next)
  240. X        {
  241. X            if (p == freep)
  242. X                return i;
  243. X            j++;
  244. X        }
  245. X    }
  246. X    return -1;
  247. X}
  248. X
  249. X
  250. X/*
  251. X * When a program attempts "storage compaction" as mentioned in the
  252. X * old malloc man page, it realloc's an already freed block.  Usually
  253. X * this is the last block it freed; occasionally it might be farther
  254. X * back.  We have to search all the free lists for the block in order
  255. X * to determine its bucket: first we make one pass thru the lists
  256. X * checking only the first block in each; if that fails we search
  257. X * ``realloc_srchlen'' blocks in each list for a match (the variable
  258. X * is extern so the caller can modify it).  If that fails we just copy
  259. X * however many bytes was given to realloc() and hope it's not huge.
  260. X */
  261. X
  262. Xstatic int realloc_srchlen = 4;    /* 4 should be plenty, -1 =>'s whole list */
  263. X
  264. X/*
  265. X * NAME
  266. X *    mem_realloc - change size
  267. X *
  268. X * SYNOPSIS
  269. X *    char
  270. X *    mem_realloc(cp, nbytes)
  271. X *    char * cp;
  272. X *    u_int nbytes;
  273. X *
  274. X * DESCRIPTION
  275. X *    Mem_realloc is used to enlarge a chunk of memory
  276. X *    returned by mem_alloc() or mem_realloc().
  277. X *
  278. X * RETURNS
  279. X *    char *, pointer to base of dynamic memory allocated
  280. X *
  281. X * CAVEAT
  282. X *    Use mem_free() when you are finished with the space.
  283. X */
  284. Xchar *
  285. Xmem_realloc(cp, nbytes)
  286. X    char *cp;
  287. X    unsigned long    nbytes;
  288. X{
  289. X    register u_int    old_nbytes;
  290. X    register union overhead *op;
  291. X    char *    res;
  292. X    register u_int    old_bucket;
  293. X    short    was_alloced = 0;
  294. X
  295. X    if (nbytes > ((unsigned int) -1))
  296. X        return NULL;
  297. X    assert((watchloc == NULL) || (watchloc->ov_magic == MAGIC), 14);
  298. X    if (!cp)
  299. X        return mem_alloc(nbytes);
  300. X    op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  301. X    if (op->ov_magic == MAGIC)
  302. X    {
  303. X        was_alloced++;
  304. X        old_bucket = op->ov_index;
  305. X    }
  306. X    else
  307. X    {
  308. X        /*
  309. X         * Already free, doing "compaction".
  310. X         *
  311. X         * Search for the old block of memory on the
  312. X         * free list. First, check the most common
  313. X         * case (last element free'd), then (this failing)
  314. X         * the last ``realloc_srchlen'' items free'd.
  315. X         * If all lookups fail, then assume the size of
  316. X         * the memory block being realloc'd is the
  317. X         * smallest possible.
  318. X         */
  319. X        if
  320. X        (
  321. X            (old_bucket = findbucket(op, 1)) == -1
  322. X        &&
  323. X            (old_bucket = findbucket(op, realloc_srchlen)) == -1
  324. X        )
  325. X            old_bucket = QUANTUM_NBITS;
  326. X    }
  327. X    old_nbytes = (1L << old_bucket) - sizeof(union overhead) - RSLOP;
  328. X
  329. X    /*
  330. X     * avoid the copy if same size block
  331. X     */
  332. X    if
  333. X    (
  334. X        was_alloced
  335. X    &&
  336. X        nbytes <= old_nbytes
  337. X    &&
  338. X        nbytes > (old_nbytes >> 1) - sizeof(union overhead) - RSLOP
  339. X    )
  340. X        return cp;
  341. X
  342. X    /*
  343. X     * grab another chunk
  344. X     */
  345. X    if(!(res = mem_alloc(nbytes)))
  346. X        return (char*)0;
  347. X    assert(cp != res, 11);
  348. X    memcpy(res, cp, (nbytes < old_nbytes) ? nbytes : old_nbytes);
  349. X    if(was_alloced)
  350. X        mem_free(cp);
  351. X    return res;
  352. X}
  353. X
  354. X#else /*CALC_MALLOC*/
  355. X
  356. X#undef MSTATS
  357. X
  358. X#endif /*CALC_MALLOC*/
  359. X
  360. X
  361. X
  362. X/*
  363. X * Allocate a new item from the specified free list.
  364. X * Returns NULL if no item can be allocated.
  365. X */
  366. XALLOCITEM *
  367. Xallocitem(fp)
  368. X    FREELIST *fp;        /* free list header */
  369. X{
  370. X    FREEITEM *ip;        /* allocated item */
  371. X
  372. X    if (fp->curfree > 0) {
  373. X        fp->curfree--;
  374. X        ip = fp->freelist;
  375. X        fp->freelist = ip->next;
  376. X        return (ALLOCITEM *) ip;
  377. X    }
  378. X    ip = (FREEITEM *) malloc(fp->itemsize);
  379. X    if (ip == NULL)
  380. X        return NULL;
  381. X    return (ALLOCITEM *) ip;
  382. X}
  383. X
  384. X
  385. X/*
  386. X * Free an item by placing it back on a free list.
  387. X * If too many items are on the list, it is really freed.
  388. X */
  389. Xvoid
  390. Xfreeitem(fp, ip)
  391. X    FREELIST *fp;        /* freelist header */
  392. X    FREEITEM *ip;        /* item to be freed */
  393. X{
  394. X    if (ip == NULL)
  395. X        return;
  396. X    if (fp->curfree >= fp->maxfree) {
  397. X        free((char *) ip);
  398. X        return;
  399. X    }
  400. X    ip->next = fp->freelist;
  401. X    fp->freelist = ip;
  402. X    fp->curfree++;
  403. X}
  404. X
  405. X
  406. X/*
  407. X * NAME
  408. X *    mem_stats - print memory statistics
  409. X *
  410. X * SYNOPSIS
  411. X *    void
  412. X *    mem_stats(s)
  413. X *    char * s;
  414. X *
  415. X * DESCRIPTION
  416. X *    Mem_stats is used to print out statistics about current memory usage.
  417. X *    ``s'' is the title string
  418. X *
  419. X *    Prints two lines of numbers, one showing the length of the free list
  420. X *    for each size category, the second showing the number of mallocs -
  421. X *    frees for each size category.
  422. X *
  423. X * RETURNS
  424. X *    void
  425. X */
  426. X/*ARGSUSED*/
  427. Xvoid
  428. Xmem_stats(s)
  429. X    char *    s;
  430. X{
  431. X#ifdef MSTATS
  432. X    register int    i, j;
  433. X    register union overhead *p;
  434. X    int    totfree = 0;
  435. X    int    totused = 0;
  436. X
  437. X    fprintf(stderr, "Memory allocation statistics %s\n", s);
  438. X    fprintf(stderr, "%11s:%12s%12s%12s\n", "Bucket", "In Use", "Free", "Sum");
  439. X    for (i = 0; i < NBUCKETS; i++)
  440. X    {
  441. X        for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
  442. X            ;
  443. X        if(!j && !nmalloc[i])
  444. X            continue;
  445. X        fprintf(stderr, "%11d:%12d%12d%12d\n", (1L<<i), nmalloc[i], j, j+nmalloc[i]);
  446. X        totfree += j * (1L << i);
  447. X        totused += nmalloc[i] * (1L << i);
  448. X    }
  449. X    fprintf(stderr, "%11s:%12d%12d%12d\n", "Totals", totused, totfree, totused+totfree);
  450. X#else
  451. X    fprintf(stderr, 
  452. X        "Memory allocation stats were not compiled into calc\n");
  453. X#endif
  454. X}
  455. X
  456. X#ifdef DEBUG
  457. Xvoid
  458. Xassertfailed(n)
  459. X{
  460. X    printf("Assertion %d failed\n", n);
  461. X    exit(1);
  462. X}
  463. X#endif
  464. X
  465. X/* END CODE */
  466. SHAR_EOF
  467. echo "File calc2.9.0/alloc.c is complete"
  468. chmod 0644 calc2.9.0/alloc.c || echo "restore of calc2.9.0/alloc.c fails"
  469. set `wc -c calc2.9.0/alloc.c`;Sum=$1
  470. if test "$Sum" != "13393"
  471. then echo original size 13393, current size $Sum;fi
  472. echo "x - extracting calc2.9.0/alloc.h (Text)"
  473. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/alloc.h &&
  474. X/*
  475. X * Copyright (c) 1993 David I. Bell
  476. X * Permission is granted to use, distribute, or modify this source,
  477. X * provided that this copyright notice remains intact.
  478. X *
  479. X * Allocator definitions (fast malloc and free)
  480. X */
  481. X
  482. X#if !defined(CALC_MALLOC)
  483. X
  484. X#include "have_malloc.h"
  485. X#ifdef HAVE_MALLOC_H
  486. X# include <malloc.h>
  487. X#else
  488. X# if defined(__STDC__)
  489. X   extern void *malloc();
  490. X   extern void *realloc();
  491. X   extern void free();
  492. X# else
  493. X   extern char *malloc();
  494. X   extern char *realloc();
  495. X   extern void free();
  496. X# endif
  497. X#endif
  498. X
  499. X#include "have_string.h"
  500. X
  501. X#ifdef HAVE_STRING_H
  502. X# include <string.h>
  503. X
  504. X#else
  505. X
  506. X# ifdef OLD_BSD
  507. Xextern void bcopy();
  508. Xextern void bfill();
  509. Xextern char *index();
  510. X# else /* OLD_BSD */
  511. Xextern void memcpy();
  512. Xextern void memset();
  513. X#  if defined(__STDC__)
  514. Xextern void *strchr();
  515. X#  else
  516. Xextern char *strchr();
  517. X#  endif
  518. X# endif /* OLD_BSD */
  519. Xextern void strcpy();
  520. Xextern void strncpy();
  521. Xextern void strcat();
  522. Xextern int strcmp();
  523. Xextern long strlen();    /* should be size_t, but old systems don't have it */
  524. X
  525. X#endif
  526. X
  527. X#ifdef OLD_BSD
  528. X#undef memcpy
  529. X#define memcpy(s1, s2, n) bcopy(s2, s1, n)
  530. X#undef memset
  531. X#define memset(s, c, n) bfill(s, n, c)
  532. X#undef strchr
  533. X#define strchr(s, c) index(s, c)
  534. X#endif
  535. X
  536. X#ifdef DONT_HAVE_VSPRINTF
  537. X/*
  538. X * XXX - hack aleart
  539. X *
  540. X * Systems that do not have vsprintf() need something.  In some cases
  541. X * the sprintf function will deal correctly with the va_alist 3rd arg.
  542. X * Hope for the best!
  543. X */
  544. X#define vsprintf sprintf
  545. X#endif
  546. X
  547. X#define mem_alloc malloc
  548. X#define mem_realloc realloc
  549. X#define mem_free free
  550. X
  551. X#else /*!CALC_MALLOC*/
  552. X
  553. X#define malloc(a) mem_alloc((long) a)
  554. X#define realloc(a,b) mem_realloc((char *) a, (long) b)
  555. X#define free(a) mem_free((char *) a)
  556. Xextern char *mem_alloc();
  557. Xextern char *mem_realloc();
  558. Xextern int mem_free();        /* MUST be int even though no return value */
  559. X
  560. X#endif /*!CALC_MALLOC*/
  561. X
  562. X
  563. X/*
  564. X * An item to be placed on a free list.
  565. X * These items are overlayed on top of the actual item being managed.
  566. X * Therefore, the managed items must be at least this size!
  567. X * Also, all items on a single free list must be the same size.
  568. X */
  569. Xstruct free_item {
  570. X    struct free_item *next;            /* next item on free list */
  571. X};
  572. Xtypedef struct free_item FREEITEM;
  573. X
  574. X
  575. X/*
  576. X * The actual free list header.
  577. X */
  578. Xtypedef struct {
  579. X    long        itemsize;    /* size of an item being managed */
  580. X    long        maxfree;    /* maximum number of free items */
  581. X    long        curfree;    /* current number of free items */
  582. X    FREEITEM    *freelist;    /* the free list */
  583. X} FREELIST;
  584. X
  585. X#if defined(__STDC__)
  586. Xtypedef void ALLOCITEM;
  587. X#else
  588. Xtypedef char ALLOCITEM;
  589. X#endif
  590. Xextern ALLOCITEM * allocitem( /* FREELIST * */ );
  591. Xextern void freeitem( /* FREELIST *, char * */ );
  592. Xextern void mem_stats();
  593. X
  594. X/* END CODE */
  595. SHAR_EOF
  596. chmod 0644 calc2.9.0/alloc.h || echo "restore of calc2.9.0/alloc.h fails"
  597. set `wc -c calc2.9.0/alloc.h`;Sum=$1
  598. if test "$Sum" != "2678"
  599. then echo original size 2678, current size $Sum;fi
  600. echo "x - extracting calc2.9.0/assocfunc.c (Text)"
  601. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/assocfunc.c &&
  602. X/*
  603. X * Copyright (c) 1993 David I. Bell
  604. X * Permission is granted to use, distribute, or modify this source,
  605. X * provided that this copyright notice remains intact.
  606. X *
  607. X * Association table routines.
  608. X * An association table is a type of value which can be "indexed" by
  609. X * one or more arbitrary values.  Each element in the table is thus an
  610. X * association between a particular set of index values and a result value.
  611. X * The elements in an association table are stored in a hash table for
  612. X * quick access.
  613. X */
  614. X
  615. X#include "value.h"
  616. X
  617. X
  618. X#define    MINHASHSIZE    31    /* minimum size of hash tables */
  619. X#define    GROWHASHSIZE    50    /* approximate growth for hash tables */
  620. X#define    CHAINLENGTH    10    /* desired number of elements on a hash chain */
  621. X#define    ELEMSIZE(n)    (sizeof(ASSOCELEM) + (sizeof(VALUE) * ((n) - 1)))
  622. X
  623. X
  624. Xstatic ASSOCELEM *elemindex MATH_PROTO((ASSOC *ap, long index));
  625. Xstatic BOOL compareindices MATH_PROTO((VALUE *v1, VALUE *v2, long dim));
  626. Xstatic void resize MATH_PROTO((ASSOC *ap, long newsize));
  627. Xstatic void elemfree MATH_PROTO((ASSOCELEM *ep));
  628. Xstatic long nextprime MATH_PROTO((long n));
  629. X
  630. X
  631. X/*
  632. X * Return the address of the value specified by normal indexing of
  633. X * an association.  The create flag is TRUE if a value is going to be
  634. X * assigned into the specified indexing location.  If create is FALSE and
  635. X * the index value doesn't exist, a pointer to a NULL value is returned.
  636. X */
  637. XVALUE *
  638. Xassocindex(ap, create, dim, indices)
  639. X    ASSOC *ap;        /* association to index into */
  640. X    BOOL create;        /* whether to create the index value */
  641. X    long dim;        /* dimension of the indexing */
  642. X    VALUE *indices;        /* table of values being indexed by */
  643. X{
  644. X    ASSOCELEM **listhead;
  645. X    ASSOCELEM *ep;
  646. X    static VALUE val;
  647. X    HASH hash;
  648. X    int i;
  649. X
  650. X    if (dim <= 0)
  651. X        math_error("No dimensions for indexing association");
  652. X
  653. X    /*
  654. X     * Calculate the hash value to use for this set of indices
  655. X     * so that we can first select the correct hash chain, and
  656. X     * also so we can quickly compare each element for a match.
  657. X     */
  658. X    hash = 0;
  659. X    for (i = 0; i < dim; i++)
  660. X        hash = hash * 67319821 + hashvalue(&indices[i]);
  661. X
  662. X    /*
  663. X     * Search the correct hash chain for the specified set of indices.
  664. X     * If found, return the address of the found element's value.
  665. X     */
  666. X    listhead = &ap->a_table[hash % ap->a_size];
  667. X    for (ep = *listhead; ep; ep = ep->e_next) {
  668. X        if ((ep->e_hash != hash) || (ep->e_dim != dim))
  669. X            continue;
  670. X        if (compareindices(ep->e_indices, indices, dim))
  671. X            return &ep->e_value;
  672. X    }
  673. X
  674. X    /*
  675. X     * The set of indices was not found.
  676. X     * Either return a pointer to a NULL value for a read reference,
  677. X     * or allocate a new element in the list for a write reference.
  678. X     */
  679. X    if (!create) {
  680. X        val.v_type = V_NULL;
  681. X        return &val;
  682. X    }
  683. X
  684. X    ep = (ASSOCELEM *) malloc(ELEMSIZE(dim));
  685. X    if (ep == NULL)
  686. X        math_error("Cannot allocate association element");
  687. X    ep->e_dim = dim;
  688. X    ep->e_hash = hash;
  689. X    ep->e_value.v_type = V_NULL;
  690. X    for (i = 0; i < dim; i++)
  691. X        copyvalue(&indices[i], &ep->e_indices[i]);
  692. X    ep->e_next = *listhead;
  693. X    *listhead = ep;
  694. X    ap->a_count++;
  695. X
  696. X    resize(ap, ap->a_count / CHAINLENGTH);
  697. X
  698. X    return &ep->e_value;
  699. X}
  700. X
  701. X
  702. X/*
  703. X * Search an association for the specified value starting at the
  704. X * specified index.  Returns the element number (zero based) of the
  705. X * found value, or -1 if the value was not found.
  706. X */
  707. Xlong
  708. Xassocsearch(ap, vp, index)
  709. X    ASSOC *ap;
  710. X    VALUE *vp;
  711. X    long index;
  712. X{
  713. X    ASSOCELEM *ep;
  714. X
  715. X    if (index < 0)
  716. X        index = 0;
  717. X    while (TRUE) {
  718. X        ep = elemindex(ap, index);
  719. X        if (ep == NULL)
  720. X            return -1;
  721. X        if (!comparevalue(&ep->e_value, vp))
  722. X            return index;
  723. X        index++;
  724. X    }
  725. X}
  726. X
  727. X
  728. X/*
  729. X * Search an association backwards for the specified value starting at the
  730. X * specified index.  Returns the element number (zero based) of the
  731. X * found value, or -1 if the value was not found.
  732. X */
  733. Xlong
  734. Xassocrsearch(ap, vp, index)
  735. X    ASSOC *ap;
  736. X    VALUE *vp;
  737. X    long index;
  738. X{
  739. X    ASSOCELEM *ep;
  740. X
  741. X    if (index >= ap->a_count)
  742. X        index = ap->a_count - 1;
  743. X    while (TRUE) {
  744. X        ep = elemindex(ap, index);
  745. X        if (ep == NULL)
  746. X            return -1;
  747. X        if (!comparevalue(&ep->e_value, vp))
  748. X            return index;
  749. X        index--;
  750. X    }
  751. X}
  752. X
  753. X
  754. X/*
  755. X * Return the address of an element of an association indexed by the
  756. X * double-bracket operation.
  757. X */
  758. Xstatic ASSOCELEM *
  759. Xelemindex(ap, index)
  760. X    ASSOC *ap;        /* association to index into */
  761. X    long index;        /* index of desired element */
  762. X{
  763. X    ASSOCELEM *ep;
  764. X    int i;
  765. X
  766. X    if ((index < 0) || (index > ap->a_count))
  767. X        return NULL;
  768. X
  769. X    /*
  770. X     * This loop should be made more efficient by remembering
  771. X     * previously requested locations within the association.
  772. X     */
  773. X    for (i = 0; i < ap->a_size; i++) {
  774. X        for (ep = ap->a_table[i]; ep; ep = ep->e_next) {
  775. X            if (index-- == 0)
  776. X                return ep;
  777. X        }
  778. X    }
  779. X    return NULL;
  780. X}
  781. X
  782. X
  783. X/*
  784. X * Return the address of the value specified by double-bracket indexing
  785. X * of an association.  Returns NULL if there is no such element.
  786. X */
  787. XVALUE *
  788. Xassocfindex(ap, index)
  789. X    ASSOC *ap;        /* association to index into */
  790. X    long index;        /* index of desired element */
  791. X{
  792. X    ASSOCELEM *ep;
  793. X
  794. X    ep = elemindex(ap, index);
  795. X    if (ep == NULL)
  796. X        return NULL;
  797. X    return &ep->e_value;
  798. X}
  799. X
  800. X
  801. X/*
  802. X * Compare two associations to see if they are identical.
  803. X * Returns TRUE if they are different.
  804. X */
  805. XBOOL
  806. Xassoccmp(ap1, ap2)
  807. X    ASSOC *ap1, *ap2;
  808. X{
  809. X    ASSOCELEM **table1;
  810. X    ASSOCELEM *ep1;
  811. X    ASSOCELEM *ep2;
  812. X    long size1;
  813. X    long size2;
  814. X    HASH hash;
  815. X    long dim;
  816. X
  817. X    if (ap1 == ap2)
  818. X        return FALSE;
  819. X    if (ap1->a_count != ap2->a_count)
  820. X        return TRUE;
  821. X
  822. X    table1 = ap1->a_table;
  823. X    size1 = ap1->a_size;
  824. X    size2 = ap2->a_size;
  825. X    while (size1-- > 0) {
  826. X        for (ep1 = *table1++; ep1; ep1 = ep1->e_next) {
  827. X            hash = ep1->e_hash;
  828. X            dim = ep1->e_dim;
  829. X            for (ep2 = ap2->a_table[hash % size2]; ;
  830. X                ep2 = ep2->e_next)
  831. X            {
  832. X                if (ep2 == NULL)
  833. X                    return TRUE;
  834. X                if (ep2->e_hash != hash)
  835. X                    continue;
  836. X                if (ep2->e_dim != dim)
  837. X                    continue;
  838. X                if (compareindices(ep1->e_indices,
  839. X                    ep2->e_indices, dim))
  840. X                        break;
  841. X            }
  842. X            if (comparevalue(&ep1->e_value, &ep2->e_value))
  843. X                return TRUE;
  844. X        }
  845. X    }
  846. X    return FALSE;
  847. X}
  848. X
  849. X
  850. X/*
  851. X * Copy an association value.
  852. X */
  853. XASSOC *
  854. Xassoccopy(oldap)
  855. X    ASSOC *oldap;
  856. X{
  857. X    ASSOC *ap;
  858. X    ASSOCELEM *oldep;
  859. X    ASSOCELEM *ep;
  860. X    ASSOCELEM **listhead;
  861. X    int oldhi;
  862. X    int i;
  863. X
  864. X    ap = assocalloc(oldap->a_count / CHAINLENGTH);
  865. X    ap->a_count = oldap->a_count;
  866. X
  867. X    for (oldhi = 0; oldhi < oldap->a_size; oldhi++) {
  868. X        for (oldep = oldap->a_table[oldhi]; oldep;
  869. X            oldep = oldep->e_next)
  870. X        {
  871. X            ep = (ASSOCELEM *) malloc(ELEMSIZE(oldep->e_dim));
  872. X            if (ep == NULL)
  873. X                math_error("Cannot allocate association element");
  874. X            ep->e_dim = oldep->e_dim;
  875. X            ep->e_hash = oldep->e_hash;
  876. X            ep->e_value.v_type = V_NULL;
  877. X            for (i = 0; i < ep->e_dim; i++)
  878. X                copyvalue(&oldep->e_indices[i], &ep->e_indices[i]);
  879. X            copyvalue(&oldep->e_value, &ep->e_value);
  880. X            listhead = &ap->a_table[ep->e_hash % ap->a_size];
  881. X            ep->e_next = *listhead;
  882. X            *listhead = ep;
  883. X        }
  884. X    }
  885. X    return ap;
  886. X}
  887. X
  888. X
  889. X/*
  890. X * Resize the hash table for an association to be the specified size.
  891. X * This is only actually done if the growth from the previous size is
  892. X * enough to make this worthwhile.
  893. X */
  894. Xstatic void
  895. Xresize(ap, newsize)
  896. X    ASSOC *ap;
  897. X    long newsize;
  898. X{
  899. X    ASSOCELEM **oldtable;
  900. X    ASSOCELEM **newtable;
  901. X    ASSOCELEM **oldlist;
  902. X    ASSOCELEM **newlist;
  903. X    ASSOCELEM *ep;
  904. X    int i;
  905. X
  906. X    if (newsize < ap->a_size + GROWHASHSIZE)
  907. X        return;
  908. X
  909. X    newsize = nextprime(newsize);
  910. X    newtable = (ASSOCELEM **) malloc(sizeof(ASSOCELEM *) * newsize);
  911. X    if (newtable == NULL)
  912. X        math_error("No memory to grow association");
  913. X    for (i = 0; i < newsize; i++)
  914. X        newtable[i] = NULL;
  915. X
  916. X    oldtable = ap->a_table;
  917. X    oldlist = oldtable;
  918. X    for (i = 0; i < ap->a_size; i++) {
  919. X        while (*oldlist) {
  920. X            ep = *oldlist;
  921. X            *oldlist = ep->e_next;
  922. X            newlist = &newtable[ep->e_hash % newsize];
  923. X            ep->e_next = *newlist;
  924. X            *newlist = ep;
  925. X        }
  926. X        oldlist++;
  927. X    }
  928. X
  929. X    ap->a_table = newtable;
  930. X    ap->a_size = newsize;
  931. X    free((char *) oldtable);
  932. X}
  933. X
  934. X
  935. X/*
  936. X * Free an association element, along with any contained values.
  937. X */
  938. Xstatic void
  939. Xelemfree(ep)
  940. X    ASSOCELEM *ep;
  941. X{
  942. X    int i;
  943. X
  944. X    for (i = 0; i < ep->e_dim; i++)
  945. X        freevalue(&ep->e_indices[i]);
  946. X    freevalue(&ep->e_value);
  947. X    ep->e_dim = 0;
  948. X    ep->e_next = NULL;
  949. X    free((char *) ep);
  950. X}
  951. X
  952. X
  953. X/*
  954. X * Allocate a new association value with an initial hash table.
  955. X * The hash table size is set at specified (but at least a minimum size).
  956. X */
  957. XASSOC *
  958. Xassocalloc(initsize)
  959. X    long initsize;
  960. X{
  961. X    register ASSOC *ap;
  962. X    int i;
  963. X
  964. X    if (initsize < MINHASHSIZE)
  965. X        initsize = MINHASHSIZE;
  966. X    ap = (ASSOC *) malloc(sizeof(ASSOC));
  967. X    if (ap == NULL)
  968. X        math_error("No memory for association");
  969. X    ap->a_count = 0;
  970. X    ap->a_size = initsize;
  971. X    ap->a_table = (ASSOCELEM **) malloc(sizeof(ASSOCELEM *) * initsize);
  972. X    if (ap->a_table == NULL) {
  973. X        free((char *) ap);
  974. X        math_error("No memory for association");
  975. X    }
  976. X    for (i = 0; i < initsize; i++)
  977. X        ap->a_table[i] = NULL;
  978. X    return ap;
  979. X}
  980. X
  981. X
  982. X/*
  983. X * Free an association value, along with all of its elements.
  984. X */
  985. Xvoid
  986. Xassocfree(ap)
  987. X    register ASSOC *ap;
  988. X{
  989. X    ASSOCELEM **listhead;
  990. X    ASSOCELEM *ep;
  991. X    ASSOCELEM *nextep;
  992. X    int i;
  993. X
  994. X    listhead = ap->a_table;
  995. X    for (i = 0; i < ap->a_size; i++) {
  996. X        nextep = *listhead;
  997. X        *listhead = NULL;
  998. X        while (nextep) {
  999. X            ep = nextep;
  1000. X            nextep = ep->e_next;
  1001. X            elemfree(ep);
  1002. X        }
  1003. X        listhead++;
  1004. X    }
  1005. X    free((char *) ap->a_table);
  1006. X    ap->a_table = NULL;
  1007. X    free((char *) ap);
  1008. X}
  1009. X
  1010. X
  1011. X/*
  1012. X * Print out an association along with the specified number of
  1013. X * its elements.  The elements are printed out in shortened form.
  1014. X */
  1015. Xvoid
  1016. Xassocprint(ap, max_print)
  1017. X    ASSOC *ap;
  1018. X    long max_print;
  1019. X{
  1020. X    ASSOCELEM *ep;
  1021. X    long index;
  1022. X    long i;
  1023. X    int savemode;
  1024. X
  1025. X    if (max_print <= 0) {
  1026. X        math_fmt("assoc (%ld element%s)", ap->a_count,
  1027. X            ((ap->a_count == 1) ? "" : "s"));
  1028. X        return;
  1029. X    }
  1030. X    math_fmt("\n  assoc (%ld element%s):\n", ap->a_count,
  1031. X        ((ap->a_count == 1) ? "" : "s"));
  1032. X
  1033. X    for (index = 0; ((index < max_print) && (index < ap->a_count));
  1034. X        index++)
  1035. X    {
  1036. X        ep = elemindex(ap, index);
  1037. X        if (ep == NULL)
  1038. X            continue;
  1039. X        math_str("  [");
  1040. X        for (i = 0; i < ep->e_dim; i++) {
  1041. X            if (i)
  1042. X                math_chr(',');
  1043. X            savemode = math_setmode(MODE_FRAC);
  1044. X            printvalue(&ep->e_indices[i],
  1045. X                (PRINT_SHORT | PRINT_UNAMBIG));
  1046. X            math_setmode(savemode);
  1047. X        }
  1048. X        math_str("] = ");
  1049. X        printvalue(&ep->e_value, PRINT_SHORT | PRINT_UNAMBIG);
  1050. X        math_chr('\n');
  1051. X    }
  1052. X    if (max_print < ap->a_count)
  1053. X        math_str("  ...\n");
  1054. X}
  1055. X
  1056. X
  1057. X/*
  1058. X * Return a trivial hash value for an association.
  1059. X */
  1060. XHASH
  1061. Xassochash(ap)
  1062. X    ASSOC *ap;
  1063. X{
  1064. X    return ap->a_count * 700001;
  1065. X}
  1066. X
  1067. X
  1068. X/*
  1069. X * Compare two lists of index values to see if they are identical.
  1070. X * Returns TRUE if they are the same.
  1071. X */
  1072. Xstatic BOOL
  1073. Xcompareindices(v1, v2, dim)
  1074. X    VALUE *v1;
  1075. X    VALUE *v2;
  1076. X    long dim;
  1077. X{
  1078. X    int i;
  1079. X
  1080. X    for (i = 0; i < dim; i++)
  1081. X        if (v1[i].v_type != v2[i].v_type)
  1082. X            return FALSE;
  1083. X
  1084. X    while (dim-- > 0)
  1085. X        if (comparevalue(v1++, v2++))
  1086. X            return FALSE;
  1087. X
  1088. X    return TRUE;
  1089. X}
  1090. X
  1091. X
  1092. X/*
  1093. X * Return the next prime number up from the specified value.
  1094. X * This is used to pick a good hash table size.
  1095. X */
  1096. Xstatic long
  1097. Xnextprime(n)
  1098. X    long n;
  1099. X{
  1100. X    long i;
  1101. X
  1102. X    if ((n & 0x01) == 0)
  1103. X        n++;
  1104. X    while (TRUE) {
  1105. X        for (i = 3; n % i; i += 2) {
  1106. X            if (i * i > n)
  1107. X                return n;
  1108. X        }
  1109. X        n += 2;
  1110. X    }
  1111. X}
  1112. X
  1113. X/* END CODE */
  1114. SHAR_EOF
  1115. chmod 0644 calc2.9.0/assocfunc.c || echo "restore of calc2.9.0/assocfunc.c fails"
  1116. set `wc -c calc2.9.0/assocfunc.c`;Sum=$1
  1117. if test "$Sum" != "10842"
  1118. then echo original size 10842, current size $Sum;fi
  1119. echo "x - extracting calc2.9.0/calc.c (Text)"
  1120. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/calc.c &&
  1121. X/*
  1122. X * Copyright (c) 1993 David I. Bell
  1123. X * Permission is granted to use, distribute, or modify this source,
  1124. X * provided that this copyright notice remains intact.
  1125. X *
  1126. X * Arbitrary precision calculator.
  1127. X */
  1128. X
  1129. X#include <signal.h>
  1130. X#include <pwd.h>
  1131. X#include <sys/types.h>
  1132. X
  1133. X#include "calc.h"
  1134. X#include "hist.h"
  1135. X#include "func.h"
  1136. X#include "opcodes.h"
  1137. X#include "config.h"
  1138. X#include "token.h"
  1139. X#include "symbol.h"
  1140. X
  1141. X
  1142. X/*
  1143. X * Common definitions
  1144. X */
  1145. Xlong maxprint;        /* number of elements to print */
  1146. Xint abortlevel;        /* current level of aborts */
  1147. XBOOL inputwait;        /* TRUE if in a terminal input wait */
  1148. Xjmp_buf jmpbuf;        /* for errors */
  1149. X
  1150. Xstatic int q_flag = FALSE;    /* TRUE => don't execute rc files */
  1151. X
  1152. Xchar *calcpath;        /* $CALCPATH or default */
  1153. Xchar *calcrc;        /* $CALCRC or default */
  1154. Xchar *calcbindings;    /* $CALCBINDINGS or default */
  1155. Xchar *home;        /* $HOME or default */
  1156. Xstatic char *pager;    /* $PAGER or default */
  1157. Xchar *shell;        /* $SHELL or default */
  1158. X
  1159. Xstatic void intint();    /* interrupt routine */
  1160. Xstatic void initenv();    /* initialize/default special environment vars */
  1161. X
  1162. X#if defined(__STDC__)
  1163. X#include <unistd.h>
  1164. X#include <stdlib.h>
  1165. X#else
  1166. Xextern struct passwd *getpwuid();
  1167. X#if defined (UID_T)
  1168. Xtypedef unsigned short uid_t;
  1169. X#endif
  1170. Xextern char *getenv();
  1171. Xextern uid_t geteuid();
  1172. X#endif
  1173. X
  1174. X
  1175. X/*
  1176. X * Top level calculator routine.
  1177. X */
  1178. Xmain(argc, argv)
  1179. X    char **argv;
  1180. X{
  1181. X    char *str;        /* current option string or expression */
  1182. X    char cmdbuf[MAXCMD+1];    /* command line expression */
  1183. X
  1184. X    initenv();
  1185. X    argc--;
  1186. X    argv++;
  1187. X    while ((argc > 0) && (**argv == '-')) {
  1188. X        for (str = &argv[0][1]; *str; str++) switch (*str) {
  1189. X            case 'h':
  1190. X                givehelp(DEFAULTCALCHELP);
  1191. X                exit(0);
  1192. X                break;
  1193. X            case 'q':
  1194. X                q_flag = TRUE;
  1195. X                break;
  1196. X            default:
  1197. X                printf("Unknown option\n");
  1198. X                exit(1);
  1199. X        }
  1200. X        argc--;
  1201. X        argv++;
  1202. X    }
  1203. X    str = cmdbuf;
  1204. X    *str = '\0';
  1205. X    while (--argc >= 0) {
  1206. X        *str++ = ' ';
  1207. X        strcpy(str, *argv++);
  1208. X        str += strlen(str);
  1209. X        str[0] = '\n';
  1210. X        str[1] = '\0';
  1211. X    }
  1212. X    str = cmdbuf;
  1213. X    if (*str == '\0') {
  1214. X        str = NULL;
  1215. X        version(stdout);
  1216. X        printf("[Type \"exit\" to exit, or \"help\" for help.]\n\n");
  1217. X
  1218. X        switch (hist_init(calcbindings)) {
  1219. X        case HIST_NOFILE:
  1220. X            fprintf(stderr,
  1221. X                "Cannot open key bindings file \"%s\", fancy editing disabled.\n",
  1222. X                calcbindings);
  1223. X            break;
  1224. X
  1225. X        case HIST_NOTTY:
  1226. X            fprintf(stderr,
  1227. X                "Cannot set terminal modes, fancy editing disabled.\n");
  1228. X            break;
  1229. X        }
  1230. X    }
  1231. X    if (setjmp(jmpbuf) == 0) {
  1232. X        initmasks();
  1233. X        inittokens();
  1234. X        initglobals();
  1235. X        initfunctions();
  1236. X        initstack();
  1237. X        resetinput();
  1238. X        math_cleardiversions();
  1239. X        math_setfp(stdout);
  1240. X        math_setmode(MODE_INITIAL);
  1241. X        math_setdigits((long)DISPLAY_DEFAULT);
  1242. X        maxprint = MAXPRINT_DEFAULT;
  1243. X        _epsilon_ = atoq(EPSILON_DEFAULT);
  1244. X        _epsilonprec_ = qprecision(_epsilon_);
  1245. X        if (str) {
  1246. X            if (q_flag == FALSE) {
  1247. X                runrcfiles();
  1248. X                q_flag = TRUE;
  1249. X            }
  1250. X            (void) openstring(str);
  1251. X            getcommands(FALSE);
  1252. X            exit(0);
  1253. X        }
  1254. X    }
  1255. X    if (str)
  1256. X        exit(1);
  1257. X    abortlevel = 0;
  1258. X    _math_abort_ = FALSE;
  1259. X    inputwait = FALSE;
  1260. X    (void) signal(SIGINT, intint);
  1261. X    math_cleardiversions();
  1262. X    math_setfp(stdout);
  1263. X    resetscopes();
  1264. X    resetinput();
  1265. X    if (q_flag == FALSE) {
  1266. X        runrcfiles();
  1267. X        q_flag = TRUE;
  1268. X    }
  1269. X    (void) openterminal();
  1270. X    getcommands(TRUE);
  1271. X    exit(0);
  1272. X    /*NOTREACHED*/
  1273. X}
  1274. X
  1275. X
  1276. X/*
  1277. X * initenv - obtain $CALCPATH, $CALCRC, $CALCBINDINGS, $HOME, $PAGER
  1278. X * and $SHELL values
  1279. X *
  1280. X * If $CALCPATH, $CALCRC, $CALCBINDINGS, $PAGER or $SHELL do not exist,
  1281. X * use the default values.  If $PAGER or $SHELL is an empty string, also
  1282. X * use a default value. If $HOME does not exist, or is empty, use the home
  1283. X * directory information from the password file.
  1284. X */
  1285. Xstatic void
  1286. Xinitenv()
  1287. X{
  1288. X    struct passwd *ent;        /* our password entry */
  1289. X
  1290. X    /* determine the $CALCPATH value */
  1291. X    calcpath = getenv(CALCPATH);
  1292. X    if (calcpath == NULL)
  1293. X        calcpath = DEFAULTCALCPATH;
  1294. X
  1295. X    /* determine the $CALCRC value */
  1296. X    calcrc = getenv(CALCRC);
  1297. X    if (calcrc == NULL) {
  1298. X        calcrc = DEFAULTCALCRC;
  1299. X    }
  1300. X
  1301. X    /* determine the $CALCBINDINGS value */
  1302. X    calcbindings = getenv(CALCBINDINGS);
  1303. X    if (calcbindings == NULL) {
  1304. X        calcbindings = DEFAULTCALCBINDINGS;
  1305. X    }
  1306. X
  1307. X    /* determine the $HOME value */
  1308. X    home = getenv(HOME);
  1309. X    if (home == NULL || home[0] == '\0') {
  1310. X        ent = getpwuid(geteuid());
  1311. X        if (ent == NULL) {
  1312. X            /* just assume . is home if all else fails */
  1313. X            home = ".";
  1314. X        }
  1315. X        home = (char *)malloc(strlen(ent->pw_dir)+1);
  1316. X        strcpy(home, ent->pw_dir);
  1317. X    }
  1318. X
  1319. X    /* determine the $PAGER value */
  1320. X    pager = getenv(PAGER);
  1321. X    if (pager == NULL || *pager == '\0') {
  1322. X        pager = DEFAULTCALCPAGER;
  1323. X    }
  1324. X
  1325. X    /* determine the $SHELL value */
  1326. X    shell = getenv(SHELL);
  1327. X    if (shell == NULL)
  1328. X        shell = DEFAULTSHELL;
  1329. X}
  1330. X
  1331. X
  1332. Xvoid
  1333. Xgivehelp(type)
  1334. X    char *type;        /* the type of help to give, NULL => index */
  1335. X{
  1336. X    char *helpcmd;        /* what to execute to print help */
  1337. X
  1338. X    /* catch the case where we just print the index */
  1339. X    if (type == NULL) {
  1340. X        type = DEFAULTCALCHELP;        /* the help index file */
  1341. X    }
  1342. X
  1343. X    /* form the help command name */
  1344. X    helpcmd = (char *)malloc(
  1345. X        sizeof("if [ ! -d \"")+sizeof(HELPDIR)+1+strlen(type)+
  1346. X        sizeof("\" ];then ")+
  1347. X        strlen(pager)+1+1+sizeof(HELPDIR)+1+strlen(type)+1+1+
  1348. X        sizeof(";else echo no such help;fi"));
  1349. X    sprintf(helpcmd, 
  1350. X        "if [ -r \"%s/%s\" ];then %s \"%s/%s\";else echo no such help;fi", 
  1351. X        HELPDIR, type, pager, HELPDIR, type);
  1352. X
  1353. X    /* execute the help command */
  1354. X    system(helpcmd);
  1355. X    free(helpcmd);
  1356. X}
  1357. X
  1358. X
  1359. X/*
  1360. X * Interrupt routine.
  1361. X */
  1362. X/*ARGSUSED*/
  1363. Xstatic void
  1364. Xintint(arg)
  1365. X    int arg;    /* to keep ANSI C happy */
  1366. X{
  1367. X    (void) signal(SIGINT, intint);
  1368. X    if (inputwait || (++abortlevel >= ABORT_NOW))
  1369. X        math_error("\nABORT");
  1370. X    if (abortlevel >= ABORT_MATH)
  1371. X        _math_abort_ = TRUE;
  1372. X    printf("\n[Abort level %d]\n", abortlevel);
  1373. X}
  1374. X
  1375. X/* END CODE */
  1376. SHAR_EOF
  1377. chmod 0644 calc2.9.0/calc.c || echo "restore of calc2.9.0/calc.c fails"
  1378. set `wc -c calc2.9.0/calc.c`;Sum=$1
  1379. if test "$Sum" != "5576"
  1380. then echo original size 5576, current size $Sum;fi
  1381. echo "x - extracting calc2.9.0/calc.h (Text)"
  1382. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/calc.h &&
  1383. X/*
  1384. X * Copyright (c) 1993 David I. Bell
  1385. X * Permission is granted to use, distribute, or modify this source,
  1386. X * provided that this copyright notice remains intact.
  1387. X *
  1388. X * Definitions for calculator program.
  1389. X */
  1390. X
  1391. X#ifndef    CALC_H
  1392. X#define    CALC_H
  1393. X
  1394. X
  1395. X#include <stdio.h>
  1396. X#include <setjmp.h>
  1397. X#include "value.h"
  1398. X
  1399. X
  1400. X/*
  1401. X * Configuration definitions
  1402. X */
  1403. X#define    CALCPATH    "CALCPATH"    /* environment variable for files */
  1404. X#define    CALCRC        "CALCRC"    /* environment variable for startup */
  1405. X#define    CALCBINDINGS    "CALCBINDINGS"    /* environment variable for hist bindings */
  1406. X#define    HOME        "HOME"        /* environment variable for home dir */
  1407. X#define    PAGER        "PAGER"        /* environment variable for help */
  1408. X#define    SHELL        "SHELL"        /* environment variable for shell */
  1409. X#define DEFAULTCALCHELP    "help"        /* help file that -h prints */
  1410. X#define DEFAULTSHELL    "sh"        /* default shell to use */
  1411. X#define    CALCEXT        ".cal"    /* extension for files read in */
  1412. X#define    PATHSIZE    1024    /* maximum length of path name */
  1413. X#define    HOMECHAR    '~'    /* char which indicates home directory */
  1414. X#define DOTCHAR        '.'    /* char which indicates current directory */
  1415. X#define    PATHCHAR    '/'    /* char which separates path components */
  1416. X#define    LISTCHAR    ':'    /* char which separates paths in a list */
  1417. X#define    MAXCMD        1024    /* maximum length of command invocation */
  1418. X#define    MAXERROR    512    /* maximum length of error message string */
  1419. X
  1420. X#define    SYMBOLSIZE    256    /* maximum symbol name size */
  1421. X#define    MAXINDICES    20    /* maximum number of indices for objects */
  1422. X#define    MAXLABELS    100    /* maximum number of user labels in function */
  1423. X#define    MAXOBJECTS    10    /* maximum number of object types */
  1424. X#define    MAXSTRING    1024    /* maximum size of string constant */
  1425. X#define    MAXSTACK    1000    /* maximum depth of evaluation stack */
  1426. X#define    MAXFILES    20    /* maximum number of opened files */
  1427. X#define PROMPT1        "> "    /* normal prompt */
  1428. X#define PROMPT2        ">> "    /* prompt when inside multi-line input */
  1429. X
  1430. X
  1431. X#define    TRACE_NORMAL    0x00    /* normal trace flags */
  1432. X#define    TRACE_OPCODES    0x01    /* trace every opcode */
  1433. X#define    TRACE_NODEBUG    0x02    /* suppress debugging opcodes */
  1434. X#define    TRACE_MAX    0x03    /* maximum value for trace flag */
  1435. X
  1436. X#define DISPLAY_DEFAULT 20    /* default digits for float display */
  1437. X#define EPSILON_DEFAULT "1e-20"    /* allowed error for float calculations */
  1438. X#define MAXPRINT_DEFAULT 16    /* default number of elements printed */
  1439. X
  1440. X#define ABORT_NONE    0    /* abort not needed yet */
  1441. X#define ABORT_STATEMENT    1    /* abort on statement boundary */
  1442. X#define ABORT_OPCODE    2    /* abort on any opcode boundary */
  1443. X#define ABORT_MATH    3    /* abort on any math operation */
  1444. X#define ABORT_NOW    4    /* abort right away */
  1445. X
  1446. X#define CONFIG_MODE    1    /* types of configuration parameters */
  1447. X#define CONFIG_DISPLAY    2
  1448. X#define CONFIG_EPSILON    3
  1449. X#define CONFIG_TRACE    4
  1450. X#define CONFIG_MAXPRINT    5
  1451. X#define    CONFIG_MUL2    6
  1452. X#define    CONFIG_SQ2    7
  1453. X#define    CONFIG_POW2    8
  1454. X#define    CONFIG_REDC2    9
  1455. X
  1456. X
  1457. X/*
  1458. X * File ids corresponding to standard in, out, error, and when not in use.
  1459. X */
  1460. X#define    FILEID_STDIN    ((FILEID) 0)
  1461. X#define    FILEID_STDOUT    ((FILEID) 1)
  1462. X#define    FILEID_STDERR    ((FILEID) 2)
  1463. X#define    FILEID_NONE    ((FILEID) -1)
  1464. X
  1465. X
  1466. X/*
  1467. X * File I/O routines.
  1468. X */
  1469. Xextern FILEID openid MATH_PROTO((char *name, char *mode));
  1470. Xextern FILEID indexid MATH_PROTO((long index));
  1471. Xextern BOOL validid MATH_PROTO((FILEID id));
  1472. Xextern BOOL errorid MATH_PROTO((FILEID id));
  1473. Xextern BOOL eofid MATH_PROTO((FILEID id));
  1474. Xextern BOOL closeid MATH_PROTO((FILEID id));
  1475. Xextern int getcharid MATH_PROTO((FILEID id));
  1476. Xextern void idprintf MATH_PROTO((FILEID id, char *fmt, int count, VALUE **vals));
  1477. Xextern void printid MATH_PROTO((FILEID id, int flags));
  1478. Xextern void flushid MATH_PROTO((FILEID id));
  1479. Xextern void readid MATH_PROTO((FILEID id, char **retptr));
  1480. X
  1481. X
  1482. X/*
  1483. X * Input routines.
  1484. X */
  1485. Xextern FILE *f_open MATH_PROTO((char *name, char *mode));
  1486. Xextern int openstring MATH_PROTO((char *str));
  1487. Xextern int openterminal MATH_PROTO((void));
  1488. Xextern int opensearchfile MATH_PROTO((char *name, char *pathlist, char *exten));
  1489. Xextern char *nextline MATH_PROTO((void));
  1490. Xextern int nextchar MATH_PROTO((void));
  1491. Xextern void reread MATH_PROTO((void));
  1492. Xextern void resetinput MATH_PROTO((void));
  1493. Xextern void setprompt MATH_PROTO((char *));
  1494. Xextern BOOL inputisterminal MATH_PROTO((void));
  1495. Xextern char *inputname MATH_PROTO((void));
  1496. Xextern long linenumber MATH_PROTO((void));
  1497. Xextern void runrcfiles MATH_PROTO((void));
  1498. X
  1499. X
  1500. X/*
  1501. X * Other routines.
  1502. X */
  1503. Xextern NUMBER *constvalue MATH_PROTO((long index));
  1504. Xextern long addnumber MATH_PROTO((char *str));
  1505. Xextern long addqconstant MATH_PROTO((NUMBER *q));
  1506. Xextern void initstack MATH_PROTO((void));
  1507. Xextern void version MATH_PROTO((FILE *stream));
  1508. Xextern void getcommands MATH_PROTO((BOOL toplevel));
  1509. Xextern void givehelp MATH_PROTO((char *type));
  1510. X
  1511. Xextern void getconfig MATH_PROTO((int type, VALUE *vp));
  1512. Xextern void setconfig MATH_PROTO((int type, VALUE *vp));
  1513. Xextern int configtype MATH_PROTO((char *name));
  1514. X
  1515. X
  1516. X/*
  1517. X * Global data definitions.
  1518. X */
  1519. Xextern long maxprint;        /* number of elements to print */
  1520. Xextern int abortlevel;        /* current level of aborts */
  1521. Xextern BOOL inputwait;        /* TRUE if in a terminal input wait */
  1522. Xextern FLAG traceflags;        /* tracing flags */
  1523. Xextern VALUE *stack;        /* execution stack */
  1524. Xextern jmp_buf jmpbuf;        /* for errors */
  1525. X
  1526. Xextern char *calcpath;        /* $CALCPATH or default */
  1527. Xextern char *calcrc;        /* $CALCRC or default */
  1528. Xextern char *calcbindings;    /* $CALCBINDINGS or default */
  1529. Xextern char *home;        /* $HOME or default */
  1530. Xextern char *shell;        /* $SHELL or default */
  1531. X
  1532. X#endif
  1533. X
  1534. X/* END CODE */
  1535. SHAR_EOF
  1536. chmod 0644 calc2.9.0/calc.h || echo "restore of calc2.9.0/calc.h fails"
  1537. set `wc -c calc2.9.0/calc.h`;Sum=$1
  1538. if test "$Sum" != "5443"
  1539. then echo original size 5443, current size $Sum;fi
  1540. echo "x - extracting calc2.9.0/calc.man (Text)"
  1541. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/calc.man &&
  1542. X.\"
  1543. X.\" Copyright (c) 1993 David I. Bell and Landon Curt Noll
  1544. X.\" Permission is granted to use, distribute, or modify this source,
  1545. X.\" provided that this copyright notice remains intact.
  1546. X.\"
  1547. X.\" calculator by David I. Bell
  1548. X.\" man page by Landon Noll
  1549. X.TH calc 1 "^..^" "15nov93"
  1550. X.SH NAME
  1551. X\f4calc\f1 \- arbitrary precision calculator
  1552. X.SH SYNOPSIS
  1553. X\f4calc\fP
  1554. X[
  1555. X\f4\-h\fP
  1556. X] [
  1557. X\f4\-q\fP
  1558. X] [
  1559. X.I calc_cmd
  1560. X\&.\|.\|.
  1561. X]
  1562. X.SH DESCRIPTION
  1563. X\&
  1564. X.br
  1565. XCALC COMMAND LINE
  1566. X.PP
  1567. X.TP
  1568. X\f4 \-h\f1
  1569. XPrint a help message.
  1570. XThis option implies \f4 \-q\f1.
  1571. XThis is equivalent to the calc command \f4help help\fP.
  1572. X.TP
  1573. X\f4 \-q\f1
  1574. XDisable the use of the \f4$CALCRC\f1 startup library scripts.
  1575. X.PP
  1576. XWithout \f4calc_cmd\fPs, \f4calc\fP operates interactively.
  1577. XIf one or more \f4calc_cmd\fPs are given on the command line,
  1578. X\f4calc\fP will execute them and exit.
  1579. X.PP
  1580. XNormally on startup, \f4calc\fP attempts to execute a collection 
  1581. Xof library scripts.
  1582. XThe environment variable \f4$CALCRC\f1 (if non-existent then
  1583. Xa compiled in value) contains a \f4:\fP separated list of
  1584. Xstartup library scripts.
  1585. XNo error conditions are produced if these startup library scripts
  1586. Xare not found.
  1587. X.PP
  1588. XFilenames are subject to ``~'' expansion (see below).
  1589. XThe environment variable \f4$CALCPATH\fP (if non-existent then
  1590. Xa compiled in value) contains a \f4:\fP separated list of search
  1591. Xdirectories.
  1592. XIf a file does not begin with \f4/\fP, \f4~\fP or \f4./\fP,
  1593. Xthen it is searched for under each directory listed in the \f4$CALCPATH\fP.
  1594. XIt is an error if no such readable file is found.
  1595. X.PP
  1596. XFor more information use the following calc commands:
  1597. X.PP
  1598. X.in 1.0i
  1599. Xhelp usage
  1600. X.br
  1601. Xhelp help
  1602. X.br
  1603. Xhelp environment
  1604. X.in -1.0i
  1605. X.PP
  1606. XOVERVIEW
  1607. X.PP
  1608. X\f4Calc\fP is arbitrary precision arithmetic system that uses 
  1609. Xa C-like language.
  1610. X\f4Calc\fP is useful as a calculator, an algorithm prototyped
  1611. Xand as a mathematical research tool.
  1612. XMore importantly, \f4calc\fP provides one with a machine
  1613. Xindependent means of computation.
  1614. X.PP
  1615. X\f4Calc\fP comes with a rich set of builtin mathematical 
  1616. Xand programmatic functions.
  1617. X.PP
  1618. X\f4Calc\fP is distributed with library of scripts.
  1619. XWritten in the same C-like language, library scripts may be
  1620. Xread in and executed during a \f4calc\fP session.
  1621. XThese library scripts are also provided because they are
  1622. Xuseful and to serve as examples of the \f4calc\fP language.
  1623. XOne may further extend \f4calc\fP thru the
  1624. Xuse of user defined scripts.
  1625. X.PP
  1626. XInternally calc represents numeric values as fractions reduced to their
  1627. Xlowest terms.
  1628. XThe numerators and denominators of these factions may grow to
  1629. Xarbitrarily large values.
  1630. XNumeric values read in are automatically converted into rationals.
  1631. XThe user need not be aware of this internal representation.
  1632. X.PP
  1633. XFor more information use the following calc commands:
  1634. X.PP
  1635. X.in 1.0i
  1636. Xhelp intro
  1637. X.br
  1638. Xhelp builtin
  1639. X.br
  1640. Xhelp stdlib
  1641. X.br
  1642. Xhelp define
  1643. X.br
  1644. Xshow builtins
  1645. X.br
  1646. Xshow functions
  1647. X.in -1.0i
  1648. X.PP
  1649. XDATA TYPES
  1650. X.PP
  1651. XFundamental builtin data types include integers, real numbers, 
  1652. Xrational numbers, complex numbers and strings.
  1653. X.PP
  1654. XBy use of an object, one may define an arbitrarily complex
  1655. Xdata types.
  1656. XOne may define how such objects behave a wide range of
  1657. Xoperations such as addition, subtraction,
  1658. Xmultiplication, division, negation, squaring, modulus,
  1659. Xrounding, exponentiation, equality, comparison, printing
  1660. Xand so on.
  1661. X.PP
  1662. XFor more information use the following calc commands:
  1663. X.PP
  1664. X.in 1.0i
  1665. Xhelp types
  1666. X.br
  1667. Xhelp obj
  1668. X.br
  1669. Xshow objfuncs
  1670. X.in -1.0i
  1671. X.PP
  1672. XVARIABLES
  1673. X.PP
  1674. XVariables in \f4calc\fP are typeless.
  1675. XIn other words, the fundamental type of a variable is determined by its content.
  1676. XBefore a variable is assigned a value it has the value of zero.
  1677. X.PP
  1678. XThe scope of a variable may be global, local to a file, or local to a
  1679. Xprocedure.
  1680. XValues may be grouped together in a matrix, or into a
  1681. Xa list that permits stack and queue style operations.
  1682. X.PP
  1683. XFor more information use the following calc commands:
  1684. X.PP
  1685. X.in 1.0i
  1686. Xhelp variable
  1687. X.br
  1688. Xhelp mat
  1689. X.br
  1690. Xhelp list
  1691. X.br
  1692. Xshow globals
  1693. X.in -1.0i
  1694. X.PP
  1695. XINPUT/OUTPUT
  1696. X.PP
  1697. XA leading ``0x'' implies a hexadecimal value,
  1698. Xa leading ``0b'' implies a binary value,
  1699. Xand a ``0'' followed by a digit implies an octal value.
  1700. XComplex numbers are indicated by a trailing ``i'' such as in ``3+4i''.
  1701. XStrings may be delimited by either a pair of single or double quotes.
  1702. XBy default, \f4calc\fP prints values as if they were floating point numbers.
  1703. XOne may change the default to print values in a number of modes
  1704. Xincluding fractions, integers and exponentials.
  1705. X.PP
  1706. XA number of stdio-like file I/O operations are provided.
  1707. XOne may open, read, write, seek and close files.
  1708. XFilenames are subject to ``\~'' expansion to home directories
  1709. Xin a way similar to that of the Korn or C-Shell.
  1710. X.PP
  1711. XFor example:
  1712. X.PP
  1713. X.in 1.0i
  1714. X~/.calcrc
  1715. X.br
  1716. X~chongo/lib/fft_multiply.cal
  1717. X.in -1.0i
  1718. X.PP
  1719. XFor more information use the following calc command:
  1720. X.PP
  1721. X.in 1.0i
  1722. Xhelp file
  1723. X.in -1.0i
  1724. X.PP
  1725. XCALC LANGUAGE
  1726. X.PP
  1727. XThe \f4calc\fP language is a C-like language.
  1728. XThe language includes commands such as variable declarations, 
  1729. Xexpressions, tests, labels, loops, file operations, function calls.
  1730. XThese commands are very similar to their counterparts in C.
  1731. X.PP
  1732. XThe language also include a number of commands particular
  1733. Xto \f4calc\fP itself.
  1734. XThese include commands such as function definition, help, 
  1735. Xreading in library scripts, dump files to a file, error notification, 
  1736. Xconfiguration control and status.
  1737. X.PP
  1738. XFor more information use the following calc command:
  1739. X.PP
  1740. X.in 1.0i
  1741. Xhelp command
  1742. X.br
  1743. Xhelp statement
  1744. X.br
  1745. Xhelp expression
  1746. X.br
  1747. Xhelp operator
  1748. X.br
  1749. Xhelp config
  1750. X.in -1.0i
  1751. X.PP
  1752. X.SH FILES
  1753. X\&
  1754. X.br
  1755. X.PD 0
  1756. X.TP 20
  1757. X${LIBDIR}/*.cal
  1758. Xlibrary scripts shipped with calc
  1759. X.br
  1760. X.sp
  1761. X.TP 20
  1762. X${LIBDIR}/help/*
  1763. Xhelp files
  1764. X.br
  1765. X.sp
  1766. X.TP 20
  1767. X${LIBDIR}/bindings
  1768. Xcommand line editor bindings
  1769. X.sp
  1770. X.SH ENVIRONMENT
  1771. X\&
  1772. X.br
  1773. X.PD 0
  1774. X.TP 5
  1775. XCALCPATH
  1776. XA :-separated list of directories used to search for
  1777. Xscripts filenames that do not begin with /, ./ or ~.
  1778. X.br
  1779. X.sp
  1780. XDefault value: .:./lib:~/lib:${LIBDIR}
  1781. X.br
  1782. X.sp
  1783. X.TP 5
  1784. XCALCRC
  1785. XOn startup (unless \-h or \-q was given on the command
  1786. Xline), calc searches for files along this :-separated
  1787. Xenvironment variable.
  1788. X.br
  1789. X.sp
  1790. XDefault value: ${LIBDIR}/startup:~/.calcrc
  1791. X.br
  1792. X.sp
  1793. X.TP 5
  1794. XCALCBINDINGS
  1795. XOn startup (unless \-h or \-q was given on the command
  1796. Xline), calc reads key bindings from the filename specified
  1797. Xby this environment variable.
  1798. X.br
  1799. X.sp
  1800. XDefault value: ${LIBDIR}/bindings
  1801. X.sp
  1802. X.SH CREDIT
  1803. X\&
  1804. X.br
  1805. XWritten by David I. Bell.
  1806. X.sp
  1807. XThanks for suggestions and encouragement from Peter Miller,
  1808. XNeil Justusson, and Landon Noll.
  1809. X.sp
  1810. XPortions of this program are derived from an earlier set of
  1811. Xpublic domain arbitrarily precision routines which was posted
  1812. Xto the net around 1984.  By now, there is almost no recognizable 
  1813. Xcode left from that original source.
  1814. X.sp
  1815. XMost of this source and binary is:
  1816. X.sp
  1817. X.PP
  1818. X.in 1.0i
  1819. XCopyright (c) 1993 David I. Bell
  1820. X.sp
  1821. X.in -1.0i
  1822. X.PP
  1823. XSome files are a copyrighted David I. Bell and Landon Noll.
  1824. X.sp
  1825. XPermission is granted to use, distribute, or modify this source,
  1826. Xprovided that this copyright notice remains intact.
  1827. X.sp
  1828. XSend calc comments, suggestions, bug fixes, enhancements
  1829. Xand interesting calc scripts that you would like you see included 
  1830. Xin future distributions to:
  1831. X.sp
  1832. X.PP
  1833. X.in 1.0i
  1834. Xdbell@canb.auug.org.au
  1835. Xchongo@toad.com
  1836. X.sp
  1837. X.in -1.0i
  1838. X.PP
  1839. X.sp
  1840. XEnjoy!
  1841. SHAR_EOF
  1842. chmod 0644 calc2.9.0/calc.man || echo "restore of calc2.9.0/calc.man fails"
  1843. set `wc -c calc2.9.0/calc.man`;Sum=$1
  1844. if test "$Sum" != "7218"
  1845. then echo original size 7218, current size $Sum;fi
  1846. echo "x - extracting calc2.9.0/cmath.h (Text)"
  1847. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/cmath.h &&
  1848. X/*
  1849. X * Copyright (c) 1993 David I. Bell
  1850. X * Permission is granted to use, distribute, or modify this source,
  1851. X * provided that this copyright notice remains intact.
  1852. X *
  1853. X * Data structure declarations for extended precision complex arithmetic.
  1854. X */
  1855. X
  1856. X#ifndef    CMATH_H
  1857. X#define    CMATH_H
  1858. X
  1859. X#include "qmath.h"
  1860. X
  1861. X
  1862. X/*
  1863. X * Complex arithmetic definitions.
  1864. X */
  1865. Xtypedef struct {
  1866. X    NUMBER *real;        /* real part of number */
  1867. X    NUMBER *imag;        /* imaginary part of number */
  1868. X    long links;        /* link count */
  1869. X} COMPLEX;
  1870. X
  1871. X
  1872. X/*
  1873. X * Input, output, and conversion routines.
  1874. X */
  1875. Xextern COMPLEX *comalloc MATH_PROTO((void));
  1876. Xextern COMPLEX *qqtoc MATH_PROTO((NUMBER *q1, NUMBER *q2));
  1877. Xextern void comfree MATH_PROTO((COMPLEX *c));
  1878. Xextern void comprint MATH_PROTO((COMPLEX *c));
  1879. Xextern void cprintfr MATH_PROTO((COMPLEX *c));
  1880. X
  1881. X
  1882. X/*
  1883. X * Basic numeric routines.
  1884. X */
  1885. Xextern COMPLEX *cadd MATH_PROTO((COMPLEX *c1, COMPLEX *c2));
  1886. Xextern COMPLEX *csub MATH_PROTO((COMPLEX *c1, COMPLEX *c2));
  1887. Xextern COMPLEX *cmul MATH_PROTO((COMPLEX *c1, COMPLEX *c2));
  1888. Xextern COMPLEX *cdiv MATH_PROTO((COMPLEX *c1, COMPLEX *c2));
  1889. Xextern COMPLEX *caddq MATH_PROTO((COMPLEX *c, NUMBER *q));
  1890. Xextern COMPLEX *csubq MATH_PROTO((COMPLEX *c, NUMBER *q));
  1891. Xextern COMPLEX *cmulq MATH_PROTO((COMPLEX *c, NUMBER *q));
  1892. Xextern COMPLEX *cdivq MATH_PROTO((COMPLEX *c, NUMBER *q));
  1893. Xextern COMPLEX *cmodq MATH_PROTO((COMPLEX *c, NUMBER *q));
  1894. Xextern COMPLEX *cquoq MATH_PROTO((COMPLEX *c, NUMBER *q));
  1895. Xextern COMPLEX *cscale MATH_PROTO((COMPLEX *c, long i));
  1896. Xextern COMPLEX *cshift MATH_PROTO((COMPLEX *c, long i));
  1897. Xextern COMPLEX *cround MATH_PROTO((COMPLEX *c, long i));
  1898. Xextern COMPLEX *cbround MATH_PROTO((COMPLEX *c, long i));
  1899. Xextern COMPLEX *csquare MATH_PROTO((COMPLEX *c));
  1900. Xextern COMPLEX *cconj MATH_PROTO((COMPLEX *c));
  1901. Xextern COMPLEX *creal MATH_PROTO((COMPLEX *c));
  1902. Xextern COMPLEX *cimag MATH_PROTO((COMPLEX *c));
  1903. Xextern COMPLEX *cneg MATH_PROTO((COMPLEX *c));
  1904. Xextern COMPLEX *cinv MATH_PROTO((COMPLEX *c));
  1905. Xextern COMPLEX *cint MATH_PROTO((COMPLEX *c));
  1906. Xextern COMPLEX *cfrac MATH_PROTO((COMPLEX *c));
  1907. Xextern BOOL ccmp MATH_PROTO((COMPLEX *c1, COMPLEX *c2));
  1908. X
  1909. X
  1910. X/*
  1911. X * More complicated functions.
  1912. X */
  1913. Xextern COMPLEX *cpowi MATH_PROTO((COMPLEX *c, NUMBER *q));
  1914. Xextern HASH chash MATH_PROTO((COMPLEX *c));
  1915. X
  1916. X
  1917. X/*
  1918. X * Transcendental routines.  These all take an epsilon argument to
  1919. X * specify how accurately these are to be calculated.
  1920. X */
  1921. Xextern COMPLEX *cpower MATH_PROTO((COMPLEX *c1, COMPLEX *c2, NUMBER *epsilon));
  1922. Xextern COMPLEX *csqrt MATH_PROTO((COMPLEX *c, NUMBER *epsilon));
  1923. Xextern COMPLEX *croot MATH_PROTO((COMPLEX *c, NUMBER *q, NUMBER *epsilon));
  1924. Xextern COMPLEX *cexp MATH_PROTO((COMPLEX *c, NUMBER *epsilon));
  1925. Xextern COMPLEX *cln MATH_PROTO((COMPLEX *c, NUMBER *epsilon));
  1926. Xextern COMPLEX *ccos MATH_PROTO((COMPLEX *c, NUMBER *epsilon));
  1927. Xextern COMPLEX *csin MATH_PROTO((COMPLEX *c, NUMBER *epsilon));
  1928. Xextern COMPLEX *cpolar MATH_PROTO((NUMBER *q1, NUMBER *q2, NUMBER *epsilon));
  1929. X
  1930. X
  1931. X/*
  1932. X * macro expansions to speed this thing up
  1933. X */
  1934. X#define cisreal(c)    (qiszero((c)->imag))
  1935. X#define cisimag(c)    (qiszero((c)->real) && !cisreal(c))
  1936. X#define ciszero(c)    (cisreal(c) && qiszero((c)->real))
  1937. X#define cisone(c)    (cisreal(c) && qisone((c)->real))
  1938. X#define cisnegone(c)    (cisreal(c) && qisnegone((c)->real))
  1939. X#define cisrunit(c)    (cisreal(c) && qisunit((c)->real))
  1940. X#define cisiunit(c)    (qiszero((c)->real) && qisunit((c)->imag))
  1941. X#define    cisunit(c)    (cisrunit(c) || cisiunit(c))
  1942. X#define cistwo(c)    (cisreal(c) && qistwo((c)->real))
  1943. X#define cisint(c)    (qisint((c)->real) && qisint((c)->imag))
  1944. X#define ciseven(c)    (qiseven((c)->real) && qiseven((c)->imag))
  1945. X#define cisodd(c)    (qisodd((c)->real) || qisodd((c)->imag))
  1946. X#define clink(c)    ((c)->links++, (c))
  1947. X
  1948. X
  1949. X/*
  1950. X * Pre-defined values.
  1951. X */
  1952. Xextern COMPLEX _czero_, _cone_, _conei_;
  1953. X
  1954. X#endif
  1955. X
  1956. X/* END CODE */
  1957. SHAR_EOF
  1958. chmod 0644 calc2.9.0/cmath.h || echo "restore of calc2.9.0/cmath.h fails"
  1959. set `wc -c calc2.9.0/cmath.h`;Sum=$1
  1960. if test "$Sum" != "3758"
  1961. then echo original size 3758, current size $Sum;fi
  1962. echo "x - extracting calc2.9.0/codegen.c (Text)"
  1963. sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/codegen.c &&
  1964. X/*
  1965. X * Copyright (c) 1993 David I. Bell
  1966. X * Permission is granted to use, distribute, or modify this source,
  1967. X * provided that this copyright notice remains intact.
  1968. X *
  1969. X * Module to generate opcodes from the input tokens.
  1970. X */
  1971. X
  1972. X#include "calc.h"
  1973. X#include "token.h"
  1974. X#include "symbol.h"
  1975. X#include "label.h"
  1976. X#include "opcodes.h"
  1977. X#include "string.h"
  1978. X#include "func.h"
  1979. X#include "config.h"
  1980. X
  1981. X
  1982. XFUNC *curfunc;
  1983. X
  1984. Xstatic BOOL getfilename(), getid();
  1985. Xstatic void getshowcommand(), getfunction(), getbody(), getdeclarations();
  1986. Xstatic void getstatement(), getobjdeclaration(), getobjvars();
  1987. Xstatic void getmatdeclaration(), getsimplebody(), getonedeclaration();
  1988. Xstatic void getcondition(), getmatargs(), getelement(), usesymbol();
  1989. Xstatic void definesymbol(), getcallargs();
  1990. Xstatic int getexprlist(), getassignment(), getaltcond(), getorcond();
  1991. Xstatic int getandcond(), getrelation(), getsum(), getproduct();
  1992. Xstatic int getorexpr(), getandexpr(), getshiftexpr(), getterm();
  1993. Xstatic int getidexpr();
  1994. Xstatic long getinitlist();
  1995. X
  1996. X
  1997. X/*
  1998. X * Read all the commands from an input file.
  1999. X * These are either declarations, or else are commands to execute now.
  2000. X * In general, commands are terminated by newlines or semicolons.
  2001. X * Exceptions are function definitions and escaped newlines.
  2002. X * Commands are read and executed until the end of file.
  2003. X * The toplevel flag indicates whether we are at the top interactive level.
  2004. X */
  2005. Xvoid
  2006. Xgetcommands(toplevel)
  2007. X    BOOL toplevel;
  2008. X{
  2009. X    char name[PATHSIZE+1];    /* program name */
  2010. X
  2011. X    if (!toplevel)
  2012. X        enterfilescope();
  2013. X    for (;;) {
  2014. X        (void) tokenmode(TM_NEWLINES);
  2015. X        switch (gettoken()) {
  2016. X
  2017. X        case T_DEFINE:
  2018. X            getfunction();
  2019. X            break;
  2020. X
  2021. X        case T_EOF:
  2022. X            if (!toplevel)
  2023. X                exitfilescope();
  2024. X            return;
  2025. X
  2026. X        case T_HELP:
  2027. X            if (!getfilename(name, FALSE)) {
  2028. X                strcpy(name, DEFAULTCALCHELP);
  2029. X            }
  2030. X            givehelp(name);
  2031. X            break;
  2032. X
  2033. X        case T_READ:
  2034. X            if (!getfilename(name, TRUE))
  2035. X                break;
  2036. X            if (opensearchfile(name, calcpath, CALCEXT) < 0) {
  2037. X                scanerror(T_NULL, "Cannot open \"%s\"\n", name);
  2038. X                break;
  2039. X            }
  2040. X            getcommands(FALSE);
  2041. X            break;
  2042. X
  2043. X        case T_WRITE:
  2044. X            if (!getfilename(name, TRUE))
  2045. X                break;
  2046. X            if (writeglobals(name))
  2047. X                scanerror(T_NULL, "Error writing \"%s\"\n", name);
  2048. X            break;
  2049. X
  2050. X        case T_SHOW:
  2051. X            rescantoken();
  2052. X            getshowcommand();
  2053. X            break;
  2054. X
  2055. X        case T_NEWLINE:
  2056. X        case T_SEMICOLON:
  2057. X            break;
  2058. X
  2059. X        default:
  2060. X            rescantoken();
  2061. X            initstack();
  2062. X            if (evaluate(FALSE))
  2063. X                updateoldvalue(curfunc);
  2064. X        }
  2065. X    }
  2066. X}
  2067. X
  2068. X
  2069. X/*
  2070. X * Evaluate a line of statements.
  2071. X * This is done by treating the current line as a function body,
  2072. X * compiling it, and then executing it.  Returns TRUE if the line
  2073. X * successfully compiled and executed.  The last expression result
  2074. X * is saved in the f_savedvalue element of the current function.
  2075. X * The nestflag variable should be FALSE for the outermost evaluation
  2076. X * level, and TRUE for all other calls (such as the 'eval' function).
  2077. X * The function name begins with an asterisk to indicate specialness.
  2078. X */
  2079. XBOOL
  2080. Xevaluate(nestflag)
  2081. X    BOOL nestflag;        /* TRUE if this is a nested evaluation */
  2082. X{
  2083. X    char *funcname;
  2084. X    BOOL gotstatement;
  2085. X
  2086. X    funcname = (nestflag ? "**" : "*");
  2087. X    beginfunc(funcname, nestflag);
  2088. X    gotstatement = FALSE;
  2089. X    for (;;) {
  2090. X        switch (gettoken()) {
  2091. X            case T_SEMICOLON:
  2092. X                break;
  2093. X
  2094. X            case T_NEWLINE:
  2095. X            case T_EOF:
  2096. X                goto done;
  2097. X
  2098. X            case T_GLOBAL:
  2099. X            case T_LOCAL:
  2100. X            case T_STATIC:
  2101. X                if (gotstatement) {
  2102. X                    scanerror(T_SEMICOLON, "Declarations must be used before code");
  2103. X                    return FALSE;
  2104. X                }
  2105. X                rescantoken();
  2106. X                getdeclarations();
  2107. X                break;
  2108. X
  2109. X            default:
  2110. X                rescantoken();
  2111. X                getstatement(NULL_LABEL, NULL_LABEL,
  2112. X                    NULL_LABEL, NULL_LABEL);
  2113. X                gotstatement = TRUE;
  2114. X        }
  2115. X    }
  2116. X
  2117. Xdone:
  2118. X    addop(OP_UNDEF);
  2119. X    addop(OP_RETURN);
  2120. X    checklabels();
  2121. X    if (errorcount)
  2122. X        return FALSE;
  2123. X    calculate(curfunc, 0);
  2124. X    return TRUE;
  2125. X}
  2126. X
  2127. X
  2128. X/*
  2129. X * Get a function declaration.
  2130. X * func = name '(' '' | name [ ',' name] ... ')' simplebody
  2131. X *    | name '(' '' | name [ ',' name] ... ')' body.
  2132. X */
  2133. Xstatic void
  2134. Xgetfunction()
  2135. X{
  2136. X    char *name;        /* parameter name */
  2137. X    int type;        /* type of token read */
  2138. X
  2139. X    (void) tokenmode(TM_DEFAULT);
  2140. X    if (gettoken() != T_SYMBOL) {
  2141. X        scanerror(T_NULL, "Function name expected");
  2142. X        return;
  2143. X    }
  2144. X    beginfunc(tokenstring(), FALSE);
  2145. X    enterfuncscope();
  2146. X    if (gettoken() != T_LEFTPAREN) {
  2147. X        scanerror(T_SEMICOLON, "Left parenthesis expected for function");
  2148. X        return;
  2149. X    }
  2150. X    for (;;) {
  2151. X        type = gettoken();
  2152. X        if (type == T_RIGHTPAREN)
  2153. X            break;
  2154. X        if (type != T_SYMBOL) {
  2155. X            scanerror(T_COMMA, "Bad function definition");
  2156. X            return;
  2157. X        }
  2158. X        name = tokenstring();
  2159. X        switch (symboltype(name)) {
  2160. X            case SYM_UNDEFINED:
  2161. X            case SYM_GLOBAL:
  2162. X            case SYM_STATIC:
  2163. X                (void) addparam(name);
  2164. X                break;
  2165. X            default:
  2166. X                scanerror(T_NULL, "Parameter \"%s\" is already defined", name);
  2167. X        }
  2168. X        type = gettoken();
  2169. X        if (type == T_RIGHTPAREN)
  2170. X            break;
  2171. X        if (type != T_COMMA) {
  2172. X            scanerror(T_COMMA, "Bad function definition");
  2173. X            return;
  2174. X        }
  2175. X    }
  2176. X    switch (gettoken()) {
  2177. X        case T_ASSIGN:
  2178. X            rescantoken();
  2179. X            getsimplebody();
  2180. X            break;
  2181. X        case T_LEFTBRACE:
  2182. X            rescantoken();
  2183. X            getbody(NULL_LABEL, NULL_LABEL, NULL_LABEL,
  2184. X                NULL_LABEL, TRUE);
  2185. X            break;
  2186. X        default:
  2187. X            scanerror(T_NULL,
  2188. X                "Left brace or equals sign expected for function");
  2189. X            return;
  2190. X    }
  2191. X    addop(OP_UNDEF);
  2192. X    addop(OP_RETURN);
  2193. X    endfunc();
  2194. X    exitfuncscope();
  2195. X}
  2196. X
  2197. X
  2198. X/*
  2199. X * Get a simple assignment style body for a function declaration.
  2200. X * simplebody = '=' assignment '\n'.
  2201. X */
  2202. Xstatic void
  2203. Xgetsimplebody()
  2204. X{
  2205. X    if (gettoken() != T_ASSIGN) {
  2206. X        scanerror(T_SEMICOLON, "Missing equals for simple function body");
  2207. X        return;
  2208. X    }
  2209. X    (void) tokenmode(TM_NEWLINES);
  2210. X    (void) getexprlist();
  2211. X    addop(OP_RETURN);
  2212. X    if (gettoken() != T_SEMICOLON)
  2213. X        rescantoken();
  2214. X    if (gettoken() != T_NEWLINE)
  2215. X        scanerror(T_NULL, "Illegal function definition");
  2216. X}
  2217. X
  2218. X
  2219. X/*
  2220. X * Get the body of a function, or a subbody of a function.
  2221. X * body = '{' [ declarations ] ... [ statement ] ... '}'
  2222. X *    | [ declarations ] ... [statement ] ... '\n'
  2223. X */
  2224. Xstatic void
  2225. Xgetbody(contlabel, breaklabel, nextcaselabel, defaultlabel, toplevel)
  2226. X    LABEL *contlabel, *breaklabel, *nextcaselabel, *defaultlabel;
  2227. X    BOOL toplevel;
  2228. X{
  2229. X    BOOL gotstatement;    /* TRUE if seen a real statement yet */
  2230. X    int oldmode;
  2231. X
  2232. X    if (gettoken() != T_LEFTBRACE) {
  2233. X        scanerror(T_SEMICOLON, "Missing left brace for function body");
  2234. X        return;
  2235. X    }
  2236. X    oldmode = tokenmode(TM_DEFAULT);
  2237. X    gotstatement = FALSE;
  2238. X    while (TRUE) {
  2239. X        switch (gettoken()) {
  2240. X        case T_RIGHTBRACE:
  2241. X            (void) tokenmode(oldmode);
  2242. X            return;
  2243. X
  2244. X        case T_GLOBAL:
  2245. X        case T_LOCAL:
  2246. X        case T_STATIC:
  2247. X            if (!toplevel) {
  2248. X                scanerror(T_SEMICOLON, "Declarations must be at the top of the function");
  2249. X                return;
  2250. X            }
  2251. X            if (gotstatement) {
  2252. X                scanerror(T_SEMICOLON, "Declarations must be used before code");
  2253. X                return;
  2254. X            }
  2255. X            rescantoken();
  2256. X            getdeclarations();
  2257. X            break;
  2258. X
  2259. X        default:
  2260. X            rescantoken();
  2261. X            getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
  2262. X            gotstatement = TRUE;
  2263. X        }
  2264. X    }
  2265. X}
  2266. X
  2267. X
  2268. X/*
  2269. X * Get a line of possible local, global, or static variable declarations.
  2270. X * declarations = { LOCAL | GLOBAL | STATIC } onedeclaration
  2271. X *    [ ',' onedeclaration ] ... ';'.
  2272. X */
  2273. Xstatic void
  2274. Xgetdeclarations()
  2275. X{
  2276. X    int type;
  2277. X
  2278. X    type = gettoken();
  2279. X
  2280. X    if ((type != T_LOCAL) && (type != T_GLOBAL) && (type != T_STATIC)) {
  2281. X        rescantoken();
  2282. X        return;
  2283. X    }
  2284. X
  2285. X    while (TRUE) {
  2286. X        getonedeclaration(type);
  2287. X
  2288. X        switch (gettoken()) {
  2289. X            case T_COMMA:
  2290. X                continue;
  2291. X
  2292. X            case T_NEWLINE:
  2293. X            case T_SEMICOLON:
  2294. X                return;
  2295. X
  2296. X            default:
  2297. X                scanerror(T_SEMICOLON, "Bad syntax in declaration statement");
  2298. X                return;
  2299. X        }
  2300. X    }
  2301. X}
  2302. X
  2303. X
  2304. X/*
  2305. X * Get a single declaration of a symbol of the specified type.
  2306. X * onedeclaration = name [ '=' getassignment ]
  2307. X *    | 'obj' type name [ '=' objvalues ]
  2308. X *    | 'mat' name '[' matargs ']' [ '=' matvalues ].
  2309. X */
  2310. Xstatic void
  2311. Xgetonedeclaration(type)
  2312. X{
  2313. X    char *name;        /* name of symbol seen */
  2314. X    int symtype;        /* type of symbol */
  2315. X    int vartype;        /* type of variable being defined */
  2316. X    LABEL label;
  2317. X
  2318. X    switch (type) {
  2319. X        case T_LOCAL:
  2320. X            symtype = SYM_LOCAL;
  2321. X            break;
  2322. X        case T_GLOBAL:
  2323. X            symtype = SYM_GLOBAL;
  2324. X            break;
  2325. X        case T_STATIC:
  2326. X            symtype = SYM_STATIC;
  2327. X            clearlabel(&label);
  2328. X            addoplabel(OP_INITSTATIC, &label);
  2329. X            break;
  2330. X    }
  2331. X
  2332. X    vartype = gettoken();
  2333. X    switch (vartype) {
  2334. X        case T_SYMBOL:
  2335. X            name = tokenstring();
  2336. X            definesymbol(name, symtype);
  2337. X            break;
  2338. X
  2339. X        case T_MAT:
  2340. X            addopone(OP_DEBUG, linenumber());
  2341. X            getmatdeclaration(symtype);
  2342. X            if (symtype == SYM_STATIC)
  2343. X                setlabel(&label);
  2344. X            return;
  2345. X
  2346. X        case T_OBJ:
  2347. X            addopone(OP_DEBUG, linenumber());
  2348. X            getobjdeclaration(symtype);
  2349. X            if (symtype == SYM_STATIC)
  2350. X                setlabel(&label);
  2351. X            return;
  2352. X
  2353. X        default:
  2354. X            scanerror(T_COMMA, "Bad syntax for declaration");
  2355. X            return;
  2356. X    }
  2357. X
  2358. X    if (gettoken() != T_ASSIGN) {
  2359. X        rescantoken();
  2360. X        if (symtype == SYM_STATIC)
  2361. X            setlabel(&label);
  2362. X        return;
  2363. X    }
  2364. X
  2365. X    /*
  2366. X     * Initialize the variable with the expression.  If the variable is
  2367. X     * static, arrange for the initialization to only be done once.
  2368. X     */
  2369. X    addopone(OP_DEBUG, linenumber());
  2370. X    usesymbol(name, FALSE);
  2371. X    getassignment();
  2372. X    addop(OP_ASSIGNPOP);
  2373. X    if (symtype == SYM_STATIC)
  2374. X        setlabel(&label);
  2375. X}
  2376. X
  2377. X
  2378. X/*
  2379. X * Get a statement.
  2380. X * statement = IF condition statement [ELSE statement]
  2381. X *    | FOR '(' [assignment] ';' [assignment] ';' [assignment] ')' statement
  2382. X *    | WHILE condition statement
  2383. X *    | DO statement WHILE condition ';'
  2384. X *    | SWITCH condition '{' [caseclause] ... '}'
  2385. X *    | CONTINUE ';'
  2386. X *    | BREAK ';'
  2387. X *    | RETURN assignment ';'
  2388. X *    | GOTO label ';'
  2389. X *    | MAT name '[' value [ ':' value ] [',' value [ ':' value ] ] ']' ';'
  2390. X *    | OBJ type '{' arg [ ',' arg ] ... '}' ] ';'
  2391. X *    | OBJ type name [ ',' name ] ';'
  2392. X *    | PRINT assignment [, assignment ] ... ';'
  2393. X *    | QUIT [ string ] ';'
  2394. X *    | SHOW item ';'
  2395. X *    | body
  2396. X *    | assignment ';'
  2397. X *    | label ':' statement
  2398. X *    | ';'.
  2399. X */
  2400. Xstatic void
  2401. Xgetstatement(contlabel, breaklabel, nextcaselabel, defaultlabel)
  2402. X    LABEL *contlabel;    /* label for continue statement */
  2403. X    LABEL *breaklabel;    /* label for break statement */
  2404. X    LABEL *nextcaselabel;    /* label for next case statement */
  2405. X    LABEL *defaultlabel;    /* label for default case */
  2406. X{
  2407. X    LABEL label1, label2, label3, label4;    /* locations for jumps */
  2408. X    int type;
  2409. X    BOOL printeol;
  2410. X
  2411. X    addopone(OP_DEBUG, linenumber());
  2412. X    switch (gettoken()) {
  2413. X    case T_NEWLINE:
  2414. X    case T_SEMICOLON:
  2415. X        return;
  2416. X
  2417. X    case T_RIGHTBRACE:
  2418. X        scanerror(T_NULL, "Extraneous right brace");
  2419. X        return;
  2420. X
  2421. X    case T_CONTINUE:
  2422. X        if (contlabel == NULL_LABEL) {
  2423. X            scanerror(T_SEMICOLON, "CONTINUE not within FOR, WHILE, or DO");
  2424. SHAR_EOF
  2425. echo "End of part 2"
  2426. echo "File calc2.9.0/codegen.c is continued in part 3"
  2427. echo "3" > s2_seq_.tmp
  2428. exit 0
  2429.