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

  1. Subject:  v23i092:  ABC interactive programming environment, Part13/25
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: e42a6455 d4dc5881 00faf5b0 64a38b31
  5.  
  6. Submitted-by: Steven Pemberton <steven@cwi.nl>
  7. Posting-number: Volume 23, Issue 92
  8. Archive-name: abc/part13
  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/e1que1.c abc/bint1/DEP abc/bint3/i3loc.c
  17. #   abc/bint3/i3scr.c abc/mkconfig.c
  18. # Wrapped by rsalz@litchi.bbn.com on Mon Dec 17 13:28:05 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 13 (of 25)."'
  22. if test -f 'abc/bed/e1que1.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'abc/bed/e1que1.c'\"
  24. else
  25.   echo shar: Extracting \"'abc/bed/e1que1.c'\" \(11620 characters\)
  26.   sed "s/^X//" >'abc/bed/e1que1.c' <<'END_OF_FILE'
  27. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  28. X
  29. X/*
  30. X * B editor -- Manipulate queues of nodes, lower levels.
  31. X */
  32. X
  33. X#include "b.h"
  34. X#include "bedi.h"
  35. X#include "etex.h"
  36. X#include "feat.h"
  37. X#include "bobj.h"
  38. X#include "node.h"
  39. X#include "supr.h"
  40. X#include "queu.h"
  41. X#include "gram.h"
  42. X#include "tabl.h"
  43. X
  44. X#ifdef lint
  45. XVisible queue
  46. Xqcopy(q)
  47. X    queue q;
  48. X{
  49. X    return (queue) copy((value) q);
  50. X}
  51. X
  52. XVisible Procedure
  53. Xqrelease(q)
  54. X    queue q;
  55. X{
  56. X    release((value) q);
  57. X}
  58. X#endif
  59. X
  60. X/*
  61. X * Append queue 2 to the end of queue 1.
  62. X */
  63. X
  64. XVisible Procedure
  65. Xjoinqueues(pq, q)
  66. X    register queue *pq;
  67. X    register queue q;
  68. X{
  69. X    if (emptyqueue(q))
  70. X        return;
  71. X    while (*pq) {
  72. X        if (Refcnt(*pq) > 1)
  73. X            uniql((value*)pq);
  74. X        pq = &(*pq)->q_link;
  75. X    }
  76. X    *pq = q;
  77. X}
  78. X
  79. X
  80. X/*
  81. X * Prepend a node to a queue ("push").
  82. X * Empty strings and Optional holes are silently discarded.
  83. X */
  84. X
  85. XVisible Procedure
  86. Xpreptoqueue(n, pq)
  87. X    node n;
  88. X    register queue *pq;
  89. X{
  90. X    register queue q;
  91. X
  92. X    if (Is_etext(n)) {
  93. X        if (e_length((value) n) == 0)
  94. X            return;
  95. X        n = nodecopy(n);
  96. X    }
  97. X    else { /* Avoid Optional holes */
  98. X        if (symbol(n) == Optional)
  99. X            return;
  100. X        n = nodecopy(n);
  101. X    }
  102. X    q = (queue) mk_compound(2);
  103. X    q->q_data = n;
  104. X    q->q_link = *pq;
  105. X    *pq = q;
  106. X}
  107. X
  108. X
  109. X/*
  110. X * Append a node to the end of a queue (same extras as preptoqueue).
  111. X */
  112. X
  113. XVisible Procedure
  114. Xaddtoqueue(pq, n)
  115. X    register queue *pq;
  116. X    register node n;
  117. X{
  118. X    auto queue q = Qnil;
  119. X
  120. X    preptoqueue(n, &q);
  121. X    joinqueues(pq, q);
  122. X}
  123. X
  124. X
  125. X/*
  126. X * Push a string onto a queue.
  127. X */
  128. X
  129. XVisible Procedure
  130. Xstringtoqueue(str, pq)
  131. X    register string str;
  132. X    register queue *pq;
  133. X{
  134. X    register value  v;
  135. X
  136. X    if (str == NULL)
  137. X        return;
  138. X    v = mk_etext(str);
  139. X    preptoqueue((node) v, pq);
  140. X    release(v);
  141. X}
  142. X
  143. X/*
  144. X * Append a string to a queue.
  145. X */
  146. X
  147. X#ifdef NOT_USED
  148. X
  149. XVisible Procedure
  150. Xaddstringtoqueue(pq, str)
  151. X    register queue *pq;
  152. X    register string str;
  153. X{
  154. X    register value v = mk_etext(str);
  155. X
  156. X    addtoqueue(pq, (node) v);
  157. X    release(v);
  158. X}
  159. X
  160. X#endif /* NOT_USED */
  161. X
  162. X/*
  163. X * Get the first node of a queue and delink it ("pop").
  164. X */
  165. X
  166. XVisible node
  167. Xqueuebehead(pq)
  168. X    register queue *pq;
  169. X{
  170. X    register node n;
  171. X    register queue q = *pq;
  172. X
  173. X    Assert(q);
  174. X
  175. X    n = nodecopy(q->q_data);
  176. X    *pq = qcopy(q->q_link);
  177. X    qrelease(q);
  178. X    return n;
  179. X}
  180. X
  181. X
  182. X/*
  183. X * Split a node in successive queue elements which are pushed
  184. X * on the queue using preptoqueue.
  185. X * 'Atomic' nodes (texts and holes) are pushed unadorned.
  186. X */
  187. X
  188. XVisible Procedure
  189. Xsplitnode(n, pq)
  190. X    register node n;
  191. X    register queue *pq;
  192. X{
  193. X    register node nn;
  194. X    register string *rp;
  195. X    register int i;
  196. X    register int sym;
  197. X
  198. X    if (Is_etext(n)) {
  199. X        preptoqueue(n, pq);
  200. X        return;
  201. X    }
  202. X    sym = symbol(n);
  203. X    if (sym == Optional)
  204. X        return;
  205. X    if (sym == Hole) {
  206. X        preptoqueue(n, pq);
  207. X        return;
  208. X    }
  209. X
  210. X    rp = noderepr(n);
  211. X    for (i = nchildren(n); i >= 0; --i) {
  212. X        if (rp[i] && rp[i][0])
  213. X            stringtoqueue(rp[i], pq);
  214. X        if (i) {
  215. X            nn = child(n, i);
  216. X            if (Is_etext(nn) || symbol(nn) != Optional)
  217. X                preptoqueue(nn, pq);
  218. X        }
  219. X    }
  220. X}
  221. X
  222. X
  223. X/*
  224. X * Substitute the focus for its parent, appending the remainder of
  225. X * the parent to the queue.
  226. X * The focus must be the first child and not preceded by fixed text.
  227. X * The focus must be allowed in the place of its parent.
  228. X * If any of these conditions is not met, No is returned and nothing
  229. X * is changed.
  230. X *
  231. X * Do not queue a "hollow" rest, since it seems to be substituted anyway.
  232. X * (timo)
  233. X */
  234. X
  235. XVisible bool
  236. Xresttoqueue(pp, pq)
  237. X    register path *pp;
  238. X    register queue *pq;
  239. X{
  240. X    auto queue q = Qnil;
  241. X    register path pa = parent(*pp);
  242. X    register node n = tree(*pp);
  243. X    register int sym = symbol(n);
  244. X    /* register markbits x; */
  245. X    bool rest_is_hollow();
  246. X
  247. X    if (!pa || ichild(*pp) != 1
  248. X        || fwidth(noderepr(tree(pa))[0]) != 0 || !allowed(pa, sym))
  249. X        return No;
  250. X
  251. X    n = nodecopy(n);
  252. X    /* x = marks(n); */
  253. X    if (!up(pp)) Abort();
  254. X    if (!rest_is_hollow(tree(*pp))) {
  255. X        splitnode(tree(*pp), &q);
  256. X        noderelease(queuebehead(&q));
  257. X        joinqueues(pq, q);
  258. X    }
  259. X    treereplace(pp, n);
  260. X    /* if (x) { */
  261. X        /* markpath(pp, x); */ /* Actually, should restore all n's marks? */
  262. X    /* } */
  263. X    return Yes;
  264. X}
  265. X
  266. XHidden bool rest_is_hollow(n) node n; {
  267. X    register node nn;
  268. X    register string *rp;
  269. X    register int i;
  270. X    register int sym;
  271. X
  272. X    Assert(!Is_etext(n));
  273. X    
  274. X    rp = noderepr(n);
  275. X    for (i = nchildren(n); i >= 0; --i) {
  276. X        if (Fwidth(rp[i]) > 0)
  277. X            return No;
  278. X        if (i > 1) {
  279. X            nn = child(n, i);
  280. X            if (Is_etext(nn)
  281. X                ||
  282. X                ((sym=symbol(nn)) != Optional
  283. X                 &&
  284. X                 sym != Hole
  285. X                )
  286. X               )
  287. X                return No;
  288. X        }
  289. X    }
  290. X    return Yes;
  291. X}
  292. X
  293. X/*
  294. X * Like resttoqueue, but exactly from current position in fixed text.
  295. X * Also, it cannot fail.
  296. X */
  297. X
  298. XVisible Procedure
  299. Xnosuggtoqueue(ep, pq)
  300. X    register environ *ep;
  301. X    queue *pq;
  302. X{
  303. X    auto queue q = Qnil;
  304. X    register int i;
  305. X    register string *rp;
  306. X    register node n;
  307. X    register node nn;
  308. X    register int sym;
  309. X    string str;
  310. X
  311. X    if (issuggestion(ep))
  312. X        return;
  313. X    Assert((ep->mode == FHOLE || ep->mode == VHOLE) && (ep->s1&1));
  314. X
  315. X    n = tree(ep->focus);
  316. X    rp = noderepr(n);
  317. X    for (i = nchildren(n); i > ep->s1/2; --i) {
  318. X        if (!Fw_zero(rp[i]))
  319. X            stringtoqueue(rp[i], &q);
  320. X        nn = child(n, i);
  321. X        sym = symbol(nn);
  322. X        if (sym != Optional) {
  323. X            preptoqueue(nn, &q);
  324. X            if (sym != Hole) {
  325. X                s_downi(ep, i);
  326. X                delfocus(&ep->focus);
  327. X                s_up(ep);
  328. X            }
  329. X        }
  330. X    }
  331. X    str = rp[i];
  332. X    if (str && str[ep->s2]) /* Push partial first text */
  333. X        stringtoqueue(str + ep->s2, &q);
  334. X    joinqueues(pq, q);
  335. X}
  336. X
  337. X
  338. X/*
  339. X * Check whether the remainder of the current node is all suggestion.
  340. X */
  341. X
  342. XVisible bool
  343. Xissuggestion(ep)
  344. X    register environ *ep;
  345. X{
  346. X    register node n;
  347. X    register int nch;
  348. X    register int sym;
  349. X    register int i;
  350. X
  351. X    if (ep->mode != VHOLE && ep->mode != FHOLE || !(ep->s1&1))
  352. X        return No; /* Actually wrong call? */
  353. X
  354. X    n = tree(ep->focus);
  355. X    nch = nchildren(n);
  356. X    for (i = ep->s1/2 + 1; i <= nch; ++i) {
  357. X        sym = symbol(child(n, i));
  358. X        if (sym != Hole && sym != Optional)
  359. X            return No;
  360. X    }
  361. X    return Yes;
  362. X}
  363. X
  364. X
  365. X/*
  366. X * See if a node fits in a hole.
  367. X */
  368. X
  369. XVisible bool
  370. Xfitnode(pp, n)
  371. X    register path *pp;
  372. X    register node n;
  373. X{
  374. X    if (!allowed(*pp, symbol(n)))
  375. X        return No;
  376. X    treereplace(pp, nodecopy(n));
  377. X    return Yes;
  378. X}
  379. X
  380. X
  381. X/*
  382. X * Fit a string in a hole.
  383. X * Returns the number of characters consumed.
  384. X * (This does not have to be the maximum possible, but a reasonable attempt
  385. X * is made.  If the internal buffer is exhausted, it leaves the rest for
  386. X * another call.)
  387. X */
  388. X
  389. XVisible int
  390. Xfitstring(pp, str, alt_c)
  391. X    register path *pp;
  392. X    register string str;
  393. X    int alt_c;
  394. X{
  395. X    environ dummyenv;
  396. X    register node n;
  397. X    register int ich;
  398. X    register int len;
  399. X    register string cp;
  400. X    char buf[1024];
  401. X
  402. X    Assert(str);
  403. X    if (!str[0])
  404. X        return 0;
  405. X    if (!insguess(pp, str[0], &dummyenv)) {
  406. X        if (!alt_c)
  407. X            return 0;
  408. X        if (!insguess(pp, alt_c, &dummyenv))
  409. X            return 0;
  410. X    }
  411. X    if (Is_etext(tree(*pp)))
  412. X        if (!up(pp)) Abort();
  413. X    if (dummyenv.mode == FHOLE) {
  414. X        cp = noderepr(tree(*pp))[0];
  415. X        len = 1;
  416. X        if (cp) {
  417. X            ++str;
  418. X            ++cp;
  419. X            while (*str >= ' ' && *str == *cp) {
  420. X                ++len;
  421. X                ++str;
  422. X                ++cp;
  423. X            }
  424. X        }
  425. X        return len;
  426. X    }
  427. X    if (dummyenv.mode == VHOLE) {
  428. X        buf[0] = str[0];
  429. X        ++str;
  430. X        len = 1;
  431. X        n = tree(*pp);
  432. X        ich = dummyenv.s1/2;
  433. X        while (*str && mayinsert(n, ich, len, *str) && len < sizeof buf - 1) {
  434. X            buf[len] = *str;
  435. X            ++str;
  436. X            ++len;
  437. X        }
  438. X        if (len > 1) {
  439. X            buf[len] = 0;
  440. X            if (!downi(pp, ich)) Abort();
  441. X            treereplace(pp, (node) mk_etext(buf));
  442. X            if (!up(pp)) Abort();
  443. X        }
  444. X        return len;
  445. X    }
  446. X    return 1;
  447. X}
  448. X
  449. X
  450. X/*
  451. X * Set the focus position (some VHOLE/FHOLE setting, probably)
  452. X * at the 'len'th character from the beginning of the current node.
  453. X * This may involve going to a child or moving beyond the current subtree.
  454. X * Negative 'len' values may be given to indicate negative widths;
  455. X * this is implemented incomplete.
  456. X */
  457. X
  458. XVisible Procedure
  459. Xfixfocus(ep, len)
  460. X    register environ *ep;
  461. X    register int len;
  462. X{
  463. X    node nn;
  464. X    register node n = tree(ep->focus);
  465. X    register string *rp;
  466. X    register int i = 0;
  467. X    register int nch;
  468. X    register int w;
  469. X
  470. X    if (Is_etext(n)) {
  471. X        w = e_length((value)n);
  472. X        Assert(w >= len && len >= 0);
  473. X        if (w > len)
  474. X            ep->spflag = No;
  475. X        ep->mode = VHOLE;
  476. X        ep->s1 = ichild(ep->focus) * 2;
  477. X        ep->s2 = len;
  478. X        s_up(ep);
  479. X        return;
  480. X    }
  481. X    nch = nchildren(n);
  482. X    w = nodewidth(n);
  483. X    if (len > w && w >= 0) {
  484. X        i = ichild(ep->focus); /* Change initial condition for for-loop */
  485. X        if (!up(&ep->focus)) {
  486. X            ep->mode = ATEND;
  487. X            return;
  488. X        }
  489. X        higher(ep);
  490. X        n = tree(ep->focus);
  491. X    }
  492. X
  493. X    rp = noderepr(n);
  494. X    for (; i <= nch; ++i) {
  495. X        if (i) {
  496. X            nn = child(n, i);
  497. X            w = nodewidth(nn);
  498. X            if (w < 0 || w >= len && len >= 0) {
  499. X                s_downi(ep, i);
  500. X                fixfocus(ep, len);
  501. X                return;
  502. X            }
  503. X            if (len >= 0)
  504. X                len -= w;
  505. X        }
  506. X        w = Fwidth(rp[i]);
  507. X        if (w >= len && len >= 0) {
  508. X            if (w > len)
  509. X                ep->spflag = No;
  510. X            ep->mode = FHOLE;
  511. X            ep->s1 = 2*i + 1;
  512. X            ep->s2 = len;
  513. X            return;
  514. X        }
  515. X        else if (w < 0)
  516. X            len = 0;
  517. X        else
  518. X            len -= w;
  519. X    }
  520. X    ep->mode = ATEND;
  521. X}
  522. X
  523. X
  524. X/*
  525. X * Apply, if possible, a special fix relating to spaces:
  526. X * when a space has been interpreted as joining character
  527. X * and we end up in the following hole, but we don't succeed
  528. X * in filling the hole; it is then tried to delete the hole
  529. X * and the space.
  530. X * Usually this doesn't occur, but it may occur when inserting
  531. X * after a space that was already fixed on the screen but now
  532. X * deserves re-interpretation.
  533. X */
  534. X
  535. XVisible bool
  536. Xspacefix(ep)
  537. X    environ *ep;
  538. X{
  539. X    path pa;
  540. X    node n;
  541. X    string *rp;
  542. X
  543. X    if (ichild(ep->focus) != 2 || symbol(tree(ep->focus)) != Hole)
  544. X        return No;
  545. X    pa = parent(ep->focus);
  546. X    n = tree(pa);
  547. X    rp = noderepr(n);
  548. X    if (!Fw_zero(rp[0]) || Fwidth(rp[1]) != 1 || rp[1][0] != ' ')
  549. X        return No;
  550. X    n = firstchild(n);
  551. X    if (!allowed(pa, symbol(n)))
  552. X        return No;
  553. X    s_up(ep);
  554. X    treereplace(&ep->focus, nodecopy(n));
  555. X    ep->mode = ATEND;
  556. X    ep->spflag = Yes;
  557. X    return Yes;
  558. X}
  559. X
  560. X
  561. X/*
  562. X * Prepend a subset of a node to a queue.
  563. X */
  564. X
  565. XVisible Procedure
  566. Xsubsettoqueue(n, s1, s2, pq)
  567. X    register node n;
  568. X    register int s1;
  569. X    register int s2;
  570. X    register queue *pq;
  571. X{
  572. X    register string *rp = noderepr(n);
  573. X
  574. X    for (; s2 >= s1; --s2) {
  575. X        if (s2&1)
  576. X            stringtoqueue(rp[s2/2], pq);
  577. X        else
  578. X            preptoqueue(child(n, s2/2), pq);
  579. X    }
  580. X}
  581. X
  582. X#ifdef SHOWBUF
  583. X
  584. X/*
  585. X * Produce flat text out of a queue's first line, to show it on screen.
  586. X */
  587. X
  588. XVisible string
  589. Xquerepr(qv)
  590. X    value qv;
  591. X{
  592. X    queue q = (queue)qv;
  593. X    node n;
  594. X    static char buf[1000]; /***** Cannot overflow? *****/
  595. X    string cp;
  596. X    string sp;
  597. X    string *rp;
  598. X    int nch;
  599. X    int i;
  600. X    int len;
  601. X    value chld;
  602. X
  603. X    cp = buf;
  604. X    for (; q; q = q->q_link) {
  605. X        n = q->q_data;
  606. X        if (Is_etext(n)) {
  607. X            for (sp = e_strval((value) n); cp < buf+80 && *sp; ++sp) {
  608. X                if (!isprint(*sp) && *sp != ' ')
  609. X                    break;
  610. X                *cp++ = *sp;
  611. X            }
  612. X            if (*sp == '\n') {
  613. X                if (!emptyqueue(q->q_link)) {
  614. X                    strcpy(cp, " ...");
  615. X                    cp += 4;
  616. X                }
  617. X                break;
  618. X            }
  619. X        }
  620. X        else {
  621. X            rp = noderepr(n);
  622. X            nch = nchildren(n);
  623. X            for (i = 0; i <= nch; ++i) {
  624. X                if (i > 0) {
  625. X                    if (Is_etext(child(n, i))) {
  626. X                        chld= (value) child(n, i);
  627. X                        len = e_length(chld);
  628. X                        if (len > 80)
  629. X                            len = 80;
  630. X                        strncpy(cp, e_strval(chld), len);
  631. X                        cp += len;
  632. X                    }
  633. X                    else {
  634. X                        strcpy(cp, "...");
  635. X                        cp += 3;
  636. X                    }
  637. X                }
  638. X                if (Fw_negative(rp[i])) {
  639. X                    strcpy(cp, " ...");
  640. X                    cp += 4;
  641. X                    break;
  642. X                }
  643. X                if (Fw_positive(rp[i])) {
  644. X                    strcpy(cp, rp[i]);
  645. X                    while (*cp)
  646. X                        ++cp;
  647. X                    if (cp[-1] == '\t' || cp[-1] == '\b')
  648. X                        --cp;
  649. X                }
  650. X            }
  651. X        }
  652. X        if (cp >= buf+80) {
  653. X            strcpy(buf+76, "...");
  654. X            break;
  655. X        }
  656. X    }
  657. X    *cp = 0;
  658. X    return buf;
  659. X}
  660. X
  661. X#endif /* SHOWBUF */
  662. X
  663. X#ifdef UNUSED
  664. XVisible Procedure dumpqueue(pq, m) queue *pq; string m; {
  665. X    char stuff[80];
  666. X    register string str = stuff;
  667. X    FILE *fp;
  668. X    static int qdump;
  669. X    queue q= *pq;
  670. X    node n;
  671. X    
  672. X    fp= fopen("/userfs4/abc/timo/mark2/ABCENV", "a");
  673. X    Assert(fp != NULL);
  674. X    
  675. X    qdump++;
  676. X    fprintf(fp, "+++ QUEUE %d: %s +++\n", qdump, m);
  677. X
  678. X    for (; q; q=q->q_link) {
  679. X        fprintf(fp, "NEXTNODE: ");
  680. X        n= q->q_data;
  681. X        writenode(n, fp);
  682. X        fprintf(fp, "\n");
  683. X    }
  684. X    fprintf(fp, "NILQ\n");
  685. X    fclose(fp);
  686. X}
  687. X#endif
  688. END_OF_FILE
  689.   if test 11620 -ne `wc -c <'abc/bed/e1que1.c'`; then
  690.     echo shar: \"'abc/bed/e1que1.c'\" unpacked with wrong size!
  691.   fi
  692.   # end of 'abc/bed/e1que1.c'
  693. fi
  694. if test -f 'abc/bint1/DEP' -a "${1}" != "-c" ; then 
  695.   echo shar: Will not clobber existing file \"'abc/bint1/DEP'\"
  696. else
  697.   echo shar: Extracting \"'abc/bint1/DEP'\" \(2543 characters\)
  698.   sed "s/^X//" >'abc/bint1/DEP' <<'END_OF_FILE'
  699. Xi1com.o: i1com.c
  700. Xi1com.o: ../bhdrs/b.h
  701. Xi1com.o: ../uhdrs/osconf.h
  702. Xi1com.o: ../uhdrs/os.h
  703. Xi1com.o: ../uhdrs/conf.h
  704. Xi1com.o: ../uhdrs/config.h
  705. Xi1com.o: ../bhdrs/bint.h
  706. Xi1com.o: ../bhdrs/bobj.h
  707. Xi1com.o: ../ihdrs/i2nod.h
  708. Xi1com.o: ../ihdrs/i2gen.h
  709. Xi1com.o: ../ihdrs/i3env.h
  710. Xi1fun.o: i1fun.c
  711. Xi1fun.o: ../bhdrs/b.h
  712. Xi1fun.o: ../uhdrs/osconf.h
  713. Xi1fun.o: ../uhdrs/os.h
  714. Xi1fun.o: ../uhdrs/conf.h
  715. Xi1fun.o: ../uhdrs/config.h
  716. Xi1fun.o: ../uhdrs/feat.h
  717. Xi1fun.o: ../bhdrs/bobj.h
  718. Xi1fun.o: ../ihdrs/i0err.h
  719. Xi1fun.o: ../ihdrs/i1num.h
  720. Xi1nua.o: i1nua.c
  721. Xi1nua.o: ../bhdrs/b.h
  722. Xi1nua.o: ../uhdrs/osconf.h
  723. Xi1nua.o: ../uhdrs/os.h
  724. Xi1nua.o: ../uhdrs/conf.h
  725. Xi1nua.o: ../uhdrs/config.h
  726. Xi1nua.o: ../uhdrs/feat.h
  727. Xi1nua.o: ../bhdrs/bobj.h
  728. Xi1nua.o: ../ihdrs/i0err.h
  729. Xi1nua.o: ../ihdrs/i1num.h
  730. Xi1nuc.o: i1nuc.c
  731. Xi1nuc.o: ../bhdrs/b.h
  732. Xi1nuc.o: ../uhdrs/osconf.h
  733. Xi1nuc.o: ../uhdrs/os.h
  734. Xi1nuc.o: ../uhdrs/conf.h
  735. Xi1nuc.o: ../uhdrs/config.h
  736. Xi1nuc.o: ../uhdrs/feat.h
  737. Xi1nuc.o: ../bhdrs/bmem.h
  738. Xi1nuc.o: ../bhdrs/bobj.h
  739. Xi1nuc.o: ../ihdrs/i1num.h
  740. Xi1nug.o: i1nug.c
  741. Xi1nug.o: ../bhdrs/b.h
  742. Xi1nug.o: ../uhdrs/osconf.h
  743. Xi1nug.o: ../uhdrs/os.h
  744. Xi1nug.o: ../uhdrs/conf.h
  745. Xi1nug.o: ../uhdrs/config.h
  746. Xi1nug.o: ../uhdrs/feat.h
  747. Xi1nug.o: ../bhdrs/bobj.h
  748. Xi1nug.o: ../ihdrs/i1num.h
  749. Xi1nui.o: i1nui.c
  750. Xi1nui.o: ../bhdrs/b.h
  751. Xi1nui.o: ../uhdrs/osconf.h
  752. Xi1nui.o: ../uhdrs/os.h
  753. Xi1nui.o: ../uhdrs/conf.h
  754. Xi1nui.o: ../uhdrs/config.h
  755. Xi1nui.o: ../uhdrs/feat.h
  756. Xi1nui.o: ../bhdrs/bobj.h
  757. Xi1nui.o: ../ihdrs/i1num.h
  758. Xi1num.o: i1num.c
  759. Xi1num.o: ../bhdrs/b.h
  760. Xi1num.o: ../uhdrs/osconf.h
  761. Xi1num.o: ../uhdrs/os.h
  762. Xi1num.o: ../uhdrs/conf.h
  763. Xi1num.o: ../uhdrs/config.h
  764. Xi1num.o: ../uhdrs/feat.h
  765. Xi1num.o: ../bhdrs/bobj.h
  766. Xi1num.o: ../ihdrs/i1num.h
  767. Xi1nuq.o: i1nuq.c
  768. Xi1nuq.o: ../bhdrs/b.h
  769. Xi1nuq.o: ../uhdrs/osconf.h
  770. Xi1nuq.o: ../uhdrs/os.h
  771. Xi1nuq.o: ../uhdrs/conf.h
  772. Xi1nuq.o: ../uhdrs/config.h
  773. Xi1nuq.o: ../uhdrs/feat.h
  774. Xi1nuq.o: ../bhdrs/bobj.h
  775. Xi1nuq.o: ../ihdrs/i1num.h
  776. Xi1nur.o: i1nur.c
  777. Xi1nur.o: ../bhdrs/b.h
  778. Xi1nur.o: ../uhdrs/osconf.h
  779. Xi1nur.o: ../uhdrs/os.h
  780. Xi1nur.o: ../uhdrs/conf.h
  781. Xi1nur.o: ../uhdrs/config.h
  782. Xi1nur.o: ../uhdrs/feat.h
  783. Xi1nur.o: ../bhdrs/bobj.h
  784. Xi1nur.o: ../ihdrs/i0err.h
  785. Xi1nur.o: ../ihdrs/i1num.h
  786. Xi1nut.o: i1nut.c
  787. Xi1nut.o: ../bhdrs/b.h
  788. Xi1nut.o: ../uhdrs/osconf.h
  789. Xi1nut.o: ../uhdrs/os.h
  790. Xi1nut.o: ../uhdrs/conf.h
  791. Xi1nut.o: ../uhdrs/config.h
  792. Xi1nut.o: ../bhdrs/bobj.h
  793. Xi1nut.o: ../ihdrs/i1num.h
  794. Xi1tra.o: i1tra.c
  795. Xi1tra.o: ../bhdrs/b.h
  796. Xi1tra.o: ../uhdrs/osconf.h
  797. Xi1tra.o: ../uhdrs/os.h
  798. Xi1tra.o: ../uhdrs/conf.h
  799. Xi1tra.o: ../uhdrs/config.h
  800. Xi1tra.o: ../uhdrs/feat.h
  801. Xi1tra.o: ../bhdrs/bobj.h
  802. Xi1tra.o: ../ihdrs/i0err.h
  803. Xi1tra.o: ../ihdrs/i1num.h
  804. END_OF_FILE
  805.   if test 2543 -ne `wc -c <'abc/bint1/DEP'`; then
  806.     echo shar: \"'abc/bint1/DEP'\" unpacked with wrong size!
  807.   fi
  808.   # end of 'abc/bint1/DEP'
  809. fi
  810. if test -f 'abc/bint3/i3loc.c' -a "${1}" != "-c" ; then 
  811.   echo shar: Will not clobber existing file \"'abc/bint3/i3loc.c'\"
  812. else
  813.   echo shar: Extracting \"'abc/bint3/i3loc.c'\" \(11448 characters\)
  814.   sed "s/^X//" >'abc/bint3/i3loc.c' <<'END_OF_FILE'
  815. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  816. X
  817. X/* B locations and environments */
  818. X#include "b.h"
  819. X#include "bint.h"
  820. X#include "bobj.h"
  821. X#include "i0err.h"
  822. X#include "i3env.h" /* for bndtgs */
  823. X#include "i3in2.h"
  824. X
  825. X#define TAR_NO_INIT    MESS(3600, "location not initialised")
  826. X#define TARNAME_NO_INIT    MESS(3601, "%s hasn't been initialised")
  827. X#define NO_KEY_OF_TABLE    MESS(3602, "key not in table")
  828. X#define INS_NO_LIST    MESS(3603, "inserting in non-list")
  829. X#define REM_NO_LIST    MESS(3604, "removing from non-list")
  830. X#define REM_EMPTY_LIST    MESS(3605, "removing from empty list")
  831. X#define SEL_EMPTY    MESS(3606, "selection on empty table")
  832. X
  833. X#define Is_local(t)    (Is_compound(t))
  834. X#define Is_global(t)    (Is_table(t))
  835. X
  836. X#define Loc_indirect(ll) ((ll) != Pnil && *(ll) != Vnil && Is_indirect(*(ll)))
  837. X
  838. XHidden value* location(l, err) loc l; bool err; {
  839. X    value *ll= Pnil, lv;
  840. X    
  841. X    if (Is_locloc(l)) {
  842. X        if (!in_locenv(curnv->tab, l, &ll) && err)
  843. X            interr(TAR_NO_INIT);
  844. X        return ll;
  845. X    }
  846. X    else if (Is_simploc(l)) {
  847. X        simploc *sl= Simploc(l);
  848. X        value ta= sl->e->tab, ke= sl->i;
  849. X        
  850. X        if (!in_locenv(ta, ke, &ll)) {
  851. X            if (Loc_indirect(ll) && Is_global(ta))
  852. X                load_global(*ll, ke, err);
  853. X            else if (err) {
  854. X                if (Is_locloc(ke))
  855. X                    interr(TAR_NO_INIT);
  856. X                else 
  857. X                    interrV(TARNAME_NO_INIT, ke);
  858. X            }
  859. X        }
  860. X        return ll;
  861. X    }
  862. X    else if (Is_tbseloc(l)) {
  863. X        tbseloc *tl= Tbseloc(l);
  864. X
  865. X        lv= locvalue(tl->R, &ll, err);
  866. X        if (lv != Vnil) {
  867. X            if (!Is_table(lv)) {
  868. X                if (err) interr(SEL_NO_TABLE);
  869. X                ll= Pnil;
  870. X            }
  871. X            else {
  872. X                ll= adrassoc(lv, tl->K);
  873. X                if (ll == Pnil && err) 
  874. X                    interr(NO_KEY_OF_TABLE);
  875. X            }
  876. X        }
  877. X        return ll;
  878. X    }
  879. X    else {
  880. X        syserr(MESS(3607, "call of location with improper type"));
  881. X        return (value *) Dummy;
  882. X    }
  883. X}
  884. X
  885. XVisible value locvalue(l, ll, err) loc l; value **ll; bool err; {
  886. X    *ll= location(l, err);
  887. X    if (*ll == Pnil || **ll == Vnil)
  888. X        return Vnil;
  889. X    else if (Is_indirect(**ll))
  890. X        return Indirect(**ll)->val;
  891. X    else return **ll;
  892. X}
  893. X
  894. XHidden bool in_locenv(t, k, ll) value t, k, **ll; {
  895. X    *ll= envassoc(t, k);
  896. X    if (*ll == Pnil || **ll == Vnil)
  897. X        return No;
  898. X    else if (Is_indirect(**ll) && Indirect(**ll)->val == Vnil)
  899. X        return No;
  900. X    else return Yes;
  901. X}
  902. X
  903. XVisible Procedure uniquify(l) loc l; {
  904. X    if (Is_simploc(l)) {
  905. X        simploc *sl= Simploc(l);
  906. X        value *ta= &(sl->e->tab), ke= sl->i;
  907. X        value *aa;
  908. X
  909. X        check_location(l);
  910. X        uniql(ta);
  911. X        if (still_ok) {
  912. X            if (Is_local(*ta))
  913. X                uniql(aa= Field(*ta, SmallIntVal(ke)));
  914. X            else {
  915. X                VOID uniq_assoc(*ta, ke);
  916. X                aa= adrassoc(*ta, ke);
  917. X            }
  918. X            if (*aa != Vnil && Is_indirect(*aa))
  919. X                uniql(&(Indirect(*aa)->val));
  920. X        }
  921. X    }
  922. X    else if (Is_tbseloc(l)) {
  923. X        tbseloc *tl= Tbseloc(l);
  924. X        value ta, ke, *ll;
  925. X        
  926. X        uniquify(tl->R);
  927. X        if (still_ok) {
  928. X            ta= locvalue(tl->R, &ll, Yes);
  929. X            ke= tl->K;
  930. X            if (!Is_table(ta)) interr(SEL_NO_TABLE);
  931. X            else if (empty(ta)) interr(SEL_EMPTY);
  932. X            else if (!in_keys(ke, ta)) interr(NO_KEY_OF_TABLE);
  933. X            else VOID uniq_assoc(ta, ke);
  934. X        }
  935. X    }
  936. X    else if (Is_trimloc(l)) {
  937. X        syserr(MESS(3608, "uniquifying text-selection location"));
  938. X    }
  939. X    else if (Is_compound(l)) {
  940. X        syserr(MESS(3609, "uniquifying comploc"));
  941. X    }
  942. X    else syserr(MESS(3610, "uniquifying non-location"));
  943. X}
  944. X
  945. XVisible Procedure check_location(l) loc l; {
  946. X    VOID location(l, Yes);
  947. X    /* location may produce an error message */
  948. X}
  949. X
  950. XHidden value content(l) loc l; {
  951. X    value *ll;
  952. X    value lv= locvalue(l, &ll, Yes);
  953. X    return still_ok ? copy(lv) : Vnil;
  954. X}
  955. X
  956. X#define TRIM_TARG_TYPE MESS(3611, "text-selection (@ or |) on non-text")
  957. X#define TRIM_TARG_TEXT MESS(3612, "in the location t@p or t|p, t does not contain a text")
  958. X#define TRIM_TARG_BND  MESS(3613, "in the location t@p or t|p, p is out of bounds")
  959. X
  960. XVisible loc trim_loc(l, N, sign) loc l; value N; char sign; {
  961. X    loc root, res= Lnil;
  962. X    value text, B, C;
  963. X    
  964. X    if (Is_simploc(l) || Is_tbseloc(l)) {
  965. X        root= l;
  966. X        B= zero; C= zero;
  967. X    }
  968. X    else if (Is_trimloc(l)) {
  969. X        trimloc *rr= Trimloc(l);
  970. X        root= rr->R;
  971. X        B= rr->B; C= rr->C;
  972. X    }
  973. X    else {
  974. X        interr(TRIM_TARG_TYPE);
  975. X        return Lnil;
  976. X    }
  977. X    text= content(root);
  978. X    if (!still_ok);
  979. X    else if (!Is_text(text))
  980. X        interr(TRIM_TARG_TEXT);
  981. X    else {
  982. X        value n= size(text), w;
  983. X        value Bnew= Vnil, Cnew= Vnil;
  984. X        bool changed= No;
  985. X        
  986. X        if (sign == '@') {     /* behead: B= max{N-1+B, B} */
  987. X            Bnew= sum(B, w= diff(N, one));
  988. X            if (changed= (compare(Bnew, B) > 0))
  989. X                B= Bnew;
  990. X        }
  991. X        else {            /* curtail: C= max{n-N-B, C} */
  992. X            Cnew= diff(w= diff(n, N), B);
  993. X            if (changed= (compare(Cnew, C) > 0))
  994. X                C= Cnew;
  995. X        }
  996. X        if (changed) {
  997. X            value b_plus_c= sum(B, C);
  998. X             if (still_ok && compare(b_plus_c, n) > 0)
  999. X                interr(TRIM_TARG_BND);
  1000. X            release(b_plus_c);
  1001. X        }
  1002. X        if (still_ok) res= mk_trimloc(root, B, C);
  1003. X        release(Bnew); 
  1004. X        release(Cnew);
  1005. X        release(w);
  1006. X        release(n);
  1007. X    }
  1008. X    release(text);
  1009. X    return res;
  1010. X}
  1011. X
  1012. XVisible loc tbsel_loc(R, K) loc R; value K; {
  1013. X    if (Is_simploc(R) || Is_tbseloc(R)) return mk_tbseloc(R, K);
  1014. X    else interr(MESS(3614, "selection on location of improper type"));
  1015. X    return Lnil;
  1016. X}
  1017. X
  1018. XVisible loc local_loc(i) basidf i; { return mk_simploc(i, curnv); }
  1019. X
  1020. XVisible loc global_loc(i) basidf i; { return mk_simploc(i, prmnv); }
  1021. X
  1022. XHidden Procedure put_trim(v, tl) value v; trimloc *tl; {
  1023. X    value rr, nn, head, tail, part, *ll;
  1024. X    value B= tl->B, C= tl->C, len, b_plus_c, tail_start;
  1025. X    
  1026. X    rr= locvalue(tl->R, &ll, Yes);
  1027. X    len= size(rr);
  1028. X    b_plus_c= sum(B, C);
  1029. X     if (compare(b_plus_c, len) > 0)
  1030. X        interr(MESS(3615, "text-selection (@ or |) out of bounds"));
  1031. X    else {
  1032. X        if (compare(B, zero) < 0) B= zero;
  1033. X        tail_start= sum(len, one);
  1034. X        if (compare(C, zero) > 0) {
  1035. X            tail_start= diff(nn= tail_start, C);
  1036. X            release(nn);
  1037. X        }
  1038. X        head= curtail(rr, B); /* rr|B */
  1039. X        tail= behead(rr, tail_start); /* rr@(#rr-C+1) */
  1040. X        release(tail_start);
  1041. X        part= concat(head, v); release(head);
  1042. X        nn= concat(part, tail); release(part); release(tail);
  1043. X        put(nn, tl->R); release(nn);
  1044. X    }
  1045. X    release(len); release(b_plus_c);
  1046. X}
  1047. X
  1048. XHidden Procedure rm_indirection(l) loc l; {
  1049. X    for (; Is_tbseloc(l); l= Tbseloc(l)->R)
  1050. X        ;
  1051. X    if (Is_simploc(l)) {
  1052. X        simploc *sl= Simploc(l);
  1053. X        value *ll= envassoc(sl->e->tab, sl->i);
  1054. X        
  1055. X        if (Loc_indirect(ll)) {
  1056. X            value v= copy(Indirect(*ll)->val);
  1057. X            release(*ll);
  1058. X            *ll= v;
  1059. X        }
  1060. X    }
  1061. X}
  1062. X
  1063. XVisible Procedure put(v, l) value v; loc l; {
  1064. X    if (Is_locloc(l)) {
  1065. X        e_replace(v, &curnv->tab, l);
  1066. X    }
  1067. X    else if (Is_simploc(l)) {
  1068. X        simploc *sl= Simploc(l);
  1069. X         e_replace(v, &(sl->e->tab), sl->i);
  1070. X    }
  1071. X    else if (Is_trimloc(l)) {
  1072. X        if (!Is_text(v)) interr(MESS(3616, "putting non-text in text-selection (@ or |)"));
  1073. X        else put_trim(v, Trimloc(l));
  1074. X    }
  1075. X    else if (Is_compound(l)) {
  1076. X        intlet k, len= Nfields(l);
  1077. X        if (!Is_compound(v))
  1078. X            interr(MESS(3617, "putting non-compound in compound location"));
  1079. X        else if (Nfields(v) != Nfields(l))
  1080. X            interr(MESS(3618, "putting compound in compound location of different length"));
  1081. X        else k_Overfields { put(*Field(v, k), *Field(l, k)); }
  1082. X    }
  1083. X    else if (Is_tbseloc(l)) {
  1084. X        tbseloc *tl= Tbseloc(l);
  1085. X        uniquify(tl->R);
  1086. X        if (still_ok) {
  1087. X            value *ll, lv;
  1088. X            lv= locvalue(tl->R, &ll, Yes);
  1089. X            if (!Is_table(lv))
  1090. X                interr(SEL_NO_TABLE);
  1091. X            else {
  1092. X                rm_indirection(tl->R);
  1093. X                replace(v, ll, tl->K);
  1094. X            }
  1095. X        }
  1096. X    }
  1097. X    else interr(MESS(3619, "putting in non-location"));
  1098. X}
  1099. X
  1100. X/* Check for correct effect of multiple put-command: catches PUT 1, 2 IN x, x.  
  1101. X   The assignment cannot be undone, but this is not considered a problem.
  1102. X   For trimmed-texts, no checks are made because the language definition
  1103. X   itself causes problem (try PUT "abc", "" IN x@2|1, x@3|1). */
  1104. X
  1105. XHidden bool putck(v, l) value v; loc l; {
  1106. X    intlet k, len;
  1107. X    value *ll, lv;
  1108. X    if (!still_ok) return No;
  1109. X    if (Is_compound(l)) {
  1110. X        if (!Is_compound(v) || Nfields(v) != (len= Nfields(l)))
  1111. X            return No; /* Severe type error */
  1112. X        k_Overfields
  1113. X            { if (!putck(*Field(v, k), *Field(l, k))) return No; }
  1114. X        return Yes;
  1115. X    }
  1116. X    if (Is_trimloc(l)) return Yes; /* Don't check trim locations */
  1117. X    lv= locvalue(l, &ll, No);
  1118. X    return lv != Vnil && compare(v, lv) == 0;
  1119. X}
  1120. X
  1121. X/* The check can't be called from within put because put is recursive,
  1122. X   and so is the check: then, for the inner levels the check would be done
  1123. X   twice.  Moreover, we don't want to clutter up put, which is called
  1124. X   internally in, many places. */
  1125. X
  1126. XVisible Procedure put_with_check(v, l) value v; loc l; {
  1127. X    intlet i, k, len; bool ok;
  1128. X    put(v, l);
  1129. X    if (!still_ok || !Is_compound(l))
  1130. X        return; /* Single target can't be wrong */
  1131. X    len= Nfields(l); ok= Yes;
  1132. X    /* Quick check for putting in all different local targets: */
  1133. X    k_Overfields {
  1134. X        if (!IsSmallInt(*Field(l, k))) { ok= No; break; }
  1135. X        for (i= k-1; i >= 0; --i) {
  1136. X            if (*Field(l, i) == *Field(l, k)) { ok= No; break; }
  1137. X        }
  1138. X        if (!ok) break;
  1139. X    }
  1140. X    if (ok) return; /* All different local basic-targets */
  1141. X    if (!putck(v, l))
  1142. X        interr(MESS(3620, "putting different values in same location"));
  1143. X}
  1144. X
  1145. X
  1146. X#define DEL_NO_TARGET    MESS(3621, "deleting non-location")
  1147. X#define DEL_TRIM_TARGET    MESS(3622, "deleting text-selection (@ or |) location")
  1148. X
  1149. XHidden bool l_exists(l) loc l; {
  1150. X    if (Is_simploc(l)) {
  1151. X        simploc *sl= Simploc(l);
  1152. X        value ta= sl->e->tab, *ll;
  1153. X        return in_locenv(ta, sl->i, &ll) ||
  1154. X            Loc_indirect(ll) && Is_global(ta);
  1155. X    }
  1156. X    else if (Is_trimloc(l)) {
  1157. X        interr(DEL_TRIM_TARGET);
  1158. X        return No;
  1159. X    }
  1160. X    else if (Is_compound(l)) {
  1161. X        intlet k, len= Nfields(l);
  1162. X        k_Overfields { if (!l_exists(*Field(l, k))) return No; }
  1163. X        return Yes;
  1164. X    }
  1165. X    else if (Is_tbseloc(l)) {
  1166. X        tbseloc *tl= Tbseloc(l);
  1167. X        value *ll;
  1168. X        value lv= locvalue(tl->R, &ll, Yes);
  1169. X        if (still_ok) {
  1170. X            if (!Is_table(lv))
  1171. X                interr(SEL_NO_TABLE);
  1172. X            else
  1173. X                return in_keys(tl->K, lv);
  1174. X        }
  1175. X        return No;
  1176. X    }
  1177. X    else {
  1178. X        interr(DEL_NO_TARGET);
  1179. X        return No;
  1180. X    }
  1181. X}
  1182. X
  1183. X/* Delete a location if it exists */
  1184. X
  1185. XVisible Procedure l_del(l) loc l; {
  1186. X    if (Is_simploc(l)) {
  1187. X        simploc *sl= Simploc(l);
  1188. X        e_delete(&(sl->e->tab), sl->i);
  1189. X        if (sl->e == prmnv)
  1190. X            del_target(sl->i);
  1191. X    }
  1192. X    else if (Is_trimloc(l)) {
  1193. X        interr(DEL_TRIM_TARGET);
  1194. X    }
  1195. X    else if (Is_compound(l)) {
  1196. X        intlet k, len= Nfields(l);
  1197. X        k_Overfields { l_del(*Field(l, k)); }
  1198. X    }
  1199. X    else if (Is_tbseloc(l)) {
  1200. X        tbseloc *tl= Tbseloc(l);
  1201. X        value *ll, lv;
  1202. X        uniquify(tl->R);
  1203. X        if (still_ok) {
  1204. X            lv= locvalue(tl->R, &ll, Yes);
  1205. X            if (in_keys(tl->K, lv)) {
  1206. X                rm_indirection(tl->R);
  1207. X                delete(ll, tl->K);
  1208. X            }
  1209. X        }
  1210. X    }
  1211. X    else interr(DEL_NO_TARGET);
  1212. X}
  1213. X
  1214. XVisible Procedure l_delete(l) loc l; {
  1215. X    if (l_exists(l)) l_del(l);
  1216. X    else interr(MESS(3623, "deleting non-existent location"));
  1217. X}
  1218. X
  1219. XVisible Procedure l_insert(v, l) value v; loc l; {
  1220. X    value *ll, lv;
  1221. X    uniquify(l);
  1222. X    if (still_ok) {
  1223. X        lv= locvalue(l, &ll, Yes);
  1224. X        if (!Is_list(lv))
  1225. X            interr(INS_NO_LIST);
  1226. X        else {
  1227. X            rm_indirection(l);
  1228. X            insert(v, ll);
  1229. X        }
  1230. X    }
  1231. X}
  1232. X
  1233. XVisible Procedure l_remove(v, l) value v; loc l; {
  1234. X    value *ll, lv;
  1235. X    uniquify(l);
  1236. X    if (still_ok) {
  1237. X        lv= locvalue(l, &ll, Yes);
  1238. X        if (!Is_list(lv))
  1239. X            interr(REM_NO_LIST);
  1240. X        else if (empty(lv))
  1241. X            interr(REM_EMPTY_LIST);
  1242. X        else {
  1243. X            rm_indirection(l);
  1244. X            remove(v, ll);
  1245. X        }
  1246. X    }
  1247. X}
  1248. X
  1249. XVisible Procedure bind(l) loc l; {
  1250. X    if (*bndtgs != Vnil) {
  1251. X        if (Is_simploc(l)) {
  1252. X            simploc *ll= Simploc(l);
  1253. X            if (!in(ll->i, *bndtgs)) /* kludge */ /* what for? */
  1254. X                insert(ll->i, bndtgs);
  1255. X        }
  1256. X        else if (Is_compound(l)) {
  1257. X            intlet k, len= Nfields(l);
  1258. X            k_Overfields { bind(*Field(l, k)); }
  1259. X        }
  1260. X        else interr(MESS(3624, "binding non-location"));
  1261. X    }
  1262. X    l_del(l);
  1263. X}
  1264. X
  1265. XVisible Procedure unbind(l) loc l; {
  1266. X    if (*bndtgs != Vnil) {
  1267. X        if (Is_simploc(l)) {
  1268. X            simploc *ll= Simploc(l);
  1269. X            if (in(ll->i, *bndtgs))
  1270. X                remove(ll->i, bndtgs);
  1271. X        }
  1272. X        else if (Is_compound(l)) {
  1273. X            intlet k, len= Nfields(l);
  1274. X            k_Overfields { unbind(*Field(l, k)); }
  1275. X        }
  1276. X        else interr(MESS(3625, "unbinding non-location"));
  1277. X    }
  1278. X    l_del(l);
  1279. X}
  1280. END_OF_FILE
  1281.   if test 11448 -ne `wc -c <'abc/bint3/i3loc.c'`; then
  1282.     echo shar: \"'abc/bint3/i3loc.c'\" unpacked with wrong size!
  1283.   fi
  1284.   # end of 'abc/bint3/i3loc.c'
  1285. fi
  1286. if test -f 'abc/bint3/i3scr.c' -a "${1}" != "-c" ; then 
  1287.   echo shar: Will not clobber existing file \"'abc/bint3/i3scr.c'\"
  1288. else
  1289.   echo shar: Extracting \"'abc/bint3/i3scr.c'\" \(12005 characters\)
  1290.   sed "s/^X//" >'abc/bint3/i3scr.c' <<'END_OF_FILE'
  1291. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  1292. X
  1293. X/* B input/output handling */
  1294. X
  1295. X#include "b.h"
  1296. X#include "bint.h"
  1297. X#include "feat.h"
  1298. X#include "bmem.h"
  1299. X#include "bobj.h"
  1300. X#include "bcom.h"
  1301. X#include "i2nod.h"
  1302. X#include "i2par.h"
  1303. X#include "i3typ.h"
  1304. X#include "i3env.h"
  1305. X#include "i3in2.h"
  1306. X#include "i3scr.h"
  1307. X
  1308. X#ifdef SETJMP
  1309. X#include <setjmp.h>
  1310. X#endif
  1311. X
  1312. XVisible bool interactive;
  1313. XVisible bool rd_interactive;
  1314. XVisible value iname= Vnil;    /* input name */
  1315. XVisible bool outeractive;
  1316. XVisible bool at_nwl= Yes;    /*Yes if currently at the start of an output line*/
  1317. XHidden bool last_was_text= No;    /*Yes if last value written was a text*/
  1318. X
  1319. XVisible bool Eof;
  1320. XHidden FILE *ofile= stdout;
  1321. XVisible FILE *ifile;         /* input file */
  1322. XVisible FILE *sv_ifile;        /* copy of ifile for restoring after reading unit */
  1323. X
  1324. XVisible bool readIcontext= No;
  1325. X#ifdef SETJMP
  1326. XVisible jmp_buf readIinterrupt;
  1327. X#endif
  1328. X
  1329. X/******************************* Output *******************************/
  1330. X
  1331. XHidden int ocol;    /* Current output column */
  1332. X
  1333. XHidden Procedure putch(c) char c; {
  1334. X    if (still_ok) {
  1335. X        putchr(ofile, c);
  1336. X        if (c == '\n') { at_nwl= Yes; ocol= 0; }
  1337. X        else {
  1338. X            if (at_nwl) { ocol= 0; at_nwl= No;}
  1339. X            ++ocol;
  1340. X        }
  1341. X    }
  1342. X}
  1343. X
  1344. XVisible Procedure newline() {
  1345. X    putch('\n');
  1346. X    fflush(ofile);
  1347. X}
  1348. X
  1349. XVisible Procedure oline() {
  1350. X    if (!at_nwl) newline();
  1351. X}
  1352. X
  1353. XVisible Procedure wri_space() {
  1354. X    putch(' ');
  1355. X}
  1356. X
  1357. XVisible Procedure writ(v) value v; {
  1358. X    wri(v, No, Yes, No);
  1359. X    fflush(ofile);
  1360. X}
  1361. X
  1362. X#define Putch_sp() {if (!perm) putch(' ');}
  1363. X
  1364. XHidden int intsize(v) value v; {
  1365. X    value s= size(v); int len=0;
  1366. X    if (large(s)) interr(MESS(3800, "value too big to output"));
  1367. X    else len= intval(s);
  1368. X    release(s);
  1369. X    return len;
  1370. X}
  1371. X
  1372. XHidden bool lwt;
  1373. X
  1374. X#ifdef RANGEPRINT
  1375. XHidden Procedure wri_vals(l, u) value l, u; {
  1376. X    if (compare(l, u) == 0)
  1377. X        wri(l, No, No, No);
  1378. X    else if (is_increment(u, l)) {
  1379. X        wri(l, No, No, No);
  1380. X        putch(';'); putch(' ');
  1381. X        wri(u, No, No, No);
  1382. X    }
  1383. X    else {
  1384. X        wri(l, No, No, No);
  1385. X        putch('.'); putch('.');
  1386. X        wri(u, No, No, No);
  1387. X    }
  1388. X}
  1389. X#endif /* RANGEPRINT */
  1390. X
  1391. XVisible Procedure wri(v, coll, outer, perm) value v; bool coll, outer, perm; {
  1392. X    if (outer && !at_nwl && (!Is_text(v) || !last_was_text)
  1393. X            && (!Is_compound(v) || !coll)) putch(' ');
  1394. X    lwt= No;
  1395. X    if (Is_number(v)) {
  1396. X        if (perm) printnum(ofile, v);
  1397. X        else {
  1398. X            string cp= convnum(v);
  1399. X            while(*cp && still_ok) putch(*cp++);
  1400. X        }
  1401. X    } else if (Is_text(v)) {
  1402. X        wrtext(putch, v, outer ? '\0' : '"');
  1403. X        lwt= outer;
  1404. X    } else if (Is_compound(v)) {
  1405. X        intlet k, len= Nfields(v);
  1406. X        if (!coll) putch('(');
  1407. X        for (k=0; k<len && still_ok; k++) {
  1408. X            wri(*Field(v, k), No, No, perm);
  1409. X            if (!Lastfield(k)) {
  1410. X                putch(',');
  1411. X                Putch_sp();
  1412. X            }
  1413. X        }
  1414. X        if (!coll) putch(')');
  1415. X    } else if (Is_list(v) || Is_ELT(v)) {
  1416. X        putch('{');
  1417. X#ifndef RANGEPRINT
  1418. X        if (perm && is_rangelist(v)) {
  1419. X            value vm;
  1420. X            wri(vm=min1(v), No, No, perm);
  1421. X            release(vm);
  1422. X            putch('.'); putch('.');
  1423. X            wri(vm=max1(v), No, No, perm);
  1424. X            release(vm);
  1425. X        }
  1426. X        else {
  1427. X            value i, s, vi;
  1428. X            relation c;
  1429. X            
  1430. X            i= copy(one); s= size(v);
  1431. X            while((c= numcomp(i, s)) <= 0 && !Interrupted()) {
  1432. X                vi= item(v, i);
  1433. X                wri(vi, No, No, perm);
  1434. X                if (c < 0) {
  1435. X                    putch(';'); putch(' ');
  1436. X                }
  1437. X                release(vi);
  1438. X                i= sum(vi=i, one);
  1439. X                release(vi);
  1440. X            }
  1441. X            release(i); release(s);
  1442. X        }
  1443. X#else /* RANGEPRINT */
  1444. X        if (is_rangelist(v)) {
  1445. X            value vm;
  1446. X            wri(vm=min1(v), No, No, perm);
  1447. X            release(vm);
  1448. X            putch('.'); putch('.');
  1449. X            wri(vm=max1(v), No, No, perm);
  1450. X            release(vm);
  1451. X        }
  1452. X        else if (!perm) {
  1453. X            value i, s, vi, lwb, upb;
  1454. X            bool first= Yes;
  1455. X            i= copy(one); s= size(v);
  1456. X            while (numcomp(i, s) <= 0 && !Interrupted()) {
  1457. X                vi= item(v, i);
  1458. X                if (first) {
  1459. X                    lwb= copy(vi);
  1460. X                    upb= copy(vi);
  1461. X                    first= No;
  1462. X                }
  1463. X                else if (is_increment(vi, upb)) {
  1464. X                    release(upb);
  1465. X                    upb= copy(vi);
  1466. X                }
  1467. X                else {
  1468. X                    wri_vals(lwb, upb) ;
  1469. X                    putch(';'); putch(' ');
  1470. X                    release(lwb); release(upb);
  1471. X                    lwb= copy(vi); upb= copy(vi);
  1472. X                }
  1473. X                release(vi);
  1474. X                i= sum(vi=i, one);
  1475. X                release(vi);
  1476. X            }
  1477. X            if (!first) {
  1478. X                wri_vals(lwb, upb);
  1479. X                release(lwb); release(upb);
  1480. X            }
  1481. X            release(i); release(s);
  1482. X        }
  1483. X        else {
  1484. X            value ve; int k, len= intsize(v);
  1485. X            for (k=0; k<len && still_ok; k++) {
  1486. X                wri(ve= thof(k+1, v), No, No, perm);
  1487. X                release(ve);
  1488. X                if (k < len - 1) {
  1489. X                    putch(';');
  1490. X                    Putch_sp();
  1491. X                }
  1492. X            }
  1493. X        }
  1494. X#endif
  1495. X        putch('}');
  1496. X    } else if (Is_table(v)) {
  1497. X        int k, len= intsize(v);
  1498. X        putch('{');
  1499. X        for (k=0; k<len && still_ok; k++) {
  1500. X            putch('['); wri(*key(v, k), Yes, No, perm);
  1501. X            putch(']'); putch(':'); Putch_sp();
  1502. X            wri(*assoc(v, k), No, No, perm);
  1503. X            if (k < len - 1) {
  1504. X                putch(';');
  1505. X                Putch_sp();
  1506. X            }
  1507. X        }
  1508. X        putch('}');
  1509. X    } else {
  1510. X        if (testing) { putch('?'); putch(Type(v)); putch('?'); }
  1511. X        else syserr(MESS(3801, "writing value of unknown type"));
  1512. X    }
  1513. X    last_was_text= lwt;
  1514. X    if (interrupted) clearerr(ofile); /* needed for MSDOS 
  1515. X                       * harmless for unix ???
  1516. X                       */
  1517. X}
  1518. X
  1519. X/***************************** Input ****************************************/
  1520. X
  1521. X/* Read a line; EOF only allowed if not interactive, in which case eof set */
  1522. X/* Returns the line input                                                  */
  1523. X/* This is the only place where a long jump is necessary                   */
  1524. X/* In other places, interrupts are just like procedure calls, and checks   */
  1525. X/* of still_ok and interrupted suffice: eventually the stack unwinds to the*/
  1526. X/* main loop in imm_command(). Here though, an interrupt must actually     */
  1527. X/* terminate the read. Hence the bool readIcontext indicating if the     */
  1528. X/* long jump is necessary or not                                           */
  1529. X
  1530. X#define Mixed_stdin_file (!rd_interactive && sv_ifile == stdin)
  1531. X
  1532. XHidden bufadm i_buf, o_buf;
  1533. Xextern bool i_looked_ahead;
  1534. X
  1535. XHidden char *read_line(kind, should_prompt, eof)
  1536. X    literal kind;
  1537. X    bool should_prompt, *eof;
  1538. X{
  1539. X    bufadm *bp= (kind == R_cmd && ifile == sv_ifile) ? &i_buf : &o_buf;
  1540. X    FILE *fp= (kind == R_cmd || kind == R_ioraw) ? ifile : stdin;
  1541. X    
  1542. X    bufreinit(bp);
  1543. X    *eof= No;
  1544. X    
  1545. X#ifdef SETJMP
  1546. X    if (setjmp(readIinterrupt) != 0) {
  1547. X        readIcontext= No;
  1548. X        return bp->buf;
  1549. X    }
  1550. X#endif
  1551. X    if ((kind == R_expr || kind == R_raw)
  1552. X        && Mixed_stdin_file && i_looked_ahead)
  1553. X    {
  1554. X        /* e.g. "abc <mixed_commands_and_input_for_READs_on_file" */
  1555. X        /* ilev looked_ahead for command following suite */
  1556. X        /* and ate a line meant for a READ command */
  1557. X        bufcpy(bp, i_buf.buf);
  1558. X        i_looked_ahead= No;
  1559. X    }
  1560. X    else if (!should_prompt) {
  1561. X        if (!fileline(fp, bp))
  1562. X            *eof= Yes;
  1563. X    }
  1564. X    else if (cmdline(kind, bp, (at_nwl ? 0 : ocol))) {
  1565. X        if (outeractive) at_nwl= Yes;
  1566. X    }
  1567. X    return bp->buf;
  1568. X}
  1569. X
  1570. X#define LINESIZE 200
  1571. X
  1572. XHidden bool fileline(fp, bp) FILE *fp; bufadm *bp; {
  1573. X    char line[LINESIZE];
  1574. X    char *pline;
  1575. X
  1576. X    for (;;) {
  1577. X        readIcontext= Yes;
  1578. X        pline= fgets(line, LINESIZE, fp);
  1579. X        readIcontext= No;
  1580. X        if (pline == NULL) {
  1581. X            bufcpy(bp, "\n");
  1582. X            if (*(bp->buf) == '\n')
  1583. X                return No;
  1584. X            clearerr(fp);
  1585. X            return Yes;
  1586. X        }
  1587. X        bufcpy(bp, line);
  1588. X        if (strchr(line, '\n') != NULL)
  1589. X            return Yes;
  1590. X    }
  1591. X}
  1592. X
  1593. XHidden Procedure init_read() {
  1594. X    bufinit(&i_buf);
  1595. X    bufinit(&o_buf);
  1596. X    bufcpy(&o_buf, "\n");
  1597. X    tx= (txptr) o_buf.buf;
  1598. X}
  1599. X
  1600. XHidden Procedure end_read() {
  1601. X    buffree(&i_buf);
  1602. X    buffree(&o_buf);
  1603. X}
  1604. X
  1605. X/****************************************************************************/
  1606. X
  1607. X#define ANSWER        MESS(3802, "*** Please answer with '%c' or '%c'\n")
  1608. X#define JUST_YES_OR_NO    MESS(3803, "*** Just '%c' or '%c', please\n")
  1609. X#define LAST_CHANCE    MESS(3804, "*** This is your last chance. Take it. I really don't know what you want.\n    So answer the question\n")
  1610. X#define NO_THEN        MESS(3805, "*** Well, I shall assume that your refusal to answer the question means '%c'!\n")
  1611. X
  1612. X/* Rather over-fancy routine to ask the user a question */
  1613. X/* Will anybody discover that you're only given 4 chances? */
  1614. X
  1615. XVisible char q_answer(m, c1, c2, c3) int m; char c1, c2, c3; {
  1616. X    char answer; intlet try; txptr tp; bool eof;
  1617. X    
  1618. X    if (!interactive)
  1619. X        return c1;
  1620. X    if (outeractive)
  1621. X        oline();
  1622. X    for (try= 1; try<=4; try++){
  1623. X        if (try == 1 || try == 3)
  1624. X            q_mess(m, c1, c2);
  1625. X        tp= (txptr) read_line(R_answer, Yes, &eof);
  1626. X        if (interrupted) {
  1627. X            interrupted= No;
  1628. X            if (c3 == '\0') {
  1629. X                still_ok= Yes;
  1630. X                q_mess(NO_THEN, c2, c1);
  1631. X                break;
  1632. X            }
  1633. X            else {
  1634. X                return c3;
  1635. X            }
  1636. X        }
  1637. X        skipsp(&tp);
  1638. X        answer= Char(tp);
  1639. X        if (answer == c1)
  1640. X            return c1;
  1641. X        if (answer == c2)
  1642. X            return c2;
  1643. X        if (outeractive)
  1644. X            oline();
  1645. X        if (try == 1)
  1646. X            q_mess(ANSWER, c1, c2);
  1647. X        else if (try == 2)
  1648. X            q_mess(JUST_YES_OR_NO, c1, c2);
  1649. X        else if (try == 3)
  1650. X            q_mess(LAST_CHANCE, c1, c2);
  1651. X        else 
  1652. X            q_mess(NO_THEN, c2, c1);
  1653. X    } /* end for */
  1654. X    return c2;
  1655. X}
  1656. X
  1657. XHidden Procedure q_mess(m, c1, c2) int m; char c1, c2; {
  1658. X    put2Cmess(errfile, m, c1, c2);
  1659. X    fflush(errfile);
  1660. X}
  1661. X
  1662. XVisible bool is_intended(m) int m; {
  1663. X    char c1, c2;
  1664. X
  1665. X#ifdef FRENCH
  1666. X    c1= 'o'; c2= 'n';
  1667. X#else /* ENGLISH */
  1668. X    c1= 'y'; c2= 'n';
  1669. X#endif
  1670. X    return q_answer(m, c1, c2, (char)'\0') == c1 ? Yes : No;
  1671. X}
  1672. X
  1673. X#define EG_EOF        MESS(3806, "End of input encountered during READ command")
  1674. X#define RAW_EOF        MESS(3807, "End of input encountered during READ t RAW")
  1675. X#define EG_INCOMP    MESS(3808, "type of expression does not agree with that of EG sample")
  1676. X#define TRY_AGAIN    MESS(3809, "*** Please try again\n")
  1677. X
  1678. X/* Read_eg uses evaluation but it shouldn't.
  1679. X   Wait for a more general mechanism. */
  1680. X
  1681. XVisible Procedure read_eg(l, t) loc l; btype t; {
  1682. X    context c; parsetree code;
  1683. X    parsetree r= NilTree; value rv= Vnil; btype rt= Vnil;
  1684. X    envtab svprmnvtab= Vnil;
  1685. X    txptr fcol_save= first_col, tx_save= tx;
  1686. X    do {
  1687. X        still_ok= Yes;
  1688. X        sv_context(&c);
  1689. X        if (cntxt != In_read) {
  1690. X            release(read_context.uname);
  1691. X            sv_context(&read_context);
  1692. X        }
  1693. X        svprmnvtab= prmnvtab == Vnil ? Vnil : prmnv->tab;
  1694. X        /* save scratch-pad copy because of following setprmnv() */
  1695. X        setprmnv();
  1696. X        cntxt= In_read;
  1697. X        first_col= tx= (txptr) read_line(R_expr, rd_interactive, &Eof);
  1698. X        if (still_ok && Eof) interr(EG_EOF);
  1699. X        if (!rd_interactive) {
  1700. X            if (sv_ifile == stdin)
  1701. X                f_lino++;
  1702. X            else
  1703. X                i_lino++;
  1704. X        }
  1705. X        rt= Vnil;
  1706. X        if (still_ok) {
  1707. X            findceol();
  1708. X            r= expr(ceol);
  1709. X            if (still_ok) fix_nodes(&r, &code);
  1710. X            rv= evalthread(code); release(r);
  1711. X            if (still_ok) rt= valtype(rv);
  1712. X        }
  1713. X        if (svprmnvtab != Vnil) {
  1714. X            prmnvtab= prmnv->tab;
  1715. X            prmnv->tab= svprmnvtab;
  1716. X        }
  1717. X        if (still_ok) must_agree(t, rt, EG_INCOMP);
  1718. X        set_context(&c);
  1719. X        release(rt);
  1720. X        if (!still_ok && rd_interactive && !interrupted)
  1721. X            putmess(errfile, TRY_AGAIN);
  1722. X    } while (!interrupted && !still_ok && rd_interactive);
  1723. X    if (still_ok) put(rv, l);
  1724. X    first_col= fcol_save;
  1725. X    tx= tx_save;
  1726. X    release(rv);
  1727. X}
  1728. X
  1729. XVisible Procedure read_raw(l) loc l; {
  1730. X    value r; bool eof;
  1731. X    txptr text= (txptr) read_line(R_raw, rd_interactive, &eof);
  1732. X    if (still_ok && eof)
  1733. X        interr(RAW_EOF);
  1734. X    if (!rd_interactive) {
  1735. X        if (sv_ifile == stdin)
  1736. X            f_lino++;
  1737. X        else
  1738. X            i_lino++;
  1739. X    }
  1740. X    if (still_ok) {
  1741. X        txptr rp= text;
  1742. X        while (*rp != '\n') rp++;
  1743. X        *rp= '\0';
  1744. X        r= mk_text(text);
  1745. X        put(r, l);
  1746. X        release(r);
  1747. X    }
  1748. X}
  1749. X
  1750. XVisible bool io_exit;
  1751. X
  1752. XVisible bool read_ioraw(v) value *v; { /* returns Yes if end of input */
  1753. X    txptr text, rp;
  1754. X    bool eof;
  1755. X    
  1756. X    *v= Vnil;
  1757. X    io_exit= No;
  1758. X    text= (txptr) read_line(R_ioraw, rd_interactive, &eof);
  1759. X    if (eof || interrupted || !still_ok)
  1760. X        return Yes;
  1761. X    rp= text;
  1762. X    while (*rp != '\n')
  1763. X        rp++;
  1764. X    *rp= '\0';
  1765. X    if (strlen(text) > 0 || !io_exit)
  1766. X        *v= mk_text(text);
  1767. X    return io_exit;
  1768. X}
  1769. X
  1770. XVisible char *getline() {
  1771. X    bool should_prompt=
  1772. X        interactive && ifile == sv_ifile;
  1773. X    return read_line(R_cmd, should_prompt, &Eof);
  1774. X}
  1775. X
  1776. X/******************************* Files ******************************/
  1777. X
  1778. XVisible Procedure redirect(of) FILE *of; {
  1779. X    static bool woa= No, wnwl= No;    /*was outeractive, was at_nwl */
  1780. X    ofile= of;
  1781. X    if (of == stdout) {
  1782. X        outeractive= woa;
  1783. X        at_nwl= wnwl;
  1784. X    } else {
  1785. X        woa= outeractive; outeractive= No;
  1786. X        wnwl= at_nwl; at_nwl= Yes;
  1787. X    }
  1788. X}
  1789. X
  1790. XVisible Procedure vs_ifile() {
  1791. X    ifile= sv_ifile;
  1792. X}
  1793. X
  1794. XVisible Procedure re_screen() {
  1795. X    sv_ifile= ifile;
  1796. X    interactive= f_interactive(ifile);
  1797. X    Eof= No;
  1798. X}
  1799. X
  1800. X/* initscr is a reserved name of CURSES */
  1801. XVisible Procedure init_scr() {
  1802. X    outeractive= f_interactive(stdout);
  1803. X    rd_interactive= f_interactive(stdin);
  1804. X    init_read();
  1805. X}
  1806. X
  1807. XVisible Procedure end_scr() {
  1808. X    end_read();
  1809. X}
  1810. END_OF_FILE
  1811.   if test 12005 -ne `wc -c <'abc/bint3/i3scr.c'`; then
  1812.     echo shar: \"'abc/bint3/i3scr.c'\" unpacked with wrong size!
  1813.   fi
  1814.   # end of 'abc/bint3/i3scr.c'
  1815. fi
  1816. if test -f 'abc/mkconfig.c' -a "${1}" != "-c" ; then 
  1817.   echo shar: Will not clobber existing file \"'abc/mkconfig.c'\"
  1818. else
  1819.   echo shar: Extracting \"'abc/mkconfig.c'\" \(12184 characters\)
  1820.   sed "s/^X//" >'abc/mkconfig.c' <<'END_OF_FILE'
  1821. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  1822. X
  1823. X/* Generate constants for configuration file            */
  1824. X
  1825. X#include "osconf.h"
  1826. X
  1827. X/* If your C system is not unix but does have signal/setjmp,    */
  1828. X/*    add a #define unix                    */
  1829. X/* You may also need to add some calls to signal().        */
  1830. X
  1831. X#ifdef unix
  1832. X
  1833. X#define SIGNAL
  1834. X
  1835. X#include <signal.h>
  1836. X#include <setjmp.h>
  1837. X
  1838. X    jmp_buf lab;
  1839. X    overflow(sig) int sig; { /* what to do on overflow/underflow */
  1840. X        signal(sig, overflow);
  1841. X        longjmp(lab, 1);
  1842. X    }
  1843. X
  1844. X#else
  1845. X    /* Dummy routines instead */
  1846. X    int lab=1;
  1847. X    int setjmp(lab) int lab; { return(0); }
  1848. X
  1849. X#endif
  1850. X
  1851. X#define absval(x) (((x)<0.0)?(-x):(x))
  1852. X#define min(x,y) (((x)<(y))?(x):(y))
  1853. X
  1854. X/* These routines are intended to defeat any attempt at optimisation */
  1855. XDstore(a, b) double a, *b; { *b=a; }
  1856. Xdouble Dsum(a, b) double a, b; { double r; Dstore(a+b, &r); return (r); }
  1857. Xdouble Ddiff(a, b) double a, b; { double r; Dstore(a-b, &r); return (r); }
  1858. Xdouble Dmul(a, b) double a, b; { double r; Dstore(a*b, &r); return (r); }
  1859. Xdouble Ddiv(a, b) double a, b; { double r; Dstore(a/b, &r); return (r); }
  1860. X
  1861. Xdouble power(x, n) int x, n; {
  1862. X    double r=1.0;
  1863. X    for (;n>0; n--) r*=x;
  1864. X    return r;
  1865. X}
  1866. X
  1867. Xint floor_log(base, x) int base; double x; { /* return floor(log base(x)) */
  1868. X    int r=0;
  1869. X    while (x>=base) { r++; x/=base; }
  1870. X    return r;
  1871. X}
  1872. X
  1873. Xint ceil_log(base, x) int base; double x; {
  1874. X    int r=0;
  1875. X    while (x>1.0) { r++; x/=base; }
  1876. X    return r;
  1877. X}
  1878. X
  1879. X/*     The following is ABC specific.                */
  1880. X/*     It tries to prevent different alignments for the field    */
  1881. X/*    following common HEADER fields in various structures    */
  1882. X/*    used by the ABC system for different types of values.    */
  1883. X
  1884. X/* literal and reftype are in ?hdrs/osconf.h */
  1885. Xtypedef short intlet;
  1886. X#define HEADER literal type; reftype refcnt; intlet len
  1887. Xtypedef struct header { HEADER; } header;
  1888. Xtypedef struct value { HEADER; char **cts;} value;
  1889. X
  1890. X
  1891. Xmain(argc, argv) int argc; char *argv[]; {
  1892. X    char c;
  1893. X    short newshort, maxshort, maxershort;
  1894. X    int newint, maxint, maxdigit, shortbits, bits, mantbits,
  1895. X        *p, shortpower, intpower, longpower;
  1896. X    long newlong, maxlong;
  1897. X#ifdef MEMSIZE
  1898. X    long count;
  1899. X#endif
  1900. X    unsigned long nfiller;
  1901. X    int i, ibase, iexp, irnd, imant, iz, k, machep, maxexp, minexp,
  1902. X        mx, negeps, tendigs;
  1903. X    double a, b, base, basein, basem1, eps, epsneg, xmax, newxmax,
  1904. X           xmin, xminner, y, y1, z, z1, z2;
  1905. X
  1906. X    double BIG, Maxreal;
  1907. X    int BASE, MAXNUMDIG, tenlogBASE, Maxexpo, Minexpo, DBLBITS, LONGBITS;
  1908. X
  1909. X#ifdef SIGNAL
  1910. X    signal(SIGFPE, overflow);
  1911. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  1912. X#endif
  1913. X
  1914. X/****** Calculate max short *********************************************/
  1915. X/*      Calculate 2**n-1 until overflow - then use the previous value    */
  1916. X
  1917. X    newshort=1; maxshort=0;
  1918. X
  1919. X    if (setjmp(lab)==0)
  1920. X        for(shortpower=0; newshort>maxshort; shortpower++) {
  1921. X            maxshort=newshort;
  1922. X            newshort=newshort*2+1;
  1923. X        }
  1924. X
  1925. X    /* Now for those daft Cybers: */
  1926. X
  1927. X    maxershort=0; newshort=maxshort;
  1928. X
  1929. X    if (setjmp(lab)==0)
  1930. X        for(shortbits=shortpower; newshort>maxershort; shortbits++) {
  1931. X            maxershort=newshort;
  1932. X            newshort=newshort+newshort+1;
  1933. X        }
  1934. X
  1935. X    bits= (shortbits+1)/sizeof(short);
  1936. X    c= (char)(-1);
  1937. X    printf("/\* char=%d bits, %ssigned *\/\n", sizeof(c)*bits,
  1938. X            ((int)c)<0?"":"un");
  1939. X    printf("/\* maxshort=%d (=2**%d-1) *\/\n", maxshort, shortpower);
  1940. X
  1941. X    if (maxershort>maxshort) {
  1942. X        printf("/\* There is a larger maxshort, %d (=2**%d-1), %s *\/\n",
  1943. X            maxershort, shortbits, 
  1944. X            "but only for addition, not multiplication");
  1945. X    }
  1946. X
  1947. X/****** Calculate max int by the same method ***************************/
  1948. X
  1949. X    newint=1; maxint=0;
  1950. X
  1951. X    if (setjmp(lab)==0)
  1952. X        for(intpower=0; newint>maxint; intpower++) {
  1953. X            maxint=newint;
  1954. X            newint=newint*2+1;
  1955. X        }
  1956. X
  1957. X    printf("/\* maxint=%d (=2**%d-1) *\/\n", maxint, intpower);
  1958. X
  1959. X/****** Calculate max long by the same method ***************************/
  1960. X
  1961. X    newlong=1; maxlong=0;
  1962. X
  1963. X    if (setjmp(lab)==0)
  1964. X        for(longpower=0; newlong>maxlong; longpower++) {
  1965. X            maxlong=newlong;
  1966. X            newlong=newlong*2+1;
  1967. X        }
  1968. X
  1969. X    if (setjmp(lab)!=0) { printf("\nUnexpected under/overflow\n"); exit(1); }
  1970. X
  1971. X    printf("/\* maxlong=%ld (=2**%d-1) *\/\n", maxlong, longpower);
  1972. X
  1973. X/****** Pointers ********************************************************/
  1974. X    printf("/\* pointers=%d bits%s *\/\n", sizeof(p)*bits,
  1975. X        sizeof(p)>sizeof(int)?" BEWARE! larger than int!":"");
  1976. X
  1977. X/****** Base and size of mantissa ***************************************/
  1978. X    a=1.0;
  1979. X    do { a=Dsum(a, a); } while (Ddiff(Ddiff(Dsum(a, 1.0), a), 1.0) == 0.0);
  1980. X    b=1.0;
  1981. X    do { b=Dsum(b, b); } while ((base=Ddiff(Dsum(a, b), a)) == 0.0);
  1982. X    ibase=base;
  1983. X    printf("/\* base=%d *\/\n", ibase);
  1984. X
  1985. X    imant=0; b=1.0;
  1986. X    do { imant++; b=Dmul(b, base); }
  1987. X    while (Ddiff(Ddiff(Dsum(b,1.0),b),1.0) == 0.0);
  1988. X    printf("/\* Significant base digits=%d *\/\n", imant);
  1989. X    tendigs= ceil_log(10, b); /* the number of digits */
  1990. X
  1991. X/****** Various flavours of epsilon *************************************/
  1992. X    basem1=Ddiff(base,1.0);
  1993. X    if (Ddiff(Dsum(a, basem1), a) != 0.0) irnd=1; 
  1994. X    else irnd=0;
  1995. X
  1996. X    negeps=imant+imant;
  1997. X    basein=1.0/base;
  1998. X    a=1.0;
  1999. X    for(i=1; i<=negeps; i++) a*=basein;
  2000. X
  2001. X    b=a;
  2002. X    while (Ddiff(Ddiff(1.0, a), 1.0) == 0.0) {
  2003. X        a*=base;
  2004. X        negeps--;
  2005. X    }
  2006. X    negeps= -negeps;
  2007. X    printf("/\* Smallest x such that 1.0-base**x != 1.0=%d *\/\n", negeps);
  2008. X
  2009. X    epsneg=a;
  2010. X    if ((ibase!=2) && (irnd==1)) {
  2011. X    /*    a=(a*(1.0+a))/(1.0+1.0); => */
  2012. X        a=Ddiv(Dmul(a, Dsum(1.0, a)), Dsum(1.0, 1.0));
  2013. X    /*    if ((1.0-a)-1.0 != 0.0) epsneg=a; => */
  2014. X        if (Ddiff(Ddiff(1.0, a), 1.0) != 0.0) epsneg=a;
  2015. X    }
  2016. X    printf("/\* Small x such that 1.0-x != 1.0=%g *\/\n", epsneg);
  2017. X    /* it may not be the smallest */
  2018. X
  2019. X    machep= -imant-imant;
  2020. X    a=b;
  2021. X    while (Ddiff(Dsum(1.0, a), 1.0) == 0.0) { a*=base; machep++; }
  2022. X    printf("/\* Smallest x such that 1.0+base**x != 1.0=%d *\/\n", machep);
  2023. X
  2024. X    eps=a;
  2025. X    if ((ibase!=2) && (irnd==1)) {
  2026. X    /*    a=(a*(1.0+a))/(1.0+1.0); => */
  2027. X        a=Ddiv(Dmul(a, Dsum(1.0, a)), Dsum(1.0, 1.0));
  2028. X    /*    if ((1.0+a)-1.0 != 0.0) eps=a; => */
  2029. X        if (Ddiff(Dsum(1.0, a), 1.0) != 0.0) eps=a;
  2030. X    }
  2031. X    printf("/\* Smallest x such that 1.0+x != 1.0=%g *\/\n", eps);
  2032. X
  2033. X/****** Round or chop ***************************************************/
  2034. X    if (irnd == 1) { printf("/\* Arithmetic rounds *\/\n"); }
  2035. X    else { 
  2036. X        printf("/\* Arithmetic chops");
  2037. X        if (Ddiff(Dmul(Dsum(1.0,eps),1.0),1.0) != 0.0) {
  2038. X            printf(" but uses guard digits");
  2039. X        }
  2040. X        printf(" *\/\n");
  2041. X    }
  2042. X
  2043. X/****** Size of and minimum normalised exponent ****************************/
  2044. X    y=0; i=0; k=1; z=basein; z1=(1.0+eps)/base;
  2045. X
  2046. X    /* Coarse search for the largest power of two */
  2047. X    if (setjmp(lab)==0) /* in case of underflow trap */
  2048. X        do {
  2049. X            y=z; y1=z1;
  2050. X            z=Dmul(y,y); z1=Dmul(z1, y);
  2051. X            a=Dmul(z,1.0);
  2052. X            z2=Ddiv(z1,y);
  2053. X            if (z2 != y1) break;
  2054. X            if ((Dsum(a,a) == 0.0) || (absval(z) >= y)) break;
  2055. X            i++;
  2056. X            k+=k;
  2057. X        } while(1);
  2058. X
  2059. X    if (ibase != 10) {
  2060. X        iexp=i+1; /* for the sign */
  2061. X        mx=k+k;
  2062. X    } else {
  2063. X        iexp=2;
  2064. X        iz=ibase;
  2065. X        while (k >= iz) { iz*=ibase; iexp++; }
  2066. X        mx=iz+iz-1;
  2067. X    }
  2068. X
  2069. X    /* Fine tune starting with y and y1 */
  2070. X    if (setjmp(lab)==0) /* in case of underflow trap */
  2071. X        do {
  2072. X            xmin=y; z1=y1;
  2073. X            y=Ddiv(y,base); y1=Ddiv(y1,base);
  2074. X            a=Dmul(y,1.0);
  2075. X            z2=Dmul(y1,base);
  2076. X            if (z2 != z1) break;
  2077. X            if ((Dsum(a,a) == 0.0) || (absval(y) >= xmin)) break;
  2078. X            k++;
  2079. X        } while (1);
  2080. X
  2081. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  2082. X
  2083. X    minexp= (-k)+1;
  2084. X
  2085. X    if ((mx <= k+k-3) && (ibase != 10)) { mx+=mx; iexp+=1; }
  2086. X    printf("/\* Number of bits used for exponent=%d *\/\n", iexp);
  2087. X    printf("/\* Minimum normalised exponent=%d *\/\n", minexp);
  2088. X    printf("/\* Minimum normalised positive number=%g *\/\n", xmin);
  2089. X
  2090. X/****** Minimum exponent ***************************************************/
  2091. X    if (setjmp(lab)==0) /* in case of underflow trap */
  2092. X        do {
  2093. X            xminner=y;
  2094. X            y=Ddiv(y,base);
  2095. X            a=Dmul(y,1.0);
  2096. X            if ((Dsum(a,a) == 0.0) || (absval(y) >= xminner)) break;
  2097. X        } while (1);
  2098. X
  2099. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  2100. X
  2101. X    if (xminner != 0.0 && xminner != xmin) {
  2102. X        printf("/\* The smallest numbers are not kept normalised *\/\n");
  2103. X        printf("/\* Smallest unnormalised positive number=%g *\/\n",
  2104. X            xminner);
  2105. X    }
  2106. X
  2107. X/****** Maximum exponent ***************************************************/
  2108. X    maxexp=2; xmax=1.0; newxmax=base+1.0;
  2109. X    if (setjmp(lab) == 0) {
  2110. X        while (xmax<newxmax) {
  2111. X            xmax=newxmax;
  2112. X            newxmax=Dmul(newxmax, base);
  2113. X            if (Ddiv(newxmax, base) != xmax) break; /* ieee infinity */
  2114. X            maxexp++;
  2115. X        }
  2116. X    }
  2117. X    if (setjmp(lab)!=0) { printf("Unexpected over/underflow\n"); exit(1); }
  2118. X
  2119. X    printf("/\* Maximum exponent=%d *\/\n", maxexp);
  2120. X
  2121. X/****** Largest and smallest numbers ************************************/
  2122. X    xmax=Ddiff(1.0, epsneg);
  2123. X    if (Dmul(xmax,1.0) != xmax) xmax=Ddiff(1.0, Dmul(base,epsneg));
  2124. X    for (i=1; i<=maxexp; i++) xmax=Dmul(xmax, base);
  2125. X    printf("/\* Maximum number=%g *\/\n", xmax);
  2126. X
  2127. X/****** Hidden bit + sanity check ***************************************/
  2128. X    if (ibase != 10) {
  2129. X        mantbits=floor_log(2, (double)ibase)*imant;
  2130. X        if (mantbits+iexp+1 == sizeof(double)*bits+1) {
  2131. X            printf("/\* Double arithmetic uses a hidden bit *\/\n");
  2132. X        } else if (mantbits+iexp+1 == sizeof(double)*bits) {
  2133. X            printf("/\* Double arithmetic doesn't use a hidden bit *\/\n");
  2134. X        } else {
  2135. X            printf("/\* Something fishy here! %s %s *\/\n",
  2136. X                "Exponent size + mantissa size doesn't match",
  2137. X                "with the size of a double.");
  2138. X        }
  2139. X    }
  2140. X
  2141. X/****** The point of it all: ********************************************/
  2142. X    printf("\n/\* Numeric package constants *\/\n");
  2143. X
  2144. X    tenlogBASE= floor_log(10, (double)maxlong)/2;
  2145. X    BASE=1; for(i=1; i<=tenlogBASE; i++) BASE*=10;
  2146. X
  2147. X    BIG= power(ibase, imant)-1.0;
  2148. X    MAXNUMDIG= tendigs;
  2149. X    Maxreal= xmax;
  2150. X    Maxexpo= floor_log(2, (double)ibase)*maxexp;
  2151. X    Minexpo= floor_log(2, (double)ibase)*minexp;
  2152. X    DBLBITS= floor_log(2, (double)ibase)*imant;
  2153. X    LONGBITS= longpower;
  2154. X
  2155. X    printf("#define Maxintlet %d /\* Maximum short *\/\n", maxshort);
  2156. X    printf("#define Maxint %d /\* Maximum int *\/\n", maxint);
  2157. X
  2158. X    if (2*intpower + 1 <= longpower) {
  2159. X        printf("typedef int digit;\n");
  2160. X        maxdigit= maxint;
  2161. X    }
  2162. X    else {
  2163. X        printf("typedef short digit;\n");
  2164. X        maxdigit= maxshort;
  2165. X    }
  2166. X    printf("typedef long twodigit;\n");
  2167. X    
  2168. X    printf("\/* BASE must be a power of ten, BASE**2 must fit in a twodigit *\/\n");
  2169. X    printf("\/* and -2*BASE as well as BASE*2 must fit in a digit *\/\n");
  2170. X
  2171. X    printf("#define BASE %d\n", BASE);
  2172. X    if (((double)BASE)*BASE > maxlong || ((double)BASE)+BASE > maxdigit) {
  2173. X        printf("*** BASE value wrong\n");
  2174. X        exit(1);
  2175. X    }
  2176. X    printf("#define tenlogBASE %d /\*  = log10(BASE) *\/\n", tenlogBASE);
  2177. X
  2178. X    printf("#define BIG %1.1f /\* Maximum integral double *\/\n", BIG);
  2179. X    printf("#define MAXNUMDIG %d /\* The number of decimal digits in BIG *\/\n",
  2180. X        MAXNUMDIG);
  2181. X    printf("#define MINNUMDIG 6 /\* Don't change: this is here for consistency *\/\n");
  2182. X
  2183. X    printf("#define Maxreal %e /\* Maximum double *\/\n", Maxreal);
  2184. X    printf("#define Maxexpo %d /\* Maximum value such that 2**Maxexpo<=Maxreal *\/\n",
  2185. X        Maxexpo);
  2186. X    printf("#define Minexpo (%d) /\* Minimum value such that -2**Minexpo>=Minreal *\/\n",
  2187. X        Minexpo);
  2188. X    printf("#define DBLBITS %d /\* The number of bits in the fraction of a double *\/\n",
  2189. X        DBLBITS);
  2190. X
  2191. X    printf("#define LONGBITS %d /\* The number of bits in a long *\/\n",
  2192. X        LONGBITS);
  2193. X    printf("#define TWOTO_DBLBITSMIN1 %1.1f /\* 2**(DBLBITS-1) *\/\n",
  2194. X        power(2, DBLBITS-1));
  2195. X    printf("#define TWOTO_LONGBITS %1.1f /\* 2**LONGBITS *\/\n",
  2196. X        power(2, LONGBITS));
  2197. X    printf("#define RNDM_LIMIT %1.1f /\* save limit for choice *\/\n",
  2198. X        power(2, (DBLBITS < 66 ? DBLBITS-3 : 63)));
  2199. X
  2200. X#ifdef MEMSIZE
  2201. X/* An extra goody: the approximate amount of data-space */
  2202. X/* Put here because it is likely to be slower then the rest */
  2203. X
  2204. X    /*Allocate blocks of 1000 until no more available*/
  2205. X    /*Don't be tempted to change this to 1024: */
  2206. X    /*we don't know how much header information there is*/
  2207. X
  2208. X    for(count=0; (p=(int *)malloc(1000))!=0; count++) { }
  2209. X
  2210. X    printf("\n/\* Memory~= %d000 *\/\n", count);
  2211. X#endif /*MEMSIZE*/
  2212. X    
  2213. X    /* Aligning ABC values */
  2214. X    
  2215. X    printf("\n");
  2216. X    nfiller= (unsigned)
  2217. X        ((sizeof(value)) - ((sizeof(header)) + (sizeof(char **))));
  2218. X    printf("#define HEADER literal type; reftype refcnt; intlet len");
  2219. X    if (nfiller > 0)
  2220. X        printf("; char filler[%u]", nfiller);
  2221. X    printf("\n");
  2222. X    printf("#define FILLER");
  2223. X    if (nfiller > 0) {
  2224. X        printf(" {");
  2225. X        for (i= 1; i < nfiller; i++) {
  2226. X            printf("0, ");
  2227. X        }
  2228. X        printf("0},");
  2229. X    }
  2230. X    printf("\n");
  2231. X    
  2232. X    exit(0);
  2233. X}
  2234. END_OF_FILE
  2235.   if test 12184 -ne `wc -c <'abc/mkconfig.c'`; then
  2236.     echo shar: \"'abc/mkconfig.c'\" unpacked with wrong size!
  2237.   fi
  2238.   # end of 'abc/mkconfig.c'
  2239. fi
  2240. echo shar: End of archive 13 \(of 25\).
  2241. cp /dev/null ark13isdone
  2242. MISSING=""
  2243. 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
  2244.     if test ! -f ark${I}isdone ; then
  2245.     MISSING="${MISSING} ${I}"
  2246.     fi
  2247. done
  2248. if test "${MISSING}" = "" ; then
  2249.     echo You have unpacked all 25 archives.
  2250.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2251. else
  2252.     echo You still must unpack the following archives:
  2253.     echo "        " ${MISSING}
  2254. fi
  2255. exit 0 # Just in case...
  2256.