home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume23 / abc / part14 < prev    next >
Encoding:
Internet Message Format  |  1991-01-08  |  54.4 KB

  1. Subject:  v23i093:  ABC interactive programming environment, Part14/25
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: a898e146 3316befe b20c0c2a 983b099f
  5.  
  6. Submitted-by: Steven Pemberton <steven@cwi.nl>
  7. Posting-number: Volume 23, Issue 93
  8. Archive-name: abc/part14
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  abc/bed/e1node.c abc/bed/e1scrn.c abc/bint1/i1nua.c
  17. #   abc/btr/i1obj.c abc/btr/i1tlt.c
  18. # Wrapped by rsalz@litchi.bbn.com on Mon Dec 17 13:28:07 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. echo If this archive is complete, you will see the following message:
  21. echo '          "shar: End of archive 14 (of 25)."'
  22. if test -f 'abc/bed/e1node.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'abc/bed/e1node.c'\"
  24. else
  25.   echo shar: Extracting \"'abc/bed/e1node.c'\" \(10811 characters\)
  26.   sed "s/^X//" >'abc/bed/e1node.c' <<'END_OF_FILE'
  27. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  28. X
  29. X/*
  30. X * B editor -- Parse tree and Focus stack.
  31. X */
  32. X
  33. X#include "b.h"
  34. X#include "bedi.h"
  35. X#include "etex.h"
  36. X#include "bobj.h"
  37. X#include "node.h"
  38. X#include "bmem.h"
  39. X
  40. Xvalue grab();
  41. X
  42. X#define Register register
  43. X    /* Used for registers 4-6.  Define as empty macro on PDP */
  44. X
  45. X
  46. X/*
  47. X * Lowest level routines for 'node' data type.
  48. X */
  49. X
  50. X#define Isnode(n) ((n) && (n)->type == Nod)
  51. X
  52. X#define Nchildren(n) ((n)->len)
  53. X#define Symbol(n) ((n)->n_symbol)
  54. X#define Child(n, i) ((n)->n_child[(i)-1])
  55. X#define Marks(n) ((n)->n_marks)
  56. X#define Width(n) ((n)->n_width)
  57. X
  58. X
  59. X/*
  60. X * Routines which are macros for the compiler but real functions for lint,
  61. X * so it will check the argument types more strictly.
  62. X */
  63. X
  64. X#ifdef lint
  65. Xnode
  66. Xnodecopy(n)
  67. X    node n;
  68. X{
  69. X    return (node) copy((value) n);
  70. X}
  71. X
  72. Xnoderelease(n)
  73. X    node n;
  74. X{
  75. X    release((value)n);
  76. X}
  77. X
  78. Xnodeuniql(pn)
  79. X    node *pn;
  80. X{
  81. X    uniql((value*)pn);
  82. X}
  83. X#endif /* lint */
  84. X
  85. X/*
  86. X * Allocate a new node.
  87. X */
  88. X
  89. XHidden node
  90. Xmk_node(nch)
  91. X    register int nch;
  92. X{
  93. X    register node n = (node) grab(Nod, nch);
  94. X    register int i;
  95. X
  96. X    n->n_marks = 0;
  97. X    n->n_width = 0;
  98. X    n->n_symbol = 0;
  99. X    for (i = nch-1; i >= 0; --i)
  100. X        n->n_child[i] = Nnil;
  101. X    return n;
  102. X}
  103. X
  104. XVisible node
  105. Xnewnode(nch, sym, children)
  106. X    register int nch;
  107. X    Register int sym;
  108. X    register node children[];
  109. X{
  110. X    register node n = (node) mk_node(nch); /* Must preset with zeros! */
  111. X
  112. X    Symbol(n) = sym;
  113. X    for (; nch > 0; --nch)
  114. X        Child(n, nch) = children[nch-1];
  115. X    Width(n) = evalwidth(n);
  116. X    return n;
  117. X}
  118. X
  119. XVisible int nodewidth(n) node n; {
  120. X    if (Is_etext(n))
  121. X        return e_length((value) n);
  122. X    else
  123. X        return Width(n);
  124. X}
  125. X
  126. X/*
  127. X * Macros to change the fields of a node.
  128. X */
  129. X
  130. X#define Locchild(pn, i) \
  131. X    (Refcnt(*(pn)) == 1 || nodeuniql(pn), &Child(*(pn), i))
  132. X#define Setmarks(pn, x) \
  133. X    (Refcnt(*(pn)) == 1 || nodeuniql(pn), Marks(*(pn))=(x))
  134. X#define Setwidth(pn, w) (Refcnt(*(pn)) == 1 || nodeuniql(pn), Width(*(pn))=w)
  135. X
  136. X
  137. X/*
  138. X * Change a child of a node.
  139. X * Like treereplace(), it does not increase the reference count of n.
  140. X */
  141. X
  142. XVisible Procedure
  143. Xsetchild(pn, i, n)
  144. X    register node *pn;
  145. X    register int i;
  146. X    Register node n;
  147. X{
  148. X    register node *pch;
  149. X    register node oldchild;
  150. X
  151. X    Assert(Isnode(*pn));
  152. X    pch = Locchild(pn, i);
  153. X    oldchild = *pch;
  154. X    *pch = n;
  155. X    repwidth(pn, oldchild, n);
  156. X    noderelease(oldchild);
  157. X}
  158. X
  159. X
  160. X/*
  161. X * Lowest level routines for 'path' data type.
  162. X */
  163. X
  164. X#define NPATHFIELDS 6
  165. X
  166. X#define Parent(p) ((p)->p_parent)
  167. X#define Tree(p) ((p)->p_tree)
  168. X#define Ichild(p) ((p)->p_ichild)
  169. X
  170. X
  171. X/*
  172. X * Routines which are macros for the compiler but real functions for lint,
  173. X * so it will check the argument types more strictly.
  174. X */
  175. X
  176. X#ifdef lint
  177. XVisible path
  178. Xpathcopy(p)
  179. X    path p;
  180. X{
  181. X    return (path) copy((value) p);
  182. X}
  183. X
  184. XVisible Procedure
  185. Xpathrelease(p)
  186. X    path p;
  187. X{
  188. X    release((value)p);
  189. X}
  190. X
  191. XVisible Procedure
  192. Xpathuniql(pp)
  193. X    path *pp;
  194. X{
  195. X    uniql((value*)pp);
  196. X}
  197. X#endif /* lint */
  198. X
  199. X/*
  200. X * Allocate a new path entry.
  201. X */
  202. X
  203. XHidden path
  204. Xmk_path()
  205. X{
  206. X    register path p = (path) grab(Pat, 0);
  207. X
  208. X    p->p_parent = NilPath;
  209. X    p->p_tree = Nnil;
  210. X    p->p_ichild = 0;
  211. X    p->p_ycoord = 0;
  212. X    p->p_xcoord = 0;
  213. X    p->p_level = 0;
  214. X    p->p_addmarks = 0;
  215. X    p->p_delmarks = 0;
  216. X    return p;
  217. X}
  218. X
  219. XVisible path
  220. Xnewpath(pa, n, i)
  221. X    register path pa;
  222. X    register node n;
  223. X    Register int i;
  224. X{
  225. X    register path p = (path) mk_path();
  226. X
  227. X    Parent(p) = pa;
  228. X    Tree(p) = n;
  229. X    Ichild(p) = i;
  230. X    Ycoord(p) = Xcoord(p) = Level(p) = 0;
  231. X    return p;
  232. X}
  233. X
  234. X
  235. X/*
  236. X * Macros to change the fields of a path entry.
  237. X */
  238. X
  239. X#define Uniqp(pp) (Refcnt(*(pp)) == 1 || pathuniql(pp))
  240. X
  241. X#define Setcoord(pp, y, x, level) (Uniqp(pp), \
  242. X    (*(pp))->p_ycoord = y, (*(pp))->p_xcoord = x, (*(pp))->p_level = level)
  243. X
  244. X#define Locparent(pp) (Uniqp(pp), &Parent(*(pp)))
  245. X
  246. X#define Loctree(pp) (Uniqp(pp), &Tree(*(pp)))
  247. X
  248. X#define Addmarks(pp, x) (Uniqp(pp), \
  249. X    (*(pp))->p_addmarks |= (x), (*(pp))->p_delmarks &= ~(x))
  250. X
  251. X#define Delmarks(pp, x) (Uniqp(pp), \
  252. X    (*(pp))->p_delmarks |= (x), (*(pp))->p_addmarks &= ~(x))
  253. X
  254. X/*
  255. X * The following procedure sets the new width of node *pn when child
  256. X * oldchild is replaced by child newchild.
  257. X * This was added because the original call to evalwidth seemed to
  258. X * be the major caller of noderepr() and fwidth().
  259. X */
  260. X
  261. XHidden Procedure
  262. Xrepwidth(pn, old, new)
  263. X    register node *pn;
  264. X    Register node old;
  265. X    Register node new;
  266. X{
  267. X    register int w = Width(*pn);
  268. X    register int oldwidth = nodewidth(old);
  269. X    register int newwidth = nodewidth(new);
  270. X
  271. X    if (w >= 0) {
  272. X        Assert(oldwidth >= 0);
  273. X        if (newwidth < 0) {
  274. X            Setwidth(pn, newwidth);
  275. X            return;
  276. X        }
  277. X    }
  278. X    else {
  279. X        if (oldwidth == w && newwidth > 0) {
  280. X            w= evalwidth(*pn);
  281. X            Setwidth(pn, w);
  282. X            return;
  283. X        }
  284. X        if (oldwidth > 0)
  285. X            oldwidth = 0;
  286. X        if (newwidth > 0)
  287. X            newwidth = 0;
  288. X    }
  289. X    newwidth -= oldwidth;
  290. X    if (newwidth)
  291. X        Setwidth(pn, w + newwidth);
  292. X}
  293. X
  294. X
  295. XVisible Procedure
  296. Xmarkpath(pp, new)
  297. X    register path *pp;
  298. X    register markbits new;
  299. X{
  300. X    register node *pn;
  301. X    register markbits old;
  302. X
  303. X    Assert(Is_Node(Tree(*pp)));
  304. X    old = Marks(Tree(*pp));
  305. X    if ((old|new) == old)
  306. X        return; /* Bits already set */
  307. X
  308. X    pn = Loctree(pp);
  309. X    Setmarks(pn, old|new);
  310. X    Addmarks(pp, new&~old);
  311. X}
  312. X
  313. X
  314. XVisible Procedure
  315. Xunmkpath(pp, del)
  316. X    register path *pp;
  317. X    register int del;
  318. X{
  319. X    register node *pn;
  320. X    register markbits old;
  321. X
  322. X    Assert(Is_Node(Tree(*pp)));
  323. X    old = Marks(Tree(*pp));
  324. X    if ((old&~del) == del)
  325. X        return;
  326. X
  327. X    pn = Loctree(pp);
  328. X    Setmarks(pn, old&~del);
  329. X    Delmarks(pp, del&old);
  330. X}
  331. X
  332. X
  333. XHidden Procedure
  334. Xclearmarks(pn)
  335. X    register node *pn;
  336. X{
  337. X    register int i;
  338. X
  339. X    if (!Marks(*pn))
  340. X        return;
  341. X    if (Isnode(*pn)) {
  342. X        Setmarks(pn, 0);
  343. X        for (i = Nchildren(*pn); i > 0; --i)
  344. X            clearmarks(Locchild(pn, i));
  345. X    }
  346. X}
  347. X
  348. X
  349. X/*
  350. X * Replace the focus' tree by a new node.
  351. X * WARNING: n's reference count is not increased!
  352. X * You can also think of this as: treereplace(pp, n) implies noderelease(n).
  353. X * Mark bits are copied from the node being replaced.
  354. X */
  355. X
  356. XVisible Procedure
  357. Xtreereplace(pp, n)
  358. X    register path *pp;
  359. X    register node n;
  360. X{
  361. X    register node *pn;
  362. X    register markbits old;
  363. X
  364. X    pn = Loctree(pp);
  365. X    if (Is_Node(*pn))
  366. X        old = Marks(*pn);
  367. X    else
  368. X        old = 0;
  369. X    noderelease(*pn);
  370. X    *pn = n;
  371. X    if (Is_Node(n)) {
  372. X        clearmarks(pn);
  373. X        if (old)
  374. X            Setmarks(pn, old);
  375. X    }
  376. X    else if (old)
  377. X        Addmarks(pp, old);
  378. X}
  379. X
  380. X
  381. XVisible bool
  382. Xup(pp)
  383. X    register path *pp;
  384. X{
  385. X    register path p = *pp;
  386. X    register path pa = Parent(p);
  387. X    register path *ppa;
  388. X    register node n;
  389. X    register node npa;
  390. X    register node *pn;
  391. X    node oldchild;
  392. X    node *pnpa;
  393. X    int i;
  394. X    markbits add;
  395. X    markbits del;
  396. X
  397. X    if (!pa)
  398. X        return No;
  399. X
  400. X    i = ichild(p);
  401. X    n = Tree(p);
  402. X    if (Child(Tree(pa), i) != n) {
  403. X        n = nodecopy(n);
  404. X        ppa = Locparent(pp);
  405. X        pnpa = Loctree(ppa);
  406. X        pn = Locchild(pnpa, i);
  407. X        oldchild = *pn;
  408. X        *pn = n;
  409. X        repwidth(pnpa, oldchild, n);
  410. X        noderelease(oldchild);
  411. X    
  412. X        add = p->p_addmarks;
  413. X        del = p->p_delmarks;
  414. X        if (add|del) {
  415. X            p = *pp;
  416. X            p->p_addmarks = 0;
  417. X            p->p_delmarks = 0;
  418. X            if (add)
  419. X                Addmarks(ppa, add);
  420. X            npa = *pnpa;
  421. X            if (del) {
  422. X                for (i = Nchildren(npa); i > 0; --i)
  423. X                    if (i != ichild(p))
  424. X                        del &= ~marks(Child(npa, i));
  425. X                Delmarks(ppa, del);
  426. X            }
  427. X            Setmarks(pnpa, Marks(npa)&~del|add);
  428. X        }
  429. X    }
  430. X    /* else: still connected */
  431. X
  432. X    p = pathcopy(Parent(*pp));
  433. X    pathrelease(*pp);
  434. X    *pp = p;
  435. X    return Yes;
  436. X}
  437. X
  438. X
  439. XVisible bool
  440. Xdowni(pp, i)
  441. X    register path *pp;
  442. X    register int i;
  443. X{
  444. X    register node n;
  445. X    auto int y;
  446. X    auto int x;
  447. X    auto int level;
  448. X
  449. X    n = Tree(*pp);
  450. X    if (!Isnode(n) || i < 1 || i > Nchildren(n))
  451. X        return No;
  452. X
  453. X    y = Ycoord(*pp);
  454. X    x = Xcoord(*pp);
  455. X    level = Level(*pp);
  456. X    *pp = newpath(*pp, nodecopy(Child(n, i)), i);
  457. X    evalcoord(n, i, &y, &x, &level);
  458. X    Setcoord(pp, y, x, level);
  459. X    return Yes;
  460. X}
  461. X
  462. X
  463. XVisible bool
  464. Xdownrite(pp)
  465. X    register path *pp;
  466. X{
  467. X    if (!Isnode(Tree(*pp)))
  468. X        return No;
  469. X    return downi(pp, Nchildren(Tree(*pp)));
  470. X}
  471. X
  472. X
  473. XVisible bool
  474. Xleft(pp)
  475. X    register path *pp;
  476. X{
  477. X    register int i;
  478. X
  479. X    i = ichild(*pp) - 1;
  480. X    if (i <= 0)
  481. X        return No;
  482. X    if (!up(pp))
  483. X        return No;
  484. X    return downi(pp, i);
  485. X}
  486. X
  487. X
  488. XVisible bool
  489. Xrite(pp)
  490. X    register path *pp;
  491. X{
  492. X    register int i;
  493. X    register path pa = Parent(*pp);
  494. X
  495. X    i = ichild(*pp) + 1;
  496. X    if (!pa || i > Nchildren(Tree(pa)))
  497. X        return No;
  498. X    if (!up(pp))
  499. X        return No;
  500. X    return downi(pp, i);
  501. X}
  502. X
  503. X
  504. X/*
  505. X * Highest level: small utilities.
  506. X *
  507. X * WARNING: Several of the following routines may change their argument
  508. X * even if they return No.
  509. X * HINT: Some of these routines are not used; they are included for
  510. X * completeness of the provided set of operators only.  If you have
  511. X * space problems (as, e.g., on a PDP-11), you can delete the superfluous
  512. X * ones (lint will tell you which they are).
  513. X */
  514. X
  515. XVisible Procedure
  516. Xtop(pp)
  517. X    register path *pp;
  518. X{
  519. X    while (up(pp))
  520. X        ;
  521. X}
  522. X
  523. X#ifdef NOT_USED
  524. XVisible bool
  525. Xnextnode(pp)
  526. X    register path *pp;
  527. X{
  528. X    while (!rite(pp)) {
  529. X        if (!up(pp))
  530. X            return No;
  531. X    }
  532. X    return Yes;
  533. X}
  534. X#endif
  535. X
  536. X#ifdef NOT_USED
  537. XVisible Procedure
  538. Xfirstleaf(pp)
  539. X    register path *pp;
  540. X{
  541. X    while (down(pp))
  542. X        ;
  543. X}
  544. X#endif
  545. X
  546. X#ifdef NOT_USED
  547. XVisible bool
  548. Xnextleaf(pp)
  549. X    register path *pp;
  550. X{
  551. X    if (!nextnode(pp))
  552. X        return No;
  553. X    firstleaf(pp);
  554. X    return Yes;
  555. X}
  556. X#endif
  557. X
  558. X#ifdef NOT_USED
  559. XVisible bool
  560. Xprevnode(pp)
  561. X    register path *pp;
  562. X{
  563. X    while (!left(pp)) {
  564. X        if (!up(pp))
  565. X            return No;
  566. X    }
  567. X    return Yes;
  568. X}
  569. X#endif
  570. X
  571. X#ifdef NOT_USED
  572. XVisible Procedure
  573. Xlastleaf(pp)
  574. X    register path *pp;
  575. X{
  576. X    while (downrite(pp))
  577. X            ;
  578. X}
  579. X#endif
  580. X
  581. X#ifdef NOT_USED
  582. XVisible bool
  583. Xprevleaf(pp)
  584. X    register path *pp;
  585. X{
  586. X    if (!prevnode(pp))
  587. X        return No;
  588. X    lastleaf(pp);
  589. X    return Yes;
  590. X}
  591. X#endif
  592. X
  593. X#ifdef NOT_USED
  594. XVisible bool
  595. Xnextmarked(pp, x)
  596. X    register path *pp;
  597. X    register markbits x;
  598. X{
  599. X    do {
  600. X        if (!nextnode(pp))
  601. X            return No;
  602. X    } while (!marked(*pp, x));
  603. X    while (down(pp)) {
  604. X        while (!marked(*pp, x)) {
  605. X            if (!rite(pp)) {
  606. X                if (!up(pp)) Abort();
  607. X                return Yes;
  608. X            }
  609. X        }
  610. X    }
  611. X    return Yes;
  612. X}
  613. X#endif
  614. X
  615. XVisible bool
  616. Xfirstmarked(pp, x)
  617. X    register path *pp;
  618. X    register markbits x;
  619. X{
  620. X    while (!marked(*pp, x)) {
  621. X        if (!up(pp))
  622. X            return No;
  623. X    }
  624. X    while (down(pp)) {
  625. X        while (Is_etext(tree(*pp)) || !marked(*pp, x)) {
  626. X            if (!rite(pp)) {
  627. X                if (!up(pp)) Abort();
  628. X                return Yes;
  629. X            }
  630. X        }
  631. X    }
  632. X    return Yes;
  633. X}
  634. X
  635. X#ifdef NOT_USED
  636. XVisible bool
  637. Xprevmarked(pp, x)
  638. X    register path *pp;
  639. X    register markbits x;
  640. X{
  641. X    do {
  642. X        if (!prevnode(pp))
  643. X            return No;
  644. X    } while (!marked(*pp, x));
  645. X    while (downrite(pp)) {
  646. X        while (!marked(*pp, x)) {
  647. X            if (!left(pp)) {
  648. X                if (!up(pp)) Abort();
  649. X                return Yes;
  650. X            }
  651. X        }
  652. X    }
  653. X    return Yes;
  654. X}
  655. X#endif
  656. X
  657. X/*
  658. X * Deliver the path length to the root.
  659. X */
  660. X
  661. X
  662. XVisible Procedure
  663. Xpathlength(p)
  664. X    register path p;
  665. X{
  666. X    register int n;
  667. X
  668. X    for (n = 0; p; ++n)
  669. X        p = parent(p);
  670. X    return n;
  671. X}
  672. X
  673. XVisible Procedure
  674. Xputintrim(pn, head, tail, str)
  675. X    register value *pn;
  676. X    register int head;
  677. X    Register int tail;
  678. X    Register string str;
  679. X{
  680. X    register value v = *pn; 
  681. X    value t1, t2, t3;
  682. X    int len= e_length(v);
  683. X
  684. X    Assert(head >= 0 && tail >= 0 && head + tail <= len);
  685. X    t1= e_icurtail(v, head);
  686. X    t2= mk_etext(str);
  687. X    t3= e_concat(t1, t2);
  688. X    release(t1); release(t2);
  689. X    t1= e_ibehead(v, len - tail + 1);
  690. X    t2= e_concat(t3, t1);
  691. X    release(t3); release(t1);
  692. X    release(v);
  693. X    *pn = t2;
  694. X}
  695. X
  696. X/*
  697. X * Touch the node in focus.
  698. X */
  699. X
  700. XVisible Procedure
  701. Xtouchpath(pp)
  702. X    register path *pp;
  703. X{
  704. X    nodeuniql(Loctree(pp));
  705. X}
  706. END_OF_FILE
  707.   if test 10811 -ne `wc -c <'abc/bed/e1node.c'`; then
  708.     echo shar: \"'abc/bed/e1node.c'\" unpacked with wrong size!
  709.   fi
  710.   # end of 'abc/bed/e1node.c'
  711. fi
  712. if test -f 'abc/bed/e1scrn.c' -a "${1}" != "-c" ; then 
  713.   echo shar: Will not clobber existing file \"'abc/bed/e1scrn.c'\"
  714. else
  715.   echo shar: Extracting \"'abc/bed/e1scrn.c'\" \(11204 characters\)
  716.   sed "s/^X//" >'abc/bed/e1scrn.c' <<'END_OF_FILE'
  717. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  718. X
  719. X/*
  720. X * B editor -- Screen management package, higher level routines.
  721. X */
  722. X
  723. X#include "b.h"
  724. X#include "bedi.h"
  725. X#include "etex.h"
  726. X#include "feat.h"
  727. X#include "bobj.h"
  728. X#include "erro.h"
  729. X#include "node.h"
  730. X#include "supr.h"
  731. X#include "gram.h"
  732. X#include "cell.h"
  733. X#include "trm.h"
  734. X#include "args.h"
  735. X
  736. Xcell *gettop();
  737. Xextern int focy;
  738. Xextern int focx;
  739. X
  740. XVisible int winstart;
  741. X
  742. XVisible int winheight;
  743. XVisible int indent;
  744. XVisible int llength;
  745. X
  746. XVisible bool noscroll;
  747. XVisible bool nosense;
  748. XVisible bool raw_newline= No;
  749. X
  750. XHidden cell *tops;
  751. X
  752. X
  753. X/*
  754. X * Actual screen update.
  755. X */
  756. X
  757. XVisible Procedure
  758. Xactupdate(copybuffer, recording, lasttime)
  759. X    value copybuffer;
  760. X    bool recording;
  761. X    bool lasttime; /* Yes if called from final screen update */
  762. X{
  763. X    register cell *p;
  764. X    cell *top = tops;
  765. X    register int diff;
  766. X    register int curlno;
  767. X    register int delcnt = 0; /* Lines deleted during the process. */
  768. X        /* Used as offset for lines that are on the screen. */
  769. X    int totlines = 0;
  770. X    int topline = 0;
  771. X    int scrlines = 0;
  772. X
  773. X    if (winstart > 0)
  774. X        growwin();
  775. X    if (winstart <= 0) {
  776. X        top = gettop(tops);
  777. X        for (p = tops; p && p != top; p = p->c_link)
  778. X            ++topline;
  779. X        totlines = topline;
  780. X    }
  781. X    startactupdate(lasttime);
  782. X    focy = Nowhere;
  783. X    for (p = top, curlno = winstart; p && curlno < winheight;
  784. X        curlno += Space(p), p = p->c_link) {
  785. X        ++scrlines;
  786. X        if (lasttime) {
  787. X            p->c_newfocus = No;
  788. X            p->c_newvhole = 0;
  789. X        }
  790. X        if (p->c_onscreen != Nowhere && Space(p) == Oldspace(p)) {
  791. X            /* Old comrade */
  792. X            diff = p->c_onscreen - (curlno+delcnt);
  793. X            /* diff can't be negative due to 'makeroom' below! */
  794. X            if (diff > 0) { /* Get him here */
  795. X                trmscrollup(curlno, winheight, diff);
  796. X                delcnt += diff;
  797. X            }
  798. X            if (p->c_oldfocus || p->c_newfocus
  799. X                || p->c_oldindent != p->c_newindent
  800. X                || p->c_onscreen + Space(p) >= winheight) {
  801. X                delcnt = make2room(p, curlno, delcnt);
  802. X                outline(p, curlno);
  803. X            }
  804. X        }
  805. X        else { /* New guy, make him toe the line */
  806. X            delcnt = makeroom(p, curlno, delcnt);
  807. X            delcnt = make2room(p, curlno, delcnt);
  808. X            outline(p, curlno);
  809. X        }
  810. X        p->c_onscreen = curlno;
  811. X        p->c_oldindent = p->c_newindent;
  812. X        p->c_oldvhole = p->c_newvhole;
  813. X        p->c_oldfocus = p->c_newfocus;
  814. X    }
  815. X    totlines += scrlines;
  816. X    for (; p; p = p->c_link) { /* Count rest and remove old memories */
  817. X        ++totlines;
  818. X        /* This code should never find any garbage?! */
  819. X#ifndef NDEBUG
  820. X        if (p->c_onscreen != Nowhere)
  821. X            debug("[Garbage removed from screen list]");
  822. X#endif /* NDEBUG */
  823. X        p->c_onscreen = Nowhere;
  824. X    }
  825. X    trmscrollup(curlno, winheight, -delcnt);
  826. X    curlno += delcnt;
  827. X    if (curlno < winheight) { /* Clear lines beyond end of unit */
  828. X        trmputdata(curlno, winheight-1, 0, "");
  829. X        scrlines += winheight-curlno;
  830. X    }
  831. X    if (!lasttime) {
  832. X        stsline(totlines, topline, scrlines, copybuffer, recording);
  833. X        if (focy != Nowhere)
  834. X            trmsync(focy, focx);
  835. X        else
  836. X            trmsync(winheight, 0);
  837. X    }
  838. X    endactupdate();
  839. X}
  840. X
  841. X
  842. X/*
  843. X * Grow the window if not maximum size.
  844. X */
  845. X
  846. XHidden Procedure
  847. Xgrowwin()
  848. X{
  849. X    register int winsize;
  850. X    register int growth;
  851. X    register cell *p;
  852. X
  853. X    winsize = 0;
  854. X    for (p = tops; p; p = p->c_link)
  855. X        winsize += Space(p);
  856. X    if (winsize <= winheight - winstart)
  857. X        return; /* No need to grow */
  858. X    if (winsize > winheight)
  859. X        winsize = winheight; /* Limit size to maximum available */
  860. X
  861. X    growth = winsize - (winheight - winstart);
  862. X    trmscrollup(0, winheight - (winstart!=winheight), growth);
  863. X    winstart -= growth;
  864. X    for (p = tops; p; p = p->c_link) {
  865. X        if (p->c_onscreen != Nowhere)
  866. X            p->c_onscreen -= growth;
  867. X    }
  868. X}
  869. X
  870. X
  871. X/*
  872. X * Make room for possible insertions.
  873. X * (If a line is inserted, it may be necessary to delete lines
  874. X * further on the screen.)
  875. X */
  876. X
  877. XHidden Procedure
  878. Xmakeroom(p, curlno, delcnt)
  879. X    register cell *p;
  880. X    register int curlno;
  881. X    register int delcnt;
  882. X{
  883. X    register int here = 0;
  884. X    register int need = Space(p);
  885. X    register int amiss;
  886. X    int avail;
  887. X    int diff;
  888. X
  889. X    Assert(p);
  890. X    do {
  891. X        p = p->c_link;
  892. X        if (!p)
  893. X            return delcnt;
  894. X    } while (p->c_onscreen == Nowhere);
  895. X    here = p->c_onscreen - delcnt;
  896. X    avail = here - curlno;
  897. X    amiss = need - avail;
  898. X#ifndef NDEBUG
  899. X    if (dflag)
  900. X        debug("[makeroom: curlno=%d, delcnt=%d, here=%d, avail=%d, amiss=%d]",
  901. X            curlno, delcnt, here, avail, amiss);
  902. X#endif /* NDEBUG */
  903. X    if (amiss <= 0)
  904. X        return delcnt;
  905. X    if (amiss > delcnt) {
  906. X        for (; p; p = p->c_link) {
  907. X            if (p->c_onscreen != Nowhere) {
  908. X                diff = amiss-delcnt;
  909. X                if (p->c_onscreen - delcnt - here < diff)
  910. X                    diff = p->c_onscreen - delcnt - here;
  911. X                if (diff > 0) {
  912. X                    trmscrollup(here, winheight, diff);
  913. X                    delcnt += diff;
  914. X                }
  915. X                p->c_onscreen += -delcnt + amiss;
  916. X                here = p->c_onscreen - amiss;
  917. X                if (p->c_onscreen >= winheight)
  918. X                    p->c_onscreen = Nowhere;
  919. X            }
  920. X            here += Space(p);
  921. X        }
  922. X        /* Now for all p encountered whose p->c_onscreen != Nowhere,
  923. X         * p->c_onscreen - amiss is its actual position.
  924. X         */
  925. X        if (amiss > delcnt) {
  926. X            trmscrollup(winheight - amiss, winheight, amiss-delcnt);
  927. X            delcnt = amiss;
  928. X        }
  929. X    }
  930. X    /* Now amiss <= delcnt */
  931. X    trmscrollup(curlno + avail, winheight, -amiss);
  932. X    return delcnt - amiss;
  933. X}
  934. X
  935. X
  936. X/*
  937. X * Addition to makeroom - make sure the status line is not overwritten.
  938. X * Returns new delcnt, like makeroom does.
  939. X */
  940. X
  941. XHidden int
  942. Xmake2room(p, curlno, delcnt)
  943. X    cell *p;
  944. X    int curlno;
  945. X    int delcnt;
  946. X{
  947. X    int nextline = curlno + Space(p);
  948. X    int sline = winheight - delcnt;
  949. X    int diff;
  950. X
  951. X    if (sline < curlno) {
  952. X#ifndef NDEBUG
  953. X        debug("[Status line overwritten]");
  954. X#endif /* NDEBUG */
  955. X        return delcnt;
  956. X    }
  957. X    if (nextline > winheight)
  958. X        nextline = winheight;
  959. X    diff = nextline - sline;
  960. X    if (diff > 0) {
  961. X        trmscrollup(sline, winheight, -diff);
  962. X        delcnt -= diff;
  963. X    }
  964. X    return delcnt;
  965. X        
  966. X}
  967. X
  968. X
  969. X/*
  970. X * Routine called for every change in the screen.
  971. X */
  972. X
  973. XVisible Procedure
  974. Xvirtupdate(oldep, newep, highest)
  975. X    environ *oldep;
  976. X    environ *newep;
  977. X    int highest;
  978. X{
  979. X    environ old;
  980. X    environ new;
  981. X    register int oldlno;
  982. X    register int newlno;
  983. X    register int oldlcnt;
  984. X    register int newlcnt;
  985. X    register int i;
  986. X
  987. X    if (!oldep) {
  988. X        highest = 1;
  989. X        trmputdata(winstart, winheight, indent, "");
  990. X        discard(tops);
  991. X        tops = Cnil;
  992. X        Ecopy(*newep, old);
  993. X    }
  994. X    else {
  995. X        Ecopy(*oldep, old);
  996. X    }
  997. X    Ecopy(*newep, new);
  998. X
  999. X    savefocus(&new);
  1000. X
  1001. X    oldlcnt = fixlevels(&old, &new, highest);
  1002. X    newlcnt = -nodewidth(tree(new.focus));
  1003. X    if (newlcnt < 0)
  1004. X        newlcnt = 0;
  1005. X    i = -nodewidth(tree(old.focus));
  1006. X    if (i < 0)
  1007. X        i = 0;
  1008. X    newlcnt -= i - oldlcnt;
  1009. X        /* Offset newlcnt as much as oldcnt is offset */
  1010. X    
  1011. X    oldlno = Ycoord(old.focus);
  1012. X    newlno = Ycoord(new.focus);
  1013. X    if (!atlinestart(&old))
  1014. X        ++oldlcnt;
  1015. X    else
  1016. X        ++oldlno;
  1017. X    if (!atlinestart(&new))
  1018. X        ++newlcnt;
  1019. X    else
  1020. X        ++newlno;
  1021. X    Assert(oldlno == newlno);
  1022. X
  1023. X    tops = replist(tops, build(new.focus, newlcnt), oldlno, oldlcnt);
  1024. X
  1025. X    setfocus(tops); /* Incorporate the information saved by savefocus */
  1026. X
  1027. X    Erelease(old);
  1028. X    Erelease(new);
  1029. X}
  1030. X
  1031. X
  1032. XHidden bool
  1033. Xatlinestart(ep)
  1034. X    environ *ep;
  1035. X{
  1036. X    register string repr = noderepr(tree(ep->focus))[0];
  1037. X
  1038. X    return Fw_negative(repr);
  1039. X}
  1040. X
  1041. X
  1042. X/*
  1043. X * Make the two levels the same, and make sure they both are line starters
  1044. X * if at all possible.  Return the OLD number of lines to be replaced.
  1045. X * (0 if the whole unit has no linefeeds.)
  1046. X */
  1047. X
  1048. XHidden int
  1049. Xfixlevels(oldep, newep, highest)
  1050. X    register environ *oldep;
  1051. X    register environ *newep;
  1052. X    register int highest;
  1053. X{
  1054. X    register int oldpl = pathlength(oldep->focus);
  1055. X    register int newpl = pathlength(newep->focus);
  1056. X    register bool intraline = No;
  1057. X    register int w;
  1058. X
  1059. X    if (oldpl < highest)
  1060. X        highest = oldpl;
  1061. X    if (newpl < highest)
  1062. X        highest = newpl;
  1063. X    while (oldpl > highest) {
  1064. X        if (!up(&oldep->focus)) Abort();
  1065. X        --oldpl;
  1066. X    }
  1067. X    while (newpl > highest) {
  1068. X        if (!up(&newep->focus)) Abort();
  1069. X        --newpl;
  1070. X    }
  1071. X    if (Ycoord(newep->focus) != Ycoord(oldep->focus) ||
  1072. X        Level(newep->focus) != Level(oldep->focus)) {
  1073. X        /* Inconsistency found.  */
  1074. X        Assert(highest > 1); /* Inconsistency at top level. Stop. */
  1075. X        return fixlevels(oldep, newep, 1); /* Try to recover. */
  1076. X    }
  1077. X    intraline = nodewidth(tree(oldep->focus)) >= 0
  1078. X        && nodewidth(tree(newep->focus)) >= 0;
  1079. X    while (!atlinestart(oldep) || !atlinestart(newep)) {
  1080. X        /* Find beginning of lines for both */
  1081. X        if (!up(&newep->focus)) {
  1082. X            Assert(!up(&newep->focus));
  1083. X            break;
  1084. X        }
  1085. X        --oldpl;
  1086. X        if (!up(&oldep->focus)) Abort();
  1087. X        --newpl;
  1088. X    }
  1089. X    if (intraline)
  1090. X        return atlinestart(oldep);
  1091. X    w = nodewidth(tree(oldep->focus));
  1092. X    return w < 0 ? -w : 0;
  1093. X}
  1094. X
  1095. X
  1096. X/*
  1097. X * Initialization code.
  1098. X */
  1099. XVisible Procedure
  1100. Xinitterm()
  1101. X{
  1102. X    initvtrm(); /* init virtual terminal package */
  1103. X    initgetc(); /* term-init string */
  1104. X}
  1105. X
  1106. X
  1107. XVisible bool in_vtrm= No;
  1108. Xextern bool in_init;
  1109. X
  1110. XHidden Procedure
  1111. Xinitvtrm() 
  1112. X{
  1113. X    int flags = 0;
  1114. X    int err;
  1115. X    
  1116. X    err= trmstart(&winheight, &llength, &flags);
  1117. X    if (err != TE_OK) {
  1118. X        if (err <= TE_DUMB)
  1119. X            putmess(errfile,
  1120. X         MESS(6600, "*** Bad $TERM or termcap, or dumb terminal\n"));
  1121. X        else if (err == TE_BADSCREEN)
  1122. X            putmess(errfile,
  1123. X         MESS(6601, "*** Bad SCREEN environment\n"));
  1124. X        else
  1125. X            putmess(errfile,
  1126. X         MESS(6602, "*** Cannot reach keyboard or screen\n"));
  1127. X
  1128. X        if (in_init)
  1129. X            immexit(2);
  1130. X        else
  1131. X            bye(2);
  1132. X    }
  1133. X    noscroll = (flags&CAN_SCROLL) == 0;
  1134. X    nosense= (flags&CAN_SENSE) == 0;
  1135. X#ifndef macintosh
  1136. X    raw_newline= Yes;
  1137. X    /* should be:
  1138. X     *     raw_newline= (flags&RAW_NEWLINE) != 0;
  1139. X     * with change in trm-module interface;
  1140. X     * RAW_NEWLINE means the cursor only goes down vertically on '\n'
  1141. X     */
  1142. X#endif
  1143. X
  1144. X    winstart = --winheight;
  1145. X
  1146. X    in_vtrm= Yes;
  1147. X}
  1148. X
  1149. XVisible Procedure
  1150. Xendterm()
  1151. X{
  1152. X    trmsync(winheight, 0);    /* needed for buggy vt100's, that
  1153. X                 * may leave cusor at top of screen
  1154. X                 * if only trmstart was called
  1155. X                 * (which did send cs_str)
  1156. X                 */
  1157. X    endgetc(); /* term-end string */
  1158. X    trmend();
  1159. X    in_vtrm= No;
  1160. X}
  1161. X
  1162. X/*
  1163. X * Routine to move the cursor to the first line after the just edited
  1164. X * document.  (Called after each editing action.)
  1165. X */
  1166. X
  1167. XVisible Procedure
  1168. Xendshow()
  1169. X{
  1170. X    register cell *p;
  1171. X    register int last = winheight;
  1172. X
  1173. X    for (p = tops; p; p = p->c_link) {
  1174. X        if (p->c_onscreen != Nowhere)
  1175. X            last = p->c_onscreen + Oldspace(p);
  1176. X    }
  1177. X    if (last > winheight)
  1178. X        last = winheight;
  1179. X    discard(tops);
  1180. X    tops = Cnil;
  1181. X    trmputdata(last, winheight, 0, "");
  1182. X    trmsync(winheight, 0);
  1183. X}
  1184. X
  1185. X#ifdef GOTOCURSOR
  1186. X
  1187. X/*
  1188. X * Translate a cursor position in tree coordinates.
  1189. X *
  1190. X * ***** DOESN'T WORK IF SCREEN INDENT DIFFERS FROM TREE INDENT! *****
  1191. X * (I.e. for lines with >= 80 spaces indentation)
  1192. X */
  1193. X
  1194. XVisible bool
  1195. Xbacktranslate(py, px)
  1196. X    int *py;
  1197. X    int *px;
  1198. X{
  1199. X    cell *p;
  1200. X    int y = *py;
  1201. X    int x = *px;
  1202. X    int i;
  1203. X
  1204. X    for (i = 0, p = tops; p; ++i, p = p->c_link) {
  1205. X        if (p->c_onscreen != Nowhere
  1206. X            && y >= p->c_onscreen && y < p->c_onscreen + Space(p)) {
  1207. X            *px += (y - p->c_onscreen) * llength - indent;
  1208. X            if (*px < 0)
  1209. X                *px = 0;
  1210. X            *py = i;
  1211. X            if (p->c_oldvhole && (y > focy || y == focy && x > focx))
  1212. X                --*px; /* Correction if beyond Vhole on same logical line */
  1213. X            return Yes;
  1214. X        }
  1215. X    }
  1216. X    ederr(GOTO_OUT);
  1217. X    return No;
  1218. X}
  1219. X
  1220. X#endif /*GOTOCURSOR*/
  1221. X/*
  1222. X * Set the indent level and window start line.
  1223. X */
  1224. X
  1225. XVisible Procedure
  1226. Xsetindent(x)
  1227. X    int x;
  1228. X{
  1229. X    winstart= winheight;
  1230. X    /* the following is a hack; should change when
  1231. X     * interpreter also writes through trm-interface.
  1232. X     * Then it must be clear what's on the screen already
  1233. X     * Handled in this file?
  1234. X     */
  1235. X    if (llength==0)
  1236. X        indent= x;
  1237. X    else
  1238. X        indent= x % llength;
  1239. X}
  1240. X
  1241. X
  1242. X/*
  1243. X * Show the command prompt.
  1244. X */
  1245. X
  1246. XVisible Procedure cmdprompt(prompt)
  1247. X    string prompt;
  1248. X{
  1249. X    setindent(strlen(prompt));
  1250. X    trmputdata(winstart, winstart, 0, prompt);
  1251. X}
  1252. END_OF_FILE
  1253.   if test 11204 -ne `wc -c <'abc/bed/e1scrn.c'`; then
  1254.     echo shar: \"'abc/bed/e1scrn.c'\" unpacked with wrong size!
  1255.   fi
  1256.   # end of 'abc/bed/e1scrn.c'
  1257. fi
  1258. if test -f 'abc/bint1/i1nua.c' -a "${1}" != "-c" ; then 
  1259.   echo shar: Will not clobber existing file \"'abc/bint1/i1nua.c'\"
  1260. else
  1261.   echo shar: Extracting \"'abc/bint1/i1nua.c'\" \(10983 characters\)
  1262.   sed "s/^X//" >'abc/bint1/i1nua.c' <<'END_OF_FILE'
  1263. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  1264. X
  1265. X/* Approximate arithmetic */
  1266. X
  1267. X#include "b.h"
  1268. X#include "feat.h"     /* for EXT_RANGE */
  1269. X#include "bobj.h"
  1270. X#include "i0err.h"
  1271. X#include "i1num.h"
  1272. X
  1273. X/*
  1274. XFor various reasons, on some machines (notably the VAX), the range
  1275. Xof the exponent is too small (ca. 1.7E38), and we cope with this by
  1276. Xadding a second word which holds the exponent.
  1277. XHowever, on other machines (notably the IBM PC), the range is sufficient
  1278. X(ca. 1E300), and here we try to save as much code as possible by not
  1279. Xdoing our own exponent handling.  (To be fair, we also don't check
  1280. Xcertain error conditions, to save more code.)
  1281. XThe difference is made by #defining EXT_RANGE (in i1num.h), meaning we
  1282. Xhave to EXTend the RANGE of the exponent.
  1283. X*/
  1284. X
  1285. X#ifdef EXT_RANGE
  1286. XHidden struct real app_0_buf = {Num, 1, -1, FILLER  0.0, -BIG};
  1287. X    /* Exponent must be less than any realistic exponent! */
  1288. X#else /* !EXT_RANGE */
  1289. XHidden struct real app_0_buf = {Num, 1, -1, FILLER  0.0};
  1290. X#endif /* !EXT_RANGE */
  1291. X
  1292. XVisible real app_0 = &app_0_buf;
  1293. X
  1294. XHidden double logtwo;
  1295. XHidden double twologBASE;
  1296. X
  1297. X/*
  1298. X * Build an approximate number.
  1299. X */
  1300. X
  1301. X#define TOO_LARGE MESS(700, "approximate number too large")
  1302. X
  1303. XVisible real mk_approx(frac, expo) double frac, expo; {
  1304. X    real u;
  1305. X#ifdef EXT_RANGE
  1306. X    expint v;
  1307. X    if (frac != 0) frac = frexp(frac, &v), expo += v;
  1308. X    if (frac == 0 || expo < -BIG) return (real) Copy(app_0);
  1309. X    if (expo > BIG) {
  1310. X        interr(TOO_LARGE);
  1311. X        expo = BIG;
  1312. X    }
  1313. X#else /* !EXT_RANGE */
  1314. X    if (frac == 0.0) return (real) Copy(app_0);
  1315. X    if (frac > 0 && log(frac)+expo*logtwo > log(Maxreal)) {
  1316. X        interr(TOO_LARGE);
  1317. X        frac= Maxreal;
  1318. X    }
  1319. X    else
  1320. X        frac= ldexp(frac, (int)expo);
  1321. X#endif /* EXT_RANGE */
  1322. X    u = (real) grab_num(-1);
  1323. X    Frac(u) = frac;
  1324. X#ifdef EXT_RANGE
  1325. X    Expo(u) = expo;
  1326. X#endif /* EXT_RANGE */
  1327. X    return u;
  1328. X}
  1329. X
  1330. XHidden value twotodblbits; /* 2**DBLBITS */
  1331. XHidden value twoto_dblbitsmin1; /* 2**(DBLBITS-1) */
  1332. X    /* stored as an unnormalized rational */
  1333. X    
  1334. XHidden double getexponent(v) value v; {
  1335. X    integer p, q;
  1336. X    struct integer pp, qq;
  1337. X    double x;
  1338. X
  1339. X    v = absval(v);
  1340. X    if (Integral(v)) {
  1341. X        p = (integer) v;
  1342. X        q = (integer) one;
  1343. X    }
  1344. X    else {
  1345. X        p = Numerator((rational) v);
  1346. X        q = Denominator((rational) v);
  1347. X    }
  1348. X    FreezeSmallInt(p, pp); FreezeSmallInt(q, qq);
  1349. X
  1350. X    x = log((double) Msd(p)) / logtwo;
  1351. X    x-= log((double) Msd(q)) / logtwo;
  1352. X    x+= (double) ((Length(p)-Length(q)) * twologBASE);
  1353. X
  1354. X    release(v);
  1355. X    return floor(x) + 1;
  1356. X}
  1357. X
  1358. XVisible value app_frexp(v) value v; {
  1359. X    integer w;
  1360. X    struct integer ww;
  1361. X    value s, t;
  1362. X    double frac, expo;
  1363. X    relation neg;
  1364. X    int i;
  1365. X
  1366. X    if ((neg = numcomp(v, zero)) == 0)
  1367. X        return Copy(app_0);
  1368. X    else if (neg < 0)
  1369. X        v = negated(v);
  1370. X
  1371. X    expo = getexponent(v); /* it can be +1 or -1 off !!! */
  1372. X
  1373. X    s = (value) mk_int((double)DBLBITS - expo);
  1374. X    s = prod2n(v, t = s, No);
  1375. X    release(t);
  1376. X    /* do the correction */
  1377. X    if (numcomp(s, twotodblbits) >= 0) {
  1378. X        s = prod2n(t = s, (value) int_min1, No); /* s / 2 */
  1379. X        ++expo;
  1380. X        release(t);
  1381. X    }
  1382. X    else if (numcomp(s, twoto_dblbitsmin1) < 0) {
  1383. X        s = prod2n(t = s, (value) int_1, No); /* s * 2 */
  1384. X        --expo;
  1385. X        release(t);
  1386. X    }
  1387. X    w = (integer) round1(s);
  1388. X    release(s);
  1389. X    FreezeSmallInt(w, ww);
  1390. X
  1391. X    frac = 0.0;
  1392. X    for (i = Length(w) - 1; i >= 0; --i) {
  1393. X        frac = frac * BASE + Digit(w, i);
  1394. X    }
  1395. X    frac = ldexp(frac, -DBLBITS);
  1396. X
  1397. X    release((value) w);
  1398. X    if (neg < 0) {
  1399. X        frac = -frac;
  1400. X        release(v);
  1401. X    }
  1402. X    return (value) mk_approx(frac, expo);
  1403. X}
  1404. X
  1405. X/*
  1406. X * Approximate arithmetic.
  1407. X */
  1408. X
  1409. XVisible real app_sum(u, v) real u, v; {
  1410. X#ifdef EXT_RANGE
  1411. X    real w;
  1412. X    if (Expo(u) < Expo(v)) w = u, u = v, v = w;
  1413. X    if (Expo(v) - Expo(u) < Minexpo) return (real) Copy(u);
  1414. X    return mk_approx(Frac(u) + ldexp(Frac(v), (int)(Expo(v) - Expo(u))),
  1415. X        Expo(u));
  1416. X#else /* !EXT_RANGE */
  1417. X    return mk_approx(Frac(u) + Frac(v), 0.0);
  1418. X#endif /* !EXT_RANGE */
  1419. X}
  1420. X
  1421. XVisible real app_diff(u, v) real u, v; {
  1422. X#ifdef EXT_RANGE
  1423. X    real w;
  1424. X    int sign = 1;
  1425. X    if (Expo(u) < Expo(v)) w = u, u = v, v = w, sign = -1;
  1426. X    if (Expo(v) - Expo(u) < Minexpo)
  1427. X        return sign < 0 ? app_neg(u) : (real) Copy(u);
  1428. X    return mk_approx(
  1429. X        sign * (Frac(u) - ldexp(Frac(v), (int)(Expo(v) - Expo(u)))),
  1430. X        Expo(u));
  1431. X#else /* !EXT_RANGE */
  1432. X    return mk_approx(Frac(u) - Frac(v), 0.0);
  1433. X#endif /* !EXT_RANGE */
  1434. X}
  1435. X
  1436. XVisible real app_neg(u) real u; {
  1437. X    return mk_approx(-Frac(u), Expo(u));
  1438. X}
  1439. X
  1440. XVisible real app_prod(u, v) real u, v; {
  1441. X    return mk_approx(Frac(u) * Frac(v), Expo(u) + Expo(v));
  1442. X}
  1443. X
  1444. XVisible real app_quot(u, v) real u, v; {
  1445. X    if (Frac(v) == 0.0) {
  1446. X        interr(ZERO_DIVIDE);
  1447. X        return (real) Copy(u);
  1448. X    }
  1449. X    return mk_approx(Frac(u) / Frac(v), Expo(u) - Expo(v));
  1450. X}
  1451. X
  1452. X/*
  1453. X    YIELD log"(frac, expo):
  1454. X        CHECK frac > 0
  1455. X        RETURN normalize"(expo*logtwo + log(frac), 0)
  1456. X*/
  1457. X
  1458. XVisible real app_log(v) real v; {
  1459. X    double frac = Frac(v), expo = Expo(v);
  1460. X     return mk_approx(expo*logtwo + log(frac), 0.0);
  1461. X}
  1462. X
  1463. X/*
  1464. X    YIELD exp"(frac, expo):
  1465. X        IF expo < minexpo: RETURN zero"
  1466. X        WHILE expo < 0: PUT frac/2, expo+1 IN frac, expo
  1467. X        PUT exp frac IN f
  1468. X        PUT normalize"(f, 0) IN f, e
  1469. X        WHILE expo > 0:
  1470. X            PUT (f, e) prod" (f, e) IN f, e
  1471. X            PUT expo-1 IN expo
  1472. X        RETURN f, e
  1473. X*/
  1474. X
  1475. XVisible real app_exp(v) real v; {
  1476. X#ifdef EXT_RANGE
  1477. X    expint ei;
  1478. X    double frac = Frac(v), vexpo = Expo(v), new_expo;
  1479. X    static double canexp;
  1480. X    if (!canexp)
  1481. X        canexp = floor(log(log(Maxreal/2.718281828459045235360)+1.0)/logtwo);
  1482. X    if (vexpo <= canexp) {
  1483. X        if (vexpo < Minexpo) return mk_approx(1.0, 0.0);
  1484. X        frac = ldexp(frac, (int)vexpo);
  1485. X        vexpo = 0;
  1486. X    }
  1487. X    else if (vexpo >= Maxexpo) {
  1488. X        /* Definitely too big (the real boundary is much smaller
  1489. X           but here we are in danger of overflowing new_expo
  1490. X           in the loop below) */
  1491. X        if (frac < 0)
  1492. X            return (real) Copy(app_0);
  1493. X        return mk_approx(1.0, Maxreal); /* Force an error! */
  1494. X    }
  1495. X    else {
  1496. X        frac = ldexp(frac, (int)canexp);
  1497. X        vexpo -= canexp;
  1498. X    }
  1499. X    frac = exp(frac);
  1500. X    new_expo = 0;
  1501. X    while (vexpo > 0 && frac != 0) {
  1502. X        frac = frexp(frac, &ei);
  1503. X        new_expo += ei;
  1504. X        frac *= frac;
  1505. X        new_expo += new_expo;
  1506. X        --vexpo;
  1507. X    }
  1508. X    return mk_approx(frac, new_expo);
  1509. X#else /* !EXT_RANGE */
  1510. X    if (Frac(v) > (Maxexpo)*logtwo)
  1511. X        return mk_approx(1.0, Maxreal); 
  1512. X        /* Force error! 
  1513. X         * (since BSD exp generates illegal instr) 
  1514. X         * [still ~2**126 ain't save against their failing exp] */
  1515. X    return mk_approx(exp(Frac(v)), 0.0);
  1516. X#endif /* !EXT_RANGE */
  1517. X}
  1518. X
  1519. XVisible real app_power(u, v) real u, v; {
  1520. X    double ufrac = Frac(u);
  1521. X    if (ufrac <= 0) {
  1522. X        if (ufrac < 0) interr(NEG_EXACT);
  1523. X        if (v == app_0) return mk_approx(1.0, 0.0); /* 0**0 = 1 */
  1524. X        return (real) Copy(app_0); /* 0**x = 0 */
  1525. X    }
  1526. X    else {
  1527. X        /* u ** v = exp(v * log (u)) */
  1528. X        real logu= app_log(u);
  1529. X        real vlogu= app_prod(v, logu);
  1530. X        real expvlogu= app_exp(vlogu);
  1531. X        Release(logu);
  1532. X        Release(vlogu);
  1533. X        return expvlogu;
  1534. X    }
  1535. X}
  1536. X
  1537. X/* about2_to_integral(ru, v, rv) returns, via rv, exactly (0.5, v+1)
  1538. X * if ru == ~2 and v is an integral. Why?, well,
  1539. X * to speed up reading the value of an approximate from a file,
  1540. X * the exponent part is stored as ~2**expo and
  1541. X * to prevent loss of precision, we cannot use the normal procedure
  1542. X * app_power().
  1543. X */
  1544. X
  1545. XVisible bool about2_to_integral(ru, v, rv) value v; real ru, *rv; {
  1546. X    double expo;
  1547. X    integer w;
  1548. X    struct integer ww;
  1549. X    int i;
  1550. X    bool neg = No;
  1551. X
  1552. X#ifdef EXT_RANGE
  1553. X    if (!(Frac(ru) == 0.5 && Expo(ru) == 2.0 && Integral(v)))
  1554. X        return No;
  1555. X#else
  1556. X    if (!(Frac(ru) == 2.0 && Integral(v)))
  1557. X        return No;
  1558. X#endif
  1559. X    w = (integer) v;
  1560. X    if (numcomp((value) w, zero) < 0) {
  1561. X        w = int_neg(w);
  1562. X        neg = Yes;
  1563. X    }
  1564. X    FreezeSmallInt(w, ww);
  1565. X    
  1566. X    expo = 0.0;
  1567. X    for (i = Length(w) - 1; i >= 0; --i) {
  1568. X        expo = expo * BASE + Digit(w, i);
  1569. X    }
  1570. X    if (neg) {
  1571. X        expo = -expo;
  1572. X        Release(w);
  1573. X    }
  1574. X    *rv = mk_approx(0.5, expo+1);
  1575. X    return Yes;
  1576. X}
  1577. X
  1578. XVisible int app_comp(u, v) real u, v; {
  1579. X    double xu, xv;
  1580. X#ifdef EXT_RANGE
  1581. X    double eu, ev;
  1582. X#endif /* EXT_RANGE */
  1583. X    if (u == v) return 0;
  1584. X    xu = Frac(u), xv = Frac(v);
  1585. X#ifdef EXT_RANGE
  1586. X    if (xu*xv > 0) {
  1587. X        eu = Expo(u), ev = Expo(v);
  1588. X        if (eu < ev) return xu < 0 ? 1 : -1;
  1589. X        if (eu > ev) return xu < 0 ? -1 : 1;
  1590. X    }
  1591. X#endif /* EXT_RANGE */
  1592. X    if (xu < xv) return -1;
  1593. X    if (xu > xv) return 1;
  1594. X    return 0;
  1595. X}
  1596. X
  1597. XVisible integer app_floor(u) real u; {
  1598. X    double frac, expo;
  1599. X    expint ei;
  1600. X    integer v, w;
  1601. X    value twotow, result;
  1602. X    
  1603. X    frac= Frac(u);
  1604. X    expo= Expo(u);
  1605. X    frac= frexp(frac, &ei);
  1606. X    expo+= ei;
  1607. X
  1608. X    if (expo <= DBLBITS) {
  1609. X        return     mk_int(floor(ldexp(frac,
  1610. X                (int)(expo < 0 ? -1 : expo))));
  1611. X    }
  1612. X    v = mk_int(ldexp(frac, DBLBITS));
  1613. X    w = mk_int(expo - DBLBITS);
  1614. X    twotow = power((value)int_2, (value)w);
  1615. X    result = prod((value)v, twotow);
  1616. X    Release(v), Release(w), Release(twotow);
  1617. X    if (!Integral(result)) 
  1618. X        syserr(MESS(701, "app_floor: result not integral"));
  1619. X    return (integer) result;
  1620. X}
  1621. X
  1622. XHidden value twotolongbits;
  1623. X
  1624. XVisible value app_exactly(u) real u; {
  1625. X    value w;
  1626. X    integer v, n, t1, t2;
  1627. X    double frac, expo, rest, p;
  1628. X    unsigned long l;
  1629. X    expint e, re, dummy;
  1630. X    int z, digits;
  1631. X    bool neg;
  1632. X    
  1633. X    if (Frac(u) == 0.0)
  1634. X        return zero;
  1635. X    frac= Frac(u);
  1636. X    expo= Expo(u);
  1637. X    if (frac < 0.0) { frac= -frac; neg= Yes; }
  1638. X    else neg= No;
  1639. X    frac= frexp(frac, &e);
  1640. X    expo+= e;
  1641. X    p= floor(ldexp(frac, LONGBITS));    /* shift the digits */
  1642. X    l= (unsigned long) p;
  1643. X    v= mk_int((double) l);
  1644. X    rest= frexp(frac - frexp(p, &dummy), &re);
  1645. X    z= -re - LONGBITS;        /* number of leading zeros */
  1646. X    digits= LONGBITS;        /* count the number of digits */
  1647. X
  1648. X    while (rest != 0.0) {
  1649. X        p= floor(ldexp(rest, LONGBITS - z));
  1650. X        l= (unsigned long) p;
  1651. X        v= int_prod(t1= v, (integer) twotolongbits);
  1652. X        Release(t1);
  1653. X        v= int_sum(t1= v, t2= mk_int((double) l));
  1654. X        Release(t1); Release(t2);
  1655. X        rest= frexp(rest - frexp(p, &dummy), &re);
  1656. X        z= z - re - LONGBITS;
  1657. X        digits+= LONGBITS;
  1658. X    }
  1659. X    if (neg) {
  1660. X        v= int_neg(t1= v);
  1661. X        Release(t1);
  1662. X    }
  1663. X    n= mk_int(expo - (double) digits);
  1664. X    w= prod2n((value) v, (value) n, Yes);
  1665. X    Release(v); Release(n);
  1666. X
  1667. X    return w;
  1668. X}
  1669. X
  1670. X/*
  1671. X * app_print(f, v) writes an approximate v on file f in such a way that it
  1672. X * can be read back identically, assuming integral powers of ~2 can be
  1673. X * computed exactly. To ensure this we have incorporated a test in the
  1674. X * routine power().
  1675. X */
  1676. X
  1677. XVisible Procedure app_print(fp, v) FILE *fp; real v; {
  1678. X    double frac= Frac(v);
  1679. X    double expo= Expo(v);
  1680. X    expint ei;
  1681. X    integer w;
  1682. X    string str;
  1683. X    
  1684. X    frac = frexp(frac, &ei);
  1685. X    expo += ei;
  1686. X
  1687. X    if (frac == 0.0) {
  1688. X        fputs("~0", fp);
  1689. X        return;
  1690. X    }
  1691. X    if (frac < 0) {
  1692. X        frac = -frac;
  1693. X        putc('-', fp);
  1694. X    }
  1695. X    if (frac == 0.5)
  1696. X        fprintf(fp, "~2**%.0lf", expo-1);
  1697. X    else {
  1698. X        w = mk_int(ldexp(frac, DBLBITS));
  1699. X        expo -= DBLBITS;
  1700. X        str = convnum((value) w);
  1701. X        fprintf(fp, "%s*~2**%.0lf", str, expo);
  1702. X        Release(w);
  1703. X    }
  1704. X}
  1705. X
  1706. XHidden Procedure initlog() {
  1707. X    double logBASE, invlogtwo;
  1708. X
  1709. X    logtwo= log(2.0);
  1710. X
  1711. X    logBASE= log(10.0) * tenlogBASE;
  1712. X    invlogtwo= 1.0 / logtwo;
  1713. X    twologBASE= logBASE * invlogtwo;
  1714. X}
  1715. X
  1716. XVisible Procedure initapp() {
  1717. X    value v;
  1718. X    rational r;
  1719. X
  1720. X    initlog();
  1721. X
  1722. X    twotolongbits= (value) mk_int((double) TWOTO_LONGBITS);
  1723. X
  1724. X    v = (value) mk_int((double) TWOTO_DBLBITSMIN1);
  1725. X    twotodblbits= prod(v, (value) int_2);
  1726. X    release(v);
  1727. X
  1728. X    /* to save space, twoto_dblbitsmin1 is stored as 
  1729. X     * an unnormalized rational.
  1730. X     */
  1731. X    r = (rational) grab_rat(0);
  1732. X    Numerator(r) = (integer) copy(twotodblbits);
  1733. X    Denominator(r) = int_2;
  1734. X    twoto_dblbitsmin1= (value) r;
  1735. X}
  1736. X
  1737. XVisible Procedure endapp() {
  1738. X    release(twoto_dblbitsmin1);
  1739. X    release(twotodblbits);
  1740. X    release(twotolongbits);
  1741. X}
  1742. END_OF_FILE
  1743.   if test 10983 -ne `wc -c <'abc/bint1/i1nua.c'`; then
  1744.     echo shar: \"'abc/bint1/i1nua.c'\" unpacked with wrong size!
  1745.   fi
  1746.   # end of 'abc/bint1/i1nua.c'
  1747. fi
  1748. if test -f 'abc/btr/i1obj.c' -a "${1}" != "-c" ; then 
  1749.   echo shar: Will not clobber existing file \"'abc/btr/i1obj.c'\"
  1750. else
  1751.   echo shar: Extracting \"'abc/btr/i1obj.c'\" \(5814 characters\)
  1752.   sed "s/^X//" >'abc/btr/i1obj.c' <<'END_OF_FILE'
  1753. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  1754. X
  1755. X/* Generic routines for all values */
  1756. X
  1757. X#include "b.h"
  1758. X#include "bmem.h"
  1759. X#include "bobj.h"
  1760. X#include "i1btr.h"
  1761. X#include "i1tlt.h"
  1762. X#include "i3typ.h"
  1763. X
  1764. XVisible unsigned tltsyze(type, len, nptrs)
  1765. X    literal type; intlet len; int *nptrs;
  1766. X{
  1767. X    *nptrs= 1;
  1768. X    return (unsigned) (sizeof(value));
  1769. X}
  1770. X
  1771. XVisible Procedure rel_subvalues(v) value v; {
  1772. X    if (Is_tlt(v)) {
  1773. X        relbtree(Root(v), Itemtype(v));
  1774. X        v->type= '\0';
  1775. X        freemem((ptr) v);
  1776. X    }
  1777. X    else rrelease(v);
  1778. X}
  1779. X
  1780. X#define INCOMP    MESS(500, "incompatible types %s and %s")
  1781. X
  1782. XHidden Procedure incompatible(v, w) value v, w; {
  1783. X    value m1, m2, m3, m;
  1784. X    string s1, s2;
  1785. X    
  1786. X    m1= convert(m3= (value) valtype(v), No, No); release(m3);
  1787. X    m2= convert(m3= (value) valtype(w), No, No); release(m3);
  1788. X    s1= sstrval(m1);
  1789. X    s2= sstrval(m2);
  1790. X    sprintf(messbuf, getmess(INCOMP), s1, s2);
  1791. X    m= mk_text(messbuf);
  1792. X    interrV(-1, m);
  1793. X
  1794. X    fstrval(s1); fstrval(s2);
  1795. X    release(m1); release(m2);
  1796. X    release(m);
  1797. X}
  1798. X
  1799. XVisible bool comp_ok = Yes;         /* Temporary, to catch type errors */
  1800. X
  1801. Xrelation comp_tlt(), comp_text();    /* From b1lta.c */
  1802. X
  1803. XVisible relation compare(v, w) value v, w; {
  1804. X    literal vt, wt;
  1805. X    int i;
  1806. X    relation rel;
  1807. X    
  1808. X    comp_ok = Yes;
  1809. X
  1810. X    if (v EQ w) return(0);
  1811. X    if (IsSmallInt(v) && IsSmallInt(w))
  1812. X        return SmallIntVal(v) - SmallIntVal(w);
  1813. X    vt = Type(v);
  1814. X    wt = Type(w);
  1815. X    switch (vt) {
  1816. X    case Num:
  1817. X        if (wt != Num) {
  1818. X incomp:
  1819. X            /*Temporary until static checks are implemented*/
  1820. X             incompatible(v, w);
  1821. X            comp_ok= No;
  1822. X            return -1;
  1823. X         }
  1824. X        return(numcomp(v, w));
  1825. X    case Com:
  1826. X        if (wt != Com || Nfields(v) != Nfields(w)) goto incomp;
  1827. X        for (i = 0; i < Nfields(v); i++) {
  1828. X            rel = compare(*Field(v, i), *Field(w, i));
  1829. X            if (rel NE 0) return(rel);
  1830. X        }
  1831. X        return(0);
  1832. X    case Tex:
  1833. X        if (wt != Tex) goto incomp;
  1834. X        return(comp_text(v, w));
  1835. X    case Lis:
  1836. X        if (wt != Lis && wt != ELT) goto incomp;
  1837. X        return(comp_tlt(v, w));
  1838. X    case Tab:
  1839. X        if (wt != Tab && wt != ELT) goto incomp;
  1840. X        return(comp_tlt(v, w));
  1841. X    case ELT:
  1842. X        if (wt != Tab && wt != Lis && wt != ELT) goto incomp;
  1843. X        return(Root(w) EQ Bnil ? 0 : -1);
  1844. X    default: 
  1845. X        syserr(MESS(501, "comparison of unknown types"));
  1846. X        /*NOTREACHED*/
  1847. X    }
  1848. X}
  1849. X
  1850. X/* Used for set'random. Needs to be rewritten so that for small changes in v */
  1851. X/* you get large changes in hash(v) */
  1852. X
  1853. XVisible double hash(v) value v; {
  1854. X    if (Is_number(v)) return numhash(v);
  1855. X    else if (Is_compound(v)) {
  1856. X        int len= Nfields(v), k; double d= .404*len;
  1857. X        k_Overfields {
  1858. X            d= .874*d+.310*hash(*Field(v, k));
  1859. X        }
  1860. X        return d;
  1861. X    } else {
  1862. X        int len= length(v), k; double d= .404*len;
  1863. X        if (len == 0) return .909;
  1864. X        else if (Is_text(v)) {
  1865. X            value ch;
  1866. X            for (k= 0; k<len; ++k) {
  1867. X                ch= thof(k+1, v);
  1868. X                d= .987*d+.277*charval(ch);
  1869. X                release(ch);
  1870. X            }
  1871. X            return d;
  1872. X        } else if (Is_list(v)) {
  1873. X            value el;
  1874. X            for (k= 0; k<len; ++k) {
  1875. X                d= .874*d+.310*hash(el= thof(k+1, v));
  1876. X                release(el);
  1877. X            }
  1878. X            return d;
  1879. X        } else if (Is_table(v)) {
  1880. X            for (k= 0; k<len; ++k) {
  1881. X                d= .874*d+.310*hash(*key(v, k))
  1882. X                     +.123*hash(*assoc(v, k));
  1883. X            }
  1884. X            return d;
  1885. X        } else {
  1886. X            syserr(MESS(502, "hash called with unknown type"));
  1887. X            return (double) 0; /* (double)NULL crashes atari MWC */
  1888. X        }
  1889. X    }
  1890. X}
  1891. X
  1892. XVisible value convert(v, coll, outer) value v; bool coll, outer; {
  1893. X    value t, quote, c, cv, sep, th, open, close; int k, len; char ch;
  1894. X    switch (Type(v)) {
  1895. X    case Num:
  1896. X        return mk_text(convnum(v));
  1897. X    case Tex:
  1898. X        if (outer) return copy(v);
  1899. X        quote= mk_text("\"");
  1900. X        len= length(v);
  1901. X        t= copy(quote);
  1902. X        for (k=1; k<=len; k++) {
  1903. X            c= thof(k, v);
  1904. X            ch= charval(c);
  1905. X            concato(&t, c);
  1906. X            if (ch == '"' || ch == '`') concato(&t, c);
  1907. X            release(c);
  1908. X        }
  1909. X        concato(&t, quote);
  1910. X        release(quote);
  1911. X        break;
  1912. X    case Com:
  1913. X        len= Nfields(v);
  1914. X        outer&= coll;
  1915. X        sep= mk_text(outer ? " " : ", ");
  1916. X        t= mk_text(coll ? "" : "(");
  1917. X        for (k= 0; k<len; ++k) {
  1918. X            concato(&t, cv= convert(*Field(v, k), No, outer));
  1919. X            release(cv);
  1920. X            if (k < len - 1) concato(&t, sep);
  1921. X        }
  1922. X        release(sep);
  1923. X        if (!coll) {
  1924. X            concato(&t, cv= mk_text(")"));
  1925. X            release(cv);
  1926. X        }
  1927. X        break;
  1928. X    case Lis:
  1929. X    case ELT:
  1930. X        len= length(v);
  1931. X        t= mk_text("{");
  1932. X        sep= mk_text("; ");
  1933. X        for (k=1; k<=len; k++) {
  1934. X            concato(&t, cv= convert(th= thof(k, v), No, No));
  1935. X            release(cv); release(th);
  1936. X            if (k != len) concato(&t, sep);
  1937. X        }
  1938. X        release(sep);
  1939. X        concato(&t, cv= mk_text("}"));
  1940. X        release(cv);
  1941. X        break;
  1942. X    case Tab:
  1943. X        len= length(v);
  1944. X        open= mk_text("[");
  1945. X        close= mk_text("]: ");
  1946. X        sep= mk_text("; ");
  1947. X        t= mk_text("{");
  1948. X        for (k= 0; k<len; ++k) {
  1949. X            concato(&t, open);
  1950. X            concato(&t, cv= convert(*key(v, k), Yes, No));
  1951. X            release(cv);
  1952. X            concato(&t, close);
  1953. X            concato(&t, cv= convert(*assoc(v, k), No, No));
  1954. X            release(cv);
  1955. X            if (k < len - 1) concato(&t, sep);
  1956. X        }
  1957. X        concato(&t, cv= mk_text("}")); release(cv);
  1958. X        release(open); release(close); release(sep);
  1959. X        break;
  1960. X    default:
  1961. X        if (testing) {
  1962. X            t= mk_text("?");
  1963. X            concato(&t, cv= mkchar(Type(v))); release(cv);
  1964. X            concato(&t, cv= mkchar('$')); release(cv);
  1965. X            break;
  1966. X        }
  1967. X        syserr(MESS(503, "unknown type in convert"));
  1968. X    }
  1969. X    return t;
  1970. X}
  1971. X
  1972. XHidden value adj(v, w, side) value v, w; char side; {
  1973. X    value t, c, sp, r, i;
  1974. X    int len, wid, diff, left, right;
  1975. X    c= convert(v, Yes, Yes);
  1976. X    len= length(c);
  1977. X    wid= intval(w);
  1978. X    if (wid<=len) return c;
  1979. X    else {
  1980. X        diff= wid-len;
  1981. X        if (side == 'L') { left= 0; right= diff; }
  1982. X        else if (side == 'R') { left= diff; right= 0; }
  1983. X        else {left= diff/2; right= (diff+1)/2; }
  1984. X        sp= mk_text(" ");
  1985. X        if (left == 0) t= c;
  1986. X        else {
  1987. X            t= repeat(sp, i= mk_integer(left)); release(i);
  1988. X            concato(&t, c);
  1989. X            release(c);
  1990. X        }
  1991. X        if (right != 0) {
  1992. X            r= repeat(sp, i= mk_integer(right)); release(i);
  1993. X            concato(&t, r);
  1994. X            release(r);
  1995. X        }
  1996. X        release(sp);
  1997. X        return t;
  1998. X    }
  1999. X}
  2000. X
  2001. XVisible value adjleft(v, w) value v, w; {
  2002. X    return adj(v, w, 'L');
  2003. X}
  2004. X
  2005. XVisible value adjright(v, w) value v, w; {
  2006. X    return adj(v, w, 'R');
  2007. X}
  2008. X
  2009. XVisible value centre(v, w) value v, w; {
  2010. X    return adj(v, w, 'C');
  2011. X}
  2012. X
  2013. END_OF_FILE
  2014.   if test 5814 -ne `wc -c <'abc/btr/i1obj.c'`; then
  2015.     echo shar: \"'abc/btr/i1obj.c'\" unpacked with wrong size!
  2016.   fi
  2017.   # end of 'abc/btr/i1obj.c'
  2018. fi
  2019. if test -f 'abc/btr/i1tlt.c' -a "${1}" != "-c" ; then 
  2020.   echo shar: Will not clobber existing file \"'abc/btr/i1tlt.c'\"
  2021. else
  2022.   echo shar: Extracting \"'abc/btr/i1tlt.c'\" \(10941 characters\)
  2023.   sed "s/^X//" >'abc/btr/i1tlt.c' <<'END_OF_FILE'
  2024. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  2025. X
  2026. X/* generic routines for B texts, lists and tables */
  2027. X
  2028. X#include "b.h"
  2029. X#include "feat.h"
  2030. X#include "bobj.h"
  2031. X#include "i1btr.h"
  2032. X#include "i1tlt.h"
  2033. X
  2034. X#define SIZE_TLT    MESS(300, "in #t, t is not a text list or table")
  2035. X
  2036. X#define SIZE2_TLT    MESS(301, "in e#t, t is not a text list or table")
  2037. X#define SIZE2_CHAR    MESS(302, "in e#t, t is a text, but e is not a character")
  2038. X
  2039. X#define MIN_TLT        MESS(303, "in min t, t is not a text list or table")
  2040. X#define MIN_EMPTY    MESS(304, "in min t, t is empty")
  2041. X
  2042. X#define MAX_TLT        MESS(305, "in max t, t is not a text list or table")
  2043. X#define MAX_EMPTY    MESS(306, "in max t, t is empty")
  2044. X
  2045. X#define MIN2_TLT    MESS(307, "in e min t, t is not a text list or table")
  2046. X#define MIN2_EMPTY    MESS(308, "in e min t, t is empty")
  2047. X#define MIN2_CHAR    MESS(309, "in e min t, t is a text, but e is not a character")
  2048. X#define MIN2_ELEM    MESS(310, "in e min t, no element of t exceeds e")
  2049. X
  2050. X#define MAX2_TLT    MESS(311, "in e max t, t is not a text list or table")
  2051. X#define MAX2_EMPTY    MESS(312, "in e max t, t is empty")
  2052. X#define MAX2_CHAR    MESS(313, "in e max t, t is a text, but e is not a character")
  2053. X#define MAX2_ELEM    MESS(314, "in e max t, no element of t is less than e")
  2054. X
  2055. X#define ITEM_TLT    MESS(315, "in t item n, t is not a text list or table")
  2056. X#define ITEM_EMPTY    MESS(316, "in t item n, t is empty")
  2057. X#define ITEM_NUM    MESS(317, "in t item n, n is not a number")
  2058. X#define ITEM_INT    MESS(318, "in t item n, n is not an integer")
  2059. X#define ITEM_L_BND    MESS(319, "in t item n, n is < 1")
  2060. X#define ITEM_U_BND    MESS(320, "in t item n, n exceeds #t")
  2061. X
  2062. X#ifdef B_COMPAT
  2063. X
  2064. X#define THOF_TLT    MESS(321, "in n th'of t, t is not a text list or table")
  2065. X#define THOF_EMPTY    MESS(322, "in n th'of t, t is empty")
  2066. X#define THOF_NUM    MESS(323, "in n th'of t, n is not a number")
  2067. X#define THOF_INT    MESS(324, "in n th'of t, n is not an integer")
  2068. X#define THOF_L_BND    MESS(325, "in n th'of t, n is < 1")
  2069. X#define THOF_U_BND    MESS(326, "in n th'of t, n exceeds #t")
  2070. X
  2071. X#endif /* B_COMPAT */
  2072. X
  2073. X/* From b1lta.c */
  2074. Xint l2size();
  2075. Xvalue l2min(), l2max();
  2076. X
  2077. XVisible value mk_elt() { /* {}, internal only */
  2078. X    value e = grab(ELT, Lt);
  2079. X    Root(e) = Bnil;
  2080. X    return e;
  2081. X}
  2082. X
  2083. XVisible bool empty(v) value v; { /* #v=0, internal only */
  2084. X    switch (Type(v)) {
  2085. X    case ELT:
  2086. X    case Lis:
  2087. X    case Tex:
  2088. X    case Tab:
  2089. X        return Root(v) EQ Bnil;
  2090. X    default:
  2091. X        return No;
  2092. X        /* Some routines must test empty(t) end return an error
  2093. X           message if it fails, before testing Type(t).
  2094. X           In this way, they won't give the wrong error message. */
  2095. X    }
  2096. X}
  2097. X
  2098. X/* return size of (number of items in) dependent tree */
  2099. X
  2100. XHidden value treesize(pnode) btreeptr pnode; {
  2101. X    int psize;
  2102. X    value vsize, childsize, u;
  2103. X    intlet l;
  2104. X    psize = Size(pnode);
  2105. X    if (psize EQ Bigsize) {
  2106. X    switch (Flag(pnode)) {        
  2107. X    case Inner:
  2108. X        vsize = mk_integer((int) Lim(pnode));
  2109. X        for (l = 0; l <= Lim(pnode); l++) {
  2110. X        childsize = treesize(Ptr(pnode, l));
  2111. X        u = vsize;
  2112. X        vsize = sum(vsize, childsize);
  2113. X        release(u);
  2114. X        release(childsize);
  2115. X        }
  2116. X        break;
  2117. X    case Irange: 
  2118. X        u = diff(Upbval(pnode), Lwbval(pnode));
  2119. X        vsize = sum(u, one);
  2120. X        release(u);
  2121. X        break;
  2122. X    case Bottom: 
  2123. X    case Crange: 
  2124. X        syserr(MESS(327, "Bigsize in Bottom or Crange"));
  2125. X    }
  2126. X    return(vsize);
  2127. X    }
  2128. X    return mk_integer(psize);
  2129. X}
  2130. X
  2131. XVisible value size(t) value t; { /* #t */
  2132. X    int tsize;
  2133. X    switch (Type(t)) {
  2134. X    case ELT:
  2135. X    case Lis:
  2136. X    case Tex:
  2137. X    case Tab:
  2138. X        tsize = Tltsize(t);
  2139. X        if (tsize EQ Bigsize) return treesize(Root(t));
  2140. X        return mk_integer(tsize);
  2141. X    default:
  2142. X        reqerr(SIZE_TLT);
  2143. X        return zero;
  2144. X    }
  2145. X}
  2146. X
  2147. XVisible value item(v, num) value v, num; { /* v item num */
  2148. X    value m= Vnil;
  2149. X    if (!Is_tlt(v))
  2150. X        interr(ITEM_TLT);
  2151. X    else if (!Is_number(num))
  2152. X        interr(ITEM_NUM);
  2153. X    else if (empty(v))
  2154. X        interr(ITEM_EMPTY);
  2155. X    else if (numcomp(num, one) < 0)
  2156. X        interr(ITEM_L_BND);
  2157. X    else if (Tltsize(v) == Bigsize) {
  2158. X        /* only happens for big Iranges;
  2159. X         * the following code is only valid for flat ranges
  2160. X         */
  2161. X        value r;
  2162. X        r= treesize(Root(v));
  2163. X        if (compare(r, num) < 0)
  2164. X            interr(ITEM_U_BND);
  2165. X        else {
  2166. X            release(r);
  2167. X            r= sum(num, Lwbval(Root(v)));
  2168. X            m= diff(r, one);
  2169. X        }
  2170. X        release(r);
  2171. X    }        
  2172. X    else {
  2173. X        m= thof(intval(num), v);
  2174. X        if (m == Vnil && still_ok)
  2175. X            interr(ITEM_U_BND);
  2176. X    }
  2177. X    return m;
  2178. X}
  2179. X
  2180. X#ifdef B_COMPAT
  2181. X
  2182. XVisible value th_of(num, v) value num, v; { /* num th'of v */
  2183. X    value m= Vnil;
  2184. X    if (!Is_tlt(v))
  2185. X        interr(THOF_TLT);
  2186. X    else if (!Is_number(num))
  2187. X        interr(THOF_NUM);
  2188. X    else if (empty(v))
  2189. X        interr(THOF_EMPTY);
  2190. X    else if (numcomp(num, one) < 0)
  2191. X        interr(THOF_L_BND);
  2192. X    else if (Tltsize(v) == Bigsize) {
  2193. X        /* only happens for big Iranges;
  2194. X         * the following code is only valid for flat ranges
  2195. X         */
  2196. X        value r;
  2197. X        r= treesize(Root(v));
  2198. X        if (compare(r, num) < 0)
  2199. X            interr(ITEM_U_BND);
  2200. X        else {
  2201. X            release(r);
  2202. X            r= sum(num, Lwbval(Root(v)));
  2203. X            m= diff(r, one);
  2204. X        }
  2205. X        release(r);
  2206. X    }        
  2207. X    else {
  2208. X        m= thof(intval(num), v);
  2209. X        if (m == Vnil && still_ok)
  2210. X            interr(THOF_U_BND);
  2211. X    }
  2212. X    return m;
  2213. X}
  2214. X
  2215. X#endif /* B_COMPAT */
  2216. X
  2217. X/*
  2218. X * 'Walktree' handles functions on texts and associates of tables.
  2219. X * The actual function performed is determined by the 'visit' function.
  2220. X * The tree is walked (possibly recursively) and all items are visited.
  2221. X * The return value of walktree() and visit() is used to determine whether
  2222. X * the walk should continue (Yes == continue, No == stop now).
  2223. X * Global variables are used to communicate the result, and the parameters
  2224. X * of the function. The naming convention is according to "e func t".
  2225. X */
  2226. X
  2227. XHidden intlet tt;        /* type of walked value t */
  2228. XHidden intlet wt;        /* width of items in walked value t */
  2229. XHidden value ve;         /* value of e, if func is dyadic */
  2230. XHidden char ce;         /* C char in e, if t is a text */
  2231. X
  2232. XHidden int count;         /* result of size2 */
  2233. XHidden bool found;         /* result for in */
  2234. XHidden intlet m_char;         /* result for min/max on texts */
  2235. XHidden value m_val;        /* result for min/max on tables */
  2236. X
  2237. X#define Lowchar (-Maxintlet)    /* -infinity for characters */
  2238. X#define Highchar (Maxintlet)    /* +infinity */
  2239. X
  2240. XHidden bool walktree(p, visit) btreeptr p; bool (*visit)(); {
  2241. X    intlet l;
  2242. X    
  2243. X    if (p EQ Bnil) return Yes; /* i.e., not found (used by in() !) */
  2244. X    for (l=0; l < Lim(p); l++) {
  2245. X        switch (Flag(p)) {
  2246. X        case Inner:
  2247. X            if (!walktree(Ptr(p, l), visit) || !still_ok)
  2248. X                return No;
  2249. X            if (!(*visit)(Piitm(p, l, wt)) || !still_ok)
  2250. X                return No;
  2251. X            break;
  2252. X        case Bottom:
  2253. X            if (!(*visit)(Pbitm(p, l, wt)) || !still_ok)
  2254. X                return No;
  2255. X        }
  2256. X    }
  2257. X    return Flag(p) EQ Bottom || walktree(Ptr(p, l), visit);
  2258. X}
  2259. X
  2260. X/* Common code for min/max-1/2, size2, in. */
  2261. X
  2262. XHidden int tlterr;
  2263. X#define T_TLT 1
  2264. X#define T_EMPTY 2
  2265. X#define T_CHAR 3
  2266. X
  2267. XHidden int tlt_func(e, t, li_func, te_visit, ta_visit)
  2268. X    value e, t;             /* [e] func t */
  2269. X    value (*li_func)();         /* func for lists */
  2270. X    bool (*te_visit)(), (*ta_visit)(); /* 'visit' for walktree */
  2271. X{
  2272. X    m_val = Vnil;
  2273. X    if (empty(t)) {
  2274. X        tlterr= T_EMPTY;
  2275. X        return -1;
  2276. X    }
  2277. X    tt = Type(t);
  2278. X    switch (tt) {
  2279. X    case Lis:
  2280. X        m_val = (*li_func)(e, t);
  2281. X        break;
  2282. X    case Tex:
  2283. X        if (e NE Vnil) {
  2284. X            if (!Character(e)) {
  2285. X                tlterr= T_CHAR;
  2286. X                return -1;
  2287. X            }
  2288. X            ce = Bchar(Root(e), 0);
  2289. X        }
  2290. X        wt = Itemwidth(Itemtype(t));
  2291. X        found = !walktree(Root(t), te_visit);
  2292. X        if (m_char NE Lowchar && m_char NE Highchar)
  2293. X            m_val = mkchar(m_char);
  2294. X        break;
  2295. X    case Tab:
  2296. X        ve = e;
  2297. X        wt = Itemwidth(Itemtype(t));
  2298. X        found = !walktree(Root(t), ta_visit);
  2299. X        break;
  2300. X    default:
  2301. X        tlterr= T_TLT;
  2302. X        return -1;
  2303. X    }
  2304. X    return 0;
  2305. X}
  2306. X
  2307. XHidden value li2size(e, t) value e, t; {
  2308. X    count = l2size(e, t);
  2309. X    return Vnil;
  2310. X}
  2311. X
  2312. XHidden bool te2size(pitm) itemptr pitm; {
  2313. X    if (ce EQ Charval(pitm))
  2314. X        count++;
  2315. X    return Yes;
  2316. X}
  2317. X
  2318. XHidden bool ta2size(pitm) itemptr pitm; {
  2319. X    if (compare(ve, Ascval(pitm)) EQ 0)
  2320. X        count++;
  2321. X    return Yes;
  2322. X}
  2323. X
  2324. XVisible value size2(e, t) value e, t; { /* e#t */
  2325. X    m_char = Lowchar;
  2326. X    count = 0;
  2327. X    if (tlt_func(e, t, li2size, te2size, ta2size) == -1) {
  2328. X        switch (tlterr) {
  2329. X        case T_TLT: interr(SIZE2_TLT);
  2330. X        case T_EMPTY: return copy(zero);
  2331. X        case T_CHAR: interr(SIZE2_CHAR);
  2332. X        }
  2333. X    }
  2334. X    return mk_integer(count);
  2335. X}
  2336. X
  2337. XHidden value li_in(e, t) value e, t; {
  2338. X    found = in_keys(e, t);
  2339. X    return Vnil;
  2340. X}
  2341. X    
  2342. XHidden bool te_in(pitm) itemptr pitm; {
  2343. X    return Charval(pitm) NE ce;
  2344. X}
  2345. X
  2346. XHidden bool ta_in(pitm) itemptr pitm; {
  2347. X    return compare(ve, Ascval(pitm)) NE 0;
  2348. X}
  2349. X
  2350. XVisible bool in(e, t) value e, t; {
  2351. X    m_char = Lowchar;
  2352. X    found = No;
  2353. X    if (tlt_func(e, t, li_in, te_in, ta_in) == -1) {
  2354. X        switch (tlterr) {
  2355. X        case T_EMPTY: return No;
  2356. X        }
  2357. X    }
  2358. X    return found;
  2359. X}
  2360. X
  2361. XHidden value li_min(e, t) value e, t; {
  2362. X    return item(t, one);
  2363. X}
  2364. X
  2365. XHidden bool te_min(pitm) itemptr pitm; {
  2366. X    if (m_char > Charval(pitm))
  2367. X        m_char = Charval(pitm);
  2368. X    return Yes;
  2369. X}
  2370. X
  2371. XHidden bool ta_min(pitm) itemptr pitm; {
  2372. X    if (m_val EQ Vnil || compare(m_val, Ascval(pitm)) > 0) {
  2373. X        release(m_val);
  2374. X        m_val = copy(Ascval(pitm));
  2375. X    }
  2376. X    return Yes;
  2377. X}
  2378. X
  2379. XVisible value min1(t) value t; {
  2380. X    m_char = Highchar;
  2381. X    if (tlt_func(Vnil, t, li_min, te_min, ta_min) == -1) {
  2382. X        switch (tlterr) {
  2383. X        case T_TLT: interr(MIN_TLT);
  2384. X        case T_EMPTY: interr(MIN_EMPTY);
  2385. X        }
  2386. X    }
  2387. X    return m_val;
  2388. X}
  2389. X
  2390. XHidden value li_max(e, t) value e, t; {
  2391. X    value v= size(t);
  2392. X    m_val = item(t, v);
  2393. X    release(v);
  2394. X    return m_val;
  2395. X}
  2396. X
  2397. XHidden bool te_max(pitm) itemptr pitm; {
  2398. X    if (m_char < Charval(pitm))
  2399. X        m_char = Charval(pitm);
  2400. X    return Yes;
  2401. X}
  2402. X
  2403. XHidden bool ta_max(pitm) itemptr pitm; {
  2404. X    if (m_val EQ Vnil || compare(Ascval(pitm), m_val) > 0) {
  2405. X        release(m_val);
  2406. X        m_val = copy(Ascval(pitm));
  2407. X    }
  2408. X    return Yes;
  2409. X}
  2410. X
  2411. XVisible value max1(t) value t; {
  2412. X    m_char = Lowchar;
  2413. X    if (tlt_func(Vnil, t, li_max, te_max, ta_max) == -1) {
  2414. X        switch (tlterr) {
  2415. X        case T_TLT: interr(MAX_TLT);
  2416. X        case T_EMPTY: interr(MAX_EMPTY);
  2417. X        }
  2418. X    }
  2419. X    return m_val;
  2420. X}
  2421. X
  2422. XHidden bool te2min(pitm) itemptr pitm; {
  2423. X    if (m_char > Charval(pitm) && Charval(pitm) > ce) {
  2424. X        m_char = Charval(pitm);
  2425. X    }
  2426. X    return Yes;
  2427. X}
  2428. X
  2429. XHidden bool ta2min(pitm) itemptr pitm; {
  2430. X    if (compare(Ascval(pitm), ve) > 0
  2431. X        &&
  2432. X        (m_val EQ Vnil || compare(m_val, Ascval(pitm)) > 0)) {
  2433. X        release(m_val);
  2434. X        m_val = copy(Ascval(pitm));
  2435. X    }
  2436. X    return Yes;
  2437. X}
  2438. X
  2439. XVisible value min2(e, t) value e, t; {
  2440. X    m_char = Highchar;
  2441. X    if (tlt_func(e, t, l2min, te2min, ta2min) == -1) {
  2442. X        switch (tlterr) {
  2443. X        case T_TLT: interr(MIN2_TLT);
  2444. X        case T_EMPTY: interr(MIN2_EMPTY);
  2445. X        case T_CHAR: interr(MIN2_CHAR);
  2446. X        }
  2447. X        return Vnil;
  2448. X    }
  2449. X    if (m_val EQ Vnil && still_ok)
  2450. X        reqerr(MIN2_ELEM);
  2451. X    return m_val;
  2452. X}
  2453. X
  2454. X/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  2455. X
  2456. XHidden bool te2max(pitm) itemptr pitm; {
  2457. X    if (ce > Charval(pitm) && Charval(pitm) > m_char) {
  2458. X        m_char = Charval(pitm);
  2459. X    }
  2460. X    return Yes;
  2461. X}
  2462. X
  2463. XHidden bool ta2max(pitm) itemptr pitm; {
  2464. X    if (compare(ve, Ascval(pitm)) > 0
  2465. X        &&
  2466. X        (m_val EQ Vnil || compare(Ascval(pitm), m_val) > 0)) {
  2467. X        release(m_val);
  2468. X        m_val = copy(Ascval(pitm));
  2469. X    }
  2470. X    return Yes;
  2471. X}
  2472. X
  2473. XVisible value max2(e, t) value e, t; {
  2474. X    m_char = Lowchar;
  2475. X    if (tlt_func(e, t, l2max, te2max, ta2max) == -1) {
  2476. X        switch (tlterr) {
  2477. X        case T_TLT: interr(MAX2_TLT);
  2478. X        case T_EMPTY: interr(MAX2_EMPTY);
  2479. X        case T_CHAR: interr(MAX2_CHAR);
  2480. X        }
  2481. X        return Vnil;
  2482. X    }
  2483. X    if (m_val EQ Vnil && still_ok)
  2484. X        reqerr(MAX2_ELEM);
  2485. X    return m_val;
  2486. X}
  2487. X
  2488. END_OF_FILE
  2489.   if test 10941 -ne `wc -c <'abc/btr/i1tlt.c'`; then
  2490.     echo shar: \"'abc/btr/i1tlt.c'\" unpacked with wrong size!
  2491.   fi
  2492.   # end of 'abc/btr/i1tlt.c'
  2493. fi
  2494. echo shar: End of archive 14 \(of 25\).
  2495. cp /dev/null ark14isdone
  2496. MISSING=""
  2497. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do
  2498.     if test ! -f ark${I}isdone ; then
  2499.     MISSING="${MISSING} ${I}"
  2500.     fi
  2501. done
  2502. if test "${MISSING}" = "" ; then
  2503.     echo You have unpacked all 25 archives.
  2504.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2505. else
  2506.     echo You still must unpack the following archives:
  2507.     echo "        " ${MISSING}
  2508. fi
  2509. exit 0 # Just in case...
  2510.