home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume23 / abc / part16 < prev    next >
Text File  |  1991-01-08  |  55KB  |  2,128 lines

  1. Subject:  v23i095:  ABC interactive programming environment, Part16/25
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: bd584991 f7c001ad a3094268 61dee307
  5.  
  6. Submitted-by: Steven Pemberton <steven@cwi.nl>
  7. Posting-number: Volume 23, Issue 95
  8. Archive-name: abc/part16
  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/bint1/i1nuc.c abc/bint2/i2ana.c abc/bint3/i3err.c
  17. #   abc/doc/abcintro.doc abc/ihdrs/i2par.h abc/lin/i1lta.c
  18. # Wrapped by rsalz@litchi.bbn.com on Mon Dec 17 13:28:11 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 16 (of 25)."'
  22. if test -f 'abc/bint1/i1nuc.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'abc/bint1/i1nuc.c'\"
  24. else
  25.   echo shar: Extracting \"'abc/bint1/i1nuc.c'\" \(8704 characters\)
  26.   sed "s/^X//" >'abc/bint1/i1nuc.c' <<'END_OF_FILE'
  27. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  28. X
  29. X#include "b.h"
  30. X#include "feat.h"
  31. X#include "bmem.h"
  32. X#include "bobj.h"
  33. X#include "i1num.h"
  34. X
  35. X#define MAXDIGITS (MAXNUMDIG)
  36. X    /* Max precision for non-integral, non-rounded numbers */
  37. X#define MAXNUMSIZE (MAXDIGITS+MAXNUMDIG+10)
  38. X    /* Maximum width of non-rounded number in convnum;
  39. X     * occurs for e.g. -0.xxxxxxe-yyy:
  40. X     * MAXDIGITS x's and MAXNUMDIG (with EXT_RANGE on) y's 
  41. X     * 10 is a few extra, not a holy number, but guard against evil:-) */
  42. X
  43. X
  44. X/* Convert an integer to a C character string.
  45. X   The character string is overwritten on each next call.
  46. X   It assumes BASE is a power of 10. */
  47. X
  48. XHidden char *convint(v) register integer v; {
  49. X    static char *buffer, shortbuffer[tenlogBASE+3];
  50. X    static char fmt[10];
  51. X    register char *cp;
  52. X    register int i;
  53. X    bool neg = No;
  54. X
  55. X    if (IsSmallInt(v)) {
  56. X        sprintf(shortbuffer, "%d", SmallIntVal(v));
  57. X        return shortbuffer;
  58. X    }
  59. X
  60. X    if (Digit(v, Length(v)-1) < 0) {
  61. X        neg = Yes;
  62. X        v = int_neg(v);
  63. X    }
  64. X    if (buffer) freemem((ptr)buffer);
  65. X    buffer = getmem((unsigned)(Length(v)*tenlogBASE + 1 + neg));
  66. X    cp = buffer;
  67. X    if (neg) *cp++ = '-';
  68. X    sprintf(cp, "%d", Msd(v));
  69. X    if (!IsSmallInt(v)) {
  70. X        if (!*fmt) sprintf(fmt, "%%0%dd", tenlogBASE);
  71. X        while (*cp) ++cp;
  72. X        for (i = Length(v)-2; i >= 0; --i, cp += tenlogBASE)
  73. X            sprintf(cp, fmt, Digit(v, i));
  74. X        if (neg) Release(v);
  75. X    }
  76. X    return buffer;
  77. X}
  78. X
  79. XHidden value tento_d(x) double x; {
  80. X    if (x > Maxint || x < -Maxint) {
  81. X        value n= (value) mk_int(x);
  82. X        value v= power((value) int_10, n);
  83. X        release(n);
  84. X        return v;
  85. X    }
  86. X    else return tento((int) x);
  87. X}
  88. X
  89. X/* return number of digits before decimal point,
  90. X * or minus the number of zero's after the decimal point
  91. X */
  92. X
  93. XHidden int digits_in(v) value v; {
  94. X    integer p, q;
  95. X    struct integer pp, qq;
  96. X    double x;
  97. X    value t1= Vnil, t2= Vnil;
  98. X
  99. X    if (numcomp(v, zero) == 0)
  100. X        return 0;
  101. X
  102. X    v= absval(v);
  103. X    if (Integral(v)) {
  104. X        p= (integer) v;
  105. X        q= (integer) one;
  106. X    }
  107. X    else {
  108. X        p= Numerator((rational) v);
  109. X        q= Denominator((rational) v);
  110. X    }
  111. X    FreezeSmallInt(p, pp); FreezeSmallInt(q, qq);
  112. X
  113. X    x = log10((double) Msd(p));
  114. X    x-= log10((double) Msd(q));
  115. X    x+= (double) ((Length(p) - Length(q)) * tenlogBASE);
  116. X    x= floor(x) + 1;
  117. X
  118. X    /* it can be +1 or -1 off!!! */
  119. X    if (numcomp(v, t1 = tento_d(x)) >= 0) /* one too low */
  120. X        ++x;
  121. X    else if (numcomp(v, t2 = tento_d(x-1)) < 0) /* one too high */
  122. X        --x;
  123. X
  124. X    release(t1); release(t2);
  125. X    release(v);
  126. X
  127. X    if (x > Maxint)
  128. X        return Maxint;
  129. X    else if (x < -Maxint)
  130. X        return -Maxint;
  131. X    else
  132. X        return (int) x;
  133. X}
  134. X
  135. X/* Convert a numeric value to a C character string.
  136. X * The character string is released on each next call.
  137. X *
  138. X * prod10n() is a routine with does a fast multiplication with a ten power
  139. X * and does not normalize a rational result sometimes.
  140. X */
  141. X
  142. XVisible string convnum(v) register value v; {
  143. X    value r, re, rre;
  144. X    int rndsize= 0;
  145. X    int num;
  146. X    int ndigits;
  147. X    int precision= MAXDIGITS;
  148. X    register string txt;
  149. X    int txtlen;
  150. X    static char *numbuf;
  151. X    register char *str;
  152. X    bool remainder;
  153. X    bool rndflag;
  154. X    int buflen= MAXNUMSIZE;
  155. X
  156. X    if (Integral(v)) return convint((integer)v);
  157. X
  158. X    /* Aproximates and rationale are treated alike,
  159. X     * using MAXDIGITS precision, and e-notation when
  160. X     * necessary.
  161. X     * However, rationals resulting from 'n round x' are
  162. X     * transformed to f-format, printing n=Roundsize digits
  163. X     * after the decimal point. */
  164. X
  165. X    if (Rational(v) && Roundsize(v) > 0)
  166. X        rndsize= Roundsize(v);
  167. X    
  168. X    r= Approximate(v) ? exactly(v) : copy(v);
  169. X
  170. X    if ((num=numcomp(r, zero)) == 0 && rndsize == 0) {
  171. X        release(r);
  172. X        return "0";
  173. X    }
  174. X    else if (num < 0) {
  175. X        r= negated(v= r);
  176. X        release(v);
  177. X    }
  178. X
  179. X    ndigits= digits_in(r);
  180. X    rndflag= rndsize > 0 && (rndsize > precision - ndigits || num == 0);
  181. X
  182. X    re= prod10n(r, rndflag ? rndsize : precision - ndigits, No);
  183. X    rre= round1(re);
  184. X    txt= convint((integer) rre);
  185. X    txtlen= strlen(txt);
  186. X
  187. X    if (rndflag) {
  188. X        ndigits= txtlen - rndsize;
  189. X        precision= (ndigits > 0 ? txtlen : rndsize);
  190. X        remainder= No;
  191. X    }
  192. X    else {
  193. X        if (txtlen > precision) {
  194. X            /* rounding caused extra digit, e.g. 999.9 ->1000 */
  195. X            txtlen--;
  196. X            txt[txtlen]= '\0';
  197. X            ndigits++;
  198. X        }
  199. X        remainder= (numcomp(re, rre) != 0);
  200. X        if (!remainder) {
  201. X            /* delete trailing zero's after decimal point */
  202. X            int headlen= ndigits + rndsize;
  203. X            int minlen= headlen;
  204. X
  205. X            if (headlen <= 0 || headlen > precision)
  206. X                minlen= 1;
  207. X            while (txtlen > minlen && txt[txtlen-1] == '0') {
  208. X                txtlen--;
  209. X            }
  210. X            txt[txtlen]= '\0';
  211. X            if (rndsize > 0 && txtlen == headlen)
  212. X                rndflag= Yes;
  213. X        }
  214. X    }
  215. X    
  216. X    release(r); release(re); release(rre);
  217. X
  218. X    /* now copy to buffer */
  219. X    if (numbuf) freemem(numbuf);
  220. X    if (rndflag)
  221. X        buflen= txtlen + (ndigits < 0 ? -ndigits : ndigits) + 10;
  222. X    
  223. X    numbuf= getmem((unsigned) buflen);
  224. X    
  225. X    str= numbuf;
  226. X    if (num<0) *str++= '-';
  227. X    
  228. X    if (ndigits > precision || (ndigits == precision && remainder)) {
  229. X        *str++= *txt++;
  230. X        if (txtlen > 1) {
  231. X            *str++= '.';
  232. X            while (*txt) *str++ = *txt++;
  233. X        }
  234. X        sprintf(str, "e+%d", ndigits-1);
  235. X    }
  236. X    else if (ndigits == precision && !remainder) {
  237. X        while (*txt) *str++ = *txt++;
  238. X        *str= '\0';
  239. X    }
  240. X    else if (ndigits > 0) {
  241. X        /* we end up here too for rndflag == Yes, r > 1 */
  242. X        while (ndigits-- > 0) *str++ = *txt++;
  243. X        if (*txt) *str++= '.';
  244. X        while (*txt) *str++ = *txt++;
  245. X        *str= '\0';
  246. X    }
  247. X    else if (ndigits >= -3 || rndflag) {
  248. X        /* 3 is about size of exponent,
  249. X         * therefore allow upto 3 0's after decimal point
  250. X         * giving 0.000ddddd instead
  251. X         * of     0.ddddde-3 notation below;
  252. X         *
  253. X         * also handle rndflag == Yes, 1>r>0 here
  254. X         */
  255. X
  256. X        *str++= '0'; *str++= '.';
  257. X        while (ndigits++ < 0) *str++= '0';
  258. X        while (*txt) *str++ = *txt++;
  259. X        *str= '\0';
  260. X    }
  261. X    else {
  262. X        *str++= '0'; *str++= '.';
  263. X        while (*txt) *str++ = *txt++;
  264. X        sprintf(str, "e%d", ndigits);    /* ndigits < 0, %d gives -nnn */
  265. X    }
  266. X        
  267. X    return numbuf;
  268. X}
  269. X
  270. X#define E_EXACT ABC
  271. X
  272. X/* Convert a text to a number (assume it's syntactically correct!).
  273. X   Again, BASE must be a power of 10.
  274. X   ********** NEW **********
  275. X   If E_EXACT is undefined, numbers in e-notation are made
  276. X   approximate.
  277. X*/
  278. X
  279. XVisible value numconst(v) register value v; {
  280. X    string txt, txt0;
  281. X    register string tp;
  282. X    register int numdigs, fraclen;
  283. X    integer a;
  284. X    register digit accu;
  285. X    value c;
  286. X
  287. X    txt= sstrval(v);
  288. X    if (*txt == 'e') a = int_1;
  289. X    else {
  290. X        txt0= txt;
  291. X        while (*txt0 && *txt0=='0') ++txt0; /* Skip leading zeros */
  292. X
  293. X        for (tp = txt0; isdigit(*tp); ++tp)
  294. X            ; /* Count integral digits */
  295. X        numdigs = tp-txt0;
  296. X        fraclen = 0;
  297. X        if (*tp=='.') {
  298. X            ++tp;
  299. X            for (; isdigit(*tp); ++tp)
  300. X                ++fraclen; /* Count fractional digits */
  301. X            numdigs += fraclen;
  302. X        }
  303. X        a = (integer) grab_num((numdigs+tenlogBASE-1) / tenlogBASE);
  304. X        if (!a) goto recover;
  305. X        accu = 0;
  306. X        /* Integer part: */
  307. X        for (tp = txt0; isdigit(*tp); ++tp) {
  308. X            accu = accu*10 + *tp - '0';
  309. X            --numdigs;
  310. X            if (numdigs%tenlogBASE == 0) {
  311. X                Digit(a, numdigs/tenlogBASE) = accu;
  312. X                accu = 0;
  313. X            }
  314. X        }
  315. X        /* Fraction: */
  316. X        if (*tp == '.') {
  317. X            ++tp;
  318. X            for (; isdigit(*tp); ++tp) {
  319. X                accu = accu*10 + *tp - '0';
  320. X                --numdigs;
  321. X                if (numdigs%tenlogBASE == 0) {
  322. X                    Digit(a, numdigs/tenlogBASE) = accu;
  323. X                    accu = 0;
  324. X                }
  325. X            }
  326. X        }
  327. X        if (numdigs != 0) syserr(MESS(800, "numconst: can't happen"));
  328. X        a = int_canon(a);
  329. X    }
  330. X
  331. X    /* Exponent: */
  332. X    if (*tp != 'e') {
  333. X        integer b = int_tento(fraclen);
  334. X        if (!b) {
  335. X            /* Can't happen now; for robustness */
  336. X            Release(a);
  337. X            goto recover;
  338. X        }
  339. X        c = mk_exact(a, b, fraclen);
  340. X        Release(b);
  341. X    }
  342. X    else {
  343. X        double expo = 0;
  344. X        int sign = 1;
  345. X        value b;
  346. X        ++tp;
  347. X        if (*tp == '+') ++tp;
  348. X        else if (*tp == '-') {
  349. X            ++tp;
  350. X            sign = -1;
  351. X        }
  352. X        for (; isdigit(*tp); ++tp) {
  353. X            expo = expo*10 + *tp - '0';
  354. X            if (expo > Maxint) {
  355. X                interr(MESS(801, "excessive exponent in e-notation"));
  356. X                expo = 0;
  357. X                break;
  358. X            }
  359. X        }
  360. X        b = tento((int)expo * sign - fraclen);
  361. X        if (!b) {
  362. X            Release(a);
  363. X            goto recover;
  364. X        }
  365. X#ifndef E_EXACT
  366. X        /* Make approximate number if e-notation used */
  367. X        c = approximate(b);
  368. X        Release(b);
  369. X        b = c;
  370. X#endif
  371. X        if (a == int_1) c = b;
  372. X        else c = prod((value)a, b), Release(b);
  373. X    }
  374. X    Release(a);
  375. X    fstrval(txt);
  376. X    return c;
  377. X
  378. Xrecover:
  379. X    /* from failure of grab_num, also indirect (int_tento); 
  380. X       an error has already been reported */
  381. X    fstrval(txt);
  382. X    return Vnil;
  383. X}
  384. X
  385. X
  386. X/*
  387. X * printnum(f, v) writes a number v on file f in such a way that it
  388. X * can be read back identically.
  389. X */
  390. X
  391. XVisible Procedure printnum(fp, v) FILE *fp; value v; {
  392. X    if (Approximate(v)) {
  393. X        app_print(fp, (real) v);
  394. X        return;
  395. X    }
  396. X    if (Rational(v) && Denominator((rational)v) != int_1) {
  397. X        int i = Roundsize(v);
  398. X        fputs(convnum((value)Numerator((rational)v)), fp);
  399. X        if (i > 0) {
  400. X            /* The assumption here is that in u/v, the Roundsize
  401. X               of the result is the sum of that of the operands. */
  402. X            putc('.', fp);
  403. X            do putc('0', fp); while (--i > 0);
  404. X        }
  405. X        putc('/', fp);
  406. X        v = (value) Denominator((rational)v);
  407. X    }
  408. X    fputs(convnum(v), fp);
  409. X}
  410. END_OF_FILE
  411.   if test 8704 -ne `wc -c <'abc/bint1/i1nuc.c'`; then
  412.     echo shar: \"'abc/bint1/i1nuc.c'\" unpacked with wrong size!
  413.   fi
  414.   # end of 'abc/bint1/i1nuc.c'
  415. fi
  416. if test -f 'abc/bint2/i2ana.c' -a "${1}" != "-c" ; then 
  417.   echo shar: Will not clobber existing file \"'abc/bint2/i2ana.c'\"
  418. else
  419.   echo shar: Extracting \"'abc/bint2/i2ana.c'\" \(8705 characters\)
  420.   sed "s/^X//" >'abc/bint2/i2ana.c' <<'END_OF_FILE'
  421. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  422. X
  423. X/* Prepare for code generation -- find out which tags are targets */
  424. X
  425. X#include "b.h"
  426. X#include "bint.h"
  427. X#include "bobj.h"
  428. X#include "i0err.h"
  429. X#include "i2nod.h"
  430. X#include "i2gen.h" /* Must be after i2nod.h */
  431. X#include "i3env.h"
  432. X#include "i3sou.h"
  433. X
  434. X
  435. XVisible int nextvarnumber; /* Counts local targets (including formals) */
  436. XHidden int nformals; /* nr of formals */
  437. XHidden bool bound; /* flag to recognise bound tags */
  438. X
  439. XVisible value locals, globals, mysteries, refinements;
  440. X
  441. X
  442. XVisible value *setup(t) parsetree t; {
  443. X    typenode n= Nodetype(t);
  444. X    bool in_prmnv= !Unit(n);
  445. X    nextvarnumber= 0;
  446. X    mysteries= mk_elt();
  447. X    if (in_prmnv) {
  448. X        globals= copy(prmnv->tab);
  449. X        locals= Vnil;
  450. X        refinements= mk_elt();
  451. X        return Command(n) ? &globals : Pnil;
  452. X    } else {
  453. X        globals= mk_elt();
  454. X        locals= mk_elt();
  455. X        refinements= *Branch(t, n == HOW_TO ? HOW_R_NAMES : FPR_R_NAMES);
  456. X        VOID copy(refinements);
  457. X        unit_context(t);
  458. X        return &locals;
  459. X    }
  460. X}
  461. X
  462. XHidden Procedure unit_context(t) parsetree t; {
  463. X    cntxt= In_unit;
  464. X    release(uname); uname= get_pname(t);
  465. X}
  466. X
  467. XVisible Procedure cleanup() {
  468. X    release(locals);
  469. X    release(globals);
  470. X    release(mysteries);
  471. X    release(refinements);
  472. X}
  473. X
  474. X/* ********************************************************************    */
  475. X
  476. X/* Analyze parse tree, finding the targets and formal parameters.
  477. X   Formal parameters are found in the heading and stored as local targets.
  478. X   Global targets are also easily found: they are mentioned in a SHARE command.
  479. X   Local targets appear on their own or in collateral forms after PUT IN
  480. X   or as bound tags after FOR, SOME, EACH or NO.
  481. X   Note that DELETE x, REMOVE e FROM x, or PUT e IN x[k] (etc.) don't
  482. X   introduce local targets, because in all these cases x must have been
  483. X   initialized first.  This speeds up our task of finding targets,
  484. X   since we don't have to visit all nodes: only nodes that may contain
  485. X   commands or tests, and the positions mentioned here, need be visited.
  486. X   (And of course unit headings).
  487. X   We don't have to look for refinements since these are already known
  488. X   from the unit heading.
  489. X */
  490. X
  491. XHidden Procedure a_tag(name, targs) value name; value *targs; {
  492. X    value *aa; int varnumber;
  493. X    if (locals != Vnil && envassoc(locals, name) != Pnil);
  494. X    else if (envassoc(globals, name) != Pnil);
  495. X    else if (envassoc(refinements, name) != Pnil) {
  496. X        if (targs != &mysteries)
  497. X            fixerr(REF_NO_TARGET);
  498. X    }
  499. X    else {
  500. X        aa= envassoc(mysteries, name);
  501. X        if (aa != Pnil && targs == &mysteries);
  502. X        else {
  503. X            if (aa != Pnil) {
  504. X                varnumber= SmallIntVal(*aa);
  505. X                e_delete(&mysteries, name);
  506. X            }
  507. X            else if (targs != &globals)
  508. X                varnumber= nextvarnumber++;
  509. X            else varnumber= 0;
  510. X            e_replace(MkSmallInt(varnumber), targs, name);
  511. X        }
  512. X    }
  513. X    if (bound && locals != Vnil) {
  514. X        aa= envassoc(locals, name);
  515. X        if (aa == Pnil || SmallIntVal(*aa) < nformals)
  516. X            fixerr(MESS(4400, "in ... i IN e, i contains a non-local name"));
  517. X    }
  518. X}
  519. X
  520. XHidden Procedure a_fpr_formals(t) parsetree t; {
  521. X    typenode n= nodetype(t);
  522. X    switch (n) {
  523. X    case TAG:
  524. X        break;
  525. X    case MONF: case MONPRD:
  526. X        analyze(*Branch(t, MON_RIGHT), &locals);
  527. X        break;
  528. X    case DYAF: case DYAPRD:
  529. X        analyze(*Branch(t, DYA_LEFT), &locals);
  530. X        analyze(*Branch(t, DYA_RIGHT), &locals);
  531. X        break;
  532. X    default: syserr(MESS(1900, "a_fpr_formals"));
  533. X    }
  534. X}
  535. X
  536. XVisible Procedure analyze(t, targs) parsetree t; value *targs; {
  537. X    typenode nt; string s; char c; int n, k, len; value v;
  538. X    if (!Is_node(t) || !still_ok) return;
  539. X    nt= Nodetype(t);
  540. X    if (nt < 0 || nt >= NTYPES) syserr(MESS(1901, "analyze bad tree"));
  541. X    s= gentab[nt];
  542. X    if (s == NULL) return;
  543. X    n= First_fieldnr;
  544. X    while ((c= *s++) != '\0' && still_ok) {
  545. X        switch (c) {
  546. X        case '0':
  547. X        case '1':
  548. X        case '2':
  549. X        case '3':
  550. X        case '4':
  551. X        case '5':
  552. X        case '6':
  553. X        case '7':
  554. X        case '8':
  555. X        case '9':
  556. X            n= (c - '0') + First_fieldnr;
  557. X            break;
  558. X        case 'c':
  559. X            v= *Branch(t, n);
  560. X            if (v != Vnil) {
  561. X                len= Nfields(v);
  562. X                for (k= 0; k < len; ++k)
  563. X                    analyze(*Field(v, k), targs);
  564. X            }
  565. X            ++n;
  566. X            break;
  567. X        case '#':
  568. X            curlino= *Branch(t, n);
  569. X            /* Fall through */
  570. X        case 'l':
  571. X        case 'v':
  572. X            ++n;
  573. X            break;
  574. X        case 'm':
  575. X            analyze(*Branch(t, n), &mysteries);
  576. X            ++n;
  577. X            break;
  578. X        case 'g':
  579. X            analyze(*Branch(t, n), &globals);
  580. X            ++n;
  581. X            break;
  582. X        case 'b':
  583. X            bound= Yes;
  584. X            analyze(*Branch(t, n),
  585. X                locals != Vnil ? &locals : &globals);
  586. X            bound= No;
  587. X            ++n;
  588. X            break;
  589. X        case 'x':
  590. X            curline= *Branch(t, n);
  591. X            /* Fall through */
  592. X        case 'a':
  593. X        case 'u':    
  594. X            analyze(*Branch(t, n), targs);
  595. X            ++n;
  596. X            break;
  597. X        case 't':
  598. X            analyze(*Branch(t, n), Pnil);
  599. X            ++n;
  600. X            break;
  601. X        case 'f':
  602. X            a_fpr_formals(*Branch(t, n));
  603. X            nformals= nextvarnumber;
  604. X            ++n;
  605. X            break;
  606. X        case 'h':
  607. X            v= *Branch(t, n);
  608. X            analyze(v, &locals);
  609. X            nformals= nextvarnumber;
  610. X            ++n;
  611. X            break;
  612. X        case '=':
  613. X            *Branch(t, n)= MkSmallInt(nextvarnumber);
  614. X            ++n;
  615. X            break;
  616. X        case ':':    /* code for WHILE loop */
  617. X            curlino= *Branch(t, WHL_LINO);
  618. X            analyze(*Branch(t, WHL_TEST), Pnil);
  619. X            v= *Branch(t, WHL_SUITE);
  620. X            if (nodetype((parsetree) v) != COLON_NODE)
  621. X                syserr(BAD_WHILE);
  622. X            analyze(*Branch(v, COLON_SUITE), targs);
  623. X            break;
  624. X        case ';':    /* code for TEST_SUITE */
  625. X            curlino= *Branch(t, TSUI_LINO);
  626. X            curline= *Branch(t, TSUI_TEST);
  627. X            analyze(curline, Pnil);
  628. X            v= *Branch(t, TSUI_SUITE);
  629. X            if (nodetype((parsetree) v) != COLON_NODE)
  630. X                syserr(BAD_TESTSUITE);
  631. X            analyze(*Branch(v, COLON_SUITE), targs);
  632. X            analyze(*Branch(t, TSUI_NEXT), targs);
  633. X            break;
  634. X        case 'T':
  635. X            if (targs != Pnil)
  636. X                a_tag((value)*Branch(t, TAG_NAME), targs);
  637. X            break;
  638. X        }
  639. X    }
  640. X}
  641. X
  642. X/* ********************************************************************    */
  643. X
  644. X/* Table describing the actions of the fixer for each node type */
  645. X
  646. X
  647. X/*
  648. X    LIST OF CODES AND THEIR MEANING
  649. X
  650. X    char    fix        n?    analyze
  651. X
  652. X    0-9            n= c-'0'
  653. X
  654. X    #    set curlino    ++n    set curlino
  655. X    =            ++n    set to nextvarnum
  656. X    a    locate        ++n    analyze
  657. X    b    locate        ++n    analyze bound tags
  658. X    c    collateral    ++n    analyze collateral
  659. X    f    fpr_formals    ++n    a_fpr_formals
  660. X    g            ++n    global
  661. X    h            ++n    how'to formal
  662. X    l    locate        ++n
  663. X    m    actual param    ++n    mystery
  664. X    t    test        ++n    analyze; set targs= 0
  665. X    u    unit        ++n    analyze
  666. X    v    evaluate    ++n
  667. X    x    execute        ++n    analyze
  668. X
  669. X    :    special code for WHILE loop
  670. X    ;    special code for TEST_SUITE
  671. X    ?    special code for UNPARSED
  672. X    @    special check for BEHEAD target
  673. X    |    special check for CURTAIL target
  674. X    C    special code for comparison
  675. X    D    special code for DYAF
  676. X    E    special code for DYAPRD
  677. X    F    make number
  678. X    G    jumpto(l1)
  679. X    H    here(&l1)
  680. X    I    if (*Branch(t, n) != NilTree) jump2here(t)
  681. X    J    jump2here(t)
  682. X    K    hold(&st)
  683. X    L    let_go(&st)
  684. X    M    special code for MONF
  685. X    N    special code for MONPRD
  686. X    Q    if (*Branch(t, n) != NilTree) visit(t);
  687. X    R    if (!reachable()) "command cannot be reached"
  688. X    S    jumpto(Stop)
  689. X    T    special code for TAG
  690. X    U    special code for user-defined-command
  691. X    V    visit(t)
  692. X    W    visit2(t, seterr(1))
  693. X    X    visit(t) or lvisit(t) depending on flag
  694. X    Y    special code for YIELD/TEST
  695. X    Z    special code for refinement
  696. X     
  697. X*/
  698. X
  699. X
  700. XVisible string gentab[NTYPES]= {
  701. X
  702. X    /* HOW_TO */ "1h3xSu6=",
  703. X    /* YIELD */ "2fV4xYu7=",
  704. X    /* TEST */ "2fV4xYu7=",
  705. X    /* REFINEMENT */ "H2xZSu",
  706. X
  707. X    /* Commands */
  708. X
  709. X    /* SUITE */ "#RQx3x",
  710. X    /* PUT */ "vaV",
  711. X    /* INSERT */ "vlV",
  712. X    /* REMOVE */ "vlV",
  713. X    /* SET_RANDOM */ "vV",
  714. X    /* DELETE */ "lV",
  715. X    /* CHECK */ "tV",
  716. X    /* SHARE */ "g",
  717. X    /* PASS */ "",
  718. X
  719. X    /* WRITE */ "1vV",
  720. X    /* WRITE1 */ "1vV",
  721. X    /* READ */ "avV",
  722. X    /* READ_RAW */ "aV",
  723. X
  724. X    /* IF */ "tV2xJ",
  725. X    /* WHILE */ ":",    /* old: "HtV2xGJ" */
  726. X    /* FOR */ "bvHV3xGJ",
  727. X
  728. X    /* SELECT */ "1x",
  729. X    /* TEST_SUITE */ ";",    /* old: "#tW3xKIxL" */
  730. X    /* ELSE */ "#2x",
  731. X
  732. X    /* QUIT */ "VS",
  733. X    /* RETURN */ "vVS",
  734. X    /* REPORT */ "tVS",
  735. X    /* SUCCEED */ "VS",
  736. X    /* FAIL */ "VS",
  737. X
  738. X    /* USER_COMMAND */ "1mUV",
  739. X    /* EXTENDED_COMMAND */ "1cV",
  740. X
  741. X    /* Expressions, targets, tests */
  742. X
  743. X    /* TAG */ "T",
  744. X    /* COMPOUND */ "a",
  745. X
  746. X    /* Expressions, targets */
  747. X
  748. X    /* COLLATERAL */ "cX",
  749. X    /* SELECTION */ "lvX",
  750. X    /* BEHEAD */ "lv@X",
  751. X    /* CURTAIL */ "lv|X",
  752. X
  753. X    /* Expressions, tests */
  754. X
  755. X    /* UNPARSED */ "?",
  756. X
  757. X    /* Expressions */
  758. X
  759. X    /* MONF */ "M1vV",
  760. X    /* DYAF */ "Dv2vV",
  761. X    /* NUMBER */ "FV",
  762. X    /* TEXT_DIS */ "1v",
  763. X    /* TEXT_LIT */ "1vV",
  764. X    /* TEXT_CONV */ "vvV",
  765. X    /* ELT_DIS */ "V",
  766. X    /* LIST_DIS */ "cV",
  767. X    /* RANGE_ELEM */ "vvV",
  768. X    /* TAB_DIS */ "cV",
  769. X
  770. X    /* Tests */
  771. X
  772. X    /* AND */ "tVtJ",
  773. X    /* OR */ "tVtJ",
  774. X    /* NOT */ "tV",
  775. X    /* SOME_IN */ "bvHVtGJ",
  776. X    /* EACH_IN */ "bvHVtGJ",
  777. X    /* NO_IN */ "bvHVtGJ",
  778. X    /* MONPRD */ "N1vV",
  779. X    /* DYAPRD */ "Ev2vV",
  780. X    /* LESS_THAN */ "vvCV",
  781. X    /* AT_MOST */ "vvCV",
  782. X    /* GREATER_THAN */ "vvCV",
  783. X    /* AT_LEAST */ "vvCV",
  784. X    /* EQUAL */ "vvCV",
  785. X    /* UNEQUAL */ "vvCV",
  786. X    /* Nonode */ "",
  787. X
  788. X    /* TAGformal */ "T",
  789. X    /* TAGlocal */ "T",
  790. X    /* TAGglobal */ "T",
  791. X    /* TAGrefinement */ "T",
  792. X    /* TAGzerfun */ "T",
  793. X    /* TAGzerprd */ "T",
  794. X
  795. X    /* ACTUAL */ "1mm",
  796. X    /* FORMAL */ "1hh",
  797. X
  798. X#ifdef GFX
  799. X    /* SPACE */ "vvV",
  800. X    /* LINE */ "vvV",
  801. X    /* CLEAR */ "V",
  802. X#endif
  803. X
  804. X    /* COLON_NODE */ ""
  805. X};
  806. END_OF_FILE
  807.   if test 8705 -ne `wc -c <'abc/bint2/i2ana.c'`; then
  808.     echo shar: \"'abc/bint2/i2ana.c'\" unpacked with wrong size!
  809.   fi
  810.   # end of 'abc/bint2/i2ana.c'
  811. fi
  812. if test -f 'abc/bint3/i3err.c' -a "${1}" != "-c" ; then 
  813.   echo shar: Will not clobber existing file \"'abc/bint3/i3err.c'\"
  814. else
  815.   echo shar: Extracting \"'abc/bint3/i3err.c'\" \(8453 characters\)
  816.   sed "s/^X//" >'abc/bint3/i3err.c' <<'END_OF_FILE'
  817. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  818. X
  819. X/* B error message handling */
  820. X
  821. X/* There are two kinds of errors:
  822. X    1) parsing, when the line in error is in a buffer
  823. X    2) execution, when the line in error is a parse-tree, and must
  824. X       therefore be reconstructed.
  825. X*/
  826. X
  827. X#include "b.h"
  828. X#include "bmem.h"
  829. X#include "bint.h"
  830. X#include "feat.h"
  831. X#include "bobj.h"
  832. X#include "i0err.h"
  833. X#include "i2par.h"
  834. X#include "i3env.h"
  835. X#include "i3scr.h"
  836. X#include "i3sou.h"
  837. X
  838. X#ifdef GFX
  839. X#include "bgfx.h"
  840. X#endif
  841. X
  842. XVisible bool still_ok= Yes;
  843. XVisible bool mess_ok= Yes;    /* if Yes print error message */
  844. XVisible bool interrupted= No;
  845. XVisible bool can_interrupt= Yes;
  846. X
  847. XVisible parsetree curline= Vnil;
  848. XVisible value curlino;
  849. X
  850. XVisible FILE *errfile= stderr;    /* may be changed in initerr() */
  851. X
  852. X/*********************************************************************/
  853. X
  854. XHidden Procedure nline() {
  855. X    fflush(stdout); /* should be i3scr.c's ofile, but doesnot matter */
  856. X    if (cntxt == In_read && rd_interactive)
  857. X        at_nwl= Yes;
  858. X    if (!at_nwl)
  859. X        putnewline(errfile);
  860. X    at_nwl= Yes;
  861. X}
  862. X
  863. XVisible intlet errlino= 0;
  864. X
  865. XHidden intlet pr_line(at) bool at; {
  866. X    /*prints the line that tx is in, with an arrow pointing to the column
  867. X      that tx is at.
  868. X    */
  869. X    txptr lx= fcol(); intlet ap= -1, p= 0; char c;
  870. X    txptr ax= tx;
  871. X    
  872. X    if (!at) do ax--; while (Space(Char(ax)));
  873. X    while (!Eol(lx) && Char(lx) != Eotc) {
  874. X        if (lx == ax) ap= p;
  875. X        c= *lx++;
  876. X        if (c == '\t') {
  877. X            do { putchr(errfile, ' '); } while (((++p)%4)!=0);
  878. X        } else { putchr(errfile, c); p++; }
  879. X    }
  880. X    putnewline(errfile);
  881. X    if (ap < 0) ap= p;
  882. X    for (p= 0; p < ap+4; p++) putchr(errfile, ' ');
  883. X    putstr(errfile, "^\n");
  884. X}
  885. X
  886. X#define IN_COMMAND    MESS(3100, " in your command\n")
  887. X#define IN_READ        MESS(3101, " in your expression to be read\n")
  888. X#define IN_EDVAL    MESS(3102, " in your edited value\n")
  889. X#define IN_TARVAL    MESS(3103, " in your location %s\n")
  890. X#define IN_PRMNV    MESS(3104, " in your permanent environment\n")
  891. X#define IN_WSGROUP    MESS(3105, " in your workspace index\n")
  892. X#define IN_UNIT        MESS(3106, " in your how-to %s\n")
  893. X#define IN_UNIT_LINE    MESS(3107, " in line %d of your how-to %s\n")
  894. X#define IN_INPUT    MESS(3108, "*** (detected after reading 1 line of your input file standard input)\n")
  895. X#define IN_INPUT_LINE    MESS(3109, "*** (detected after reading %d lines of your input file standard input)\n")
  896. X#define IN_FILE        MESS(3110, "*** (detected after reading 1 line of your input file %s)\n")
  897. X#define IN_FILE_LINE    MESS(3111, "*** (detected after reading %d lines of your input file %s)\n")
  898. X
  899. XHidden Procedure show_where(in_node, at, node)
  900. X    bool in_node, at; parsetree node; {
  901. X
  902. X    int line_no= in_node ? intval(curlino) : lino;
  903. X    show_line(in_node, at, node, line_no);
  904. X    if (!interactive && ifile == sv_ifile && !unit_file())
  905. X        show_f_line();
  906. X}
  907. X
  908. XHidden Procedure show_line(in_node, at, node, line_no)
  909. X    bool in_node, at; parsetree node; int line_no; {
  910. X    
  911. X    switch (cntxt) {
  912. X        case In_command: putmess(errfile, IN_COMMAND); break;
  913. X        case In_read: putmess(errfile, IN_READ); break;
  914. X        case In_edval: putmess(errfile, IN_EDVAL); break;
  915. X        case In_tarval:
  916. X            putSmess(errfile, IN_TARVAL, strval(errtname));
  917. X            break;
  918. X        case In_prmnv: putmess(errfile, IN_PRMNV); break;
  919. X        case In_wsgroup: putmess(errfile, IN_WSGROUP); break;
  920. X        case In_unit: show_howto(line_no); break;
  921. X        default:
  922. X            putstr(errfile, "???\n");
  923. X            return;
  924. X    }
  925. X    if (!in_node || Valid(node)) putstr(errfile, "    ");
  926. X    if (in_node) display(errfile, node, Yes);
  927. X    else pr_line(at);
  928. X}
  929. X
  930. XHidden value unitname(line_no) int line_no; {
  931. X    if (Valid(uname) && Is_text(uname)) {
  932. X        def_perm(last_unit, uname);
  933. X        errlino= line_no;
  934. X        return Permname(uname);
  935. X    }
  936. X    else free_perm(last_unit);
  937. X    return mk_text("");
  938. X}
  939. X
  940. XHidden Procedure show_howto(line_no) int line_no; {
  941. X    value name= unitname(line_no);
  942. X    if (line_no == 1)
  943. X        putSmess(errfile, IN_UNIT, strval(name));
  944. X    else
  945. X        putDSmess(errfile, IN_UNIT_LINE, line_no, strval(name));
  946. X    release(name);
  947. X}
  948. X
  949. XHidden bool unit_file() {
  950. X    value *aa;
  951. X    return cntxt == In_unit &&
  952. X        Valid(uname) && Is_text(uname) && p_exists(uname, &aa);
  953. X}
  954. X
  955. XHidden Procedure show_f_line() {
  956. X    if (f_lino == 1 && iname == Vnil) 
  957. X        putmess(errfile, IN_INPUT);
  958. X    else if (f_lino == 1)
  959. X        putSmess(errfile, IN_FILE, strval(iname));
  960. X    else if (iname == Vnil)
  961. X        putDSmess(errfile, IN_INPUT_LINE, f_lino, "");
  962. X    else
  963. X        putDSmess(errfile, IN_FILE_LINE, f_lino, strval(iname));
  964. X    if (iname != Vnil && i_lino > 0) {
  965. X        if (i_lino == 1)
  966. X            putmess(errfile, IN_INPUT);
  967. X        else
  968. X            putDSmess(errfile, IN_INPUT_LINE, i_lino, "");
  969. X    }
  970. X}
  971. X
  972. X#define PROBLEM        MESS(3112, "*** The problem is:")
  973. X
  974. XVisible Procedure syserr(m) int m; {
  975. X    static bool beenhere= No;
  976. X    if (beenhere) immexit(-1);
  977. X    beenhere= Yes;
  978. X    nline();
  979. X#ifdef DEBUG
  980. X#ifdef macintosh
  981. X    Debugger();
  982. X#endif
  983. X#endif
  984. X    putmess(errfile, MESS(3113, "*** Sorry, ABC system malfunction\n"));
  985. X    putmess(errfile, PROBLEM);
  986. X    putstr(errfile, " ");
  987. X    putmess(errfile, m); 
  988. X    putnewline(errfile);
  989. X    bye(-1);
  990. X}
  991. X
  992. X#ifndef macintosh
  993. X    /* MacABC uses an alert to make sure the user gets the message */
  994. X
  995. XVisible Procedure memexh() {
  996. X    static bool beenhere= No;
  997. X    if (beenhere) immexit(-1);
  998. X    beenhere= Yes;
  999. X    nline();
  1000. X    putmess(errfile, MESS(3114, "*** Sorry, memory exhausted"));
  1001. X/* show_where(Yes, Yes); don't know if in node or not; to fix */
  1002. X    putnewline(errfile);
  1003. X    bye(-1);
  1004. X}
  1005. X
  1006. X#endif /*macintosh*/
  1007. X
  1008. XHidden Procedure message(m1, m2, in_node, at, arg)
  1009. X    int m1, m2;
  1010. X    bool in_node, at; 
  1011. X    value arg;
  1012. X{
  1013. X    still_ok= No;
  1014. X    if (!mess_ok)
  1015. X        return;
  1016. X    nline();
  1017. X    putmess(errfile, m1);
  1018. X    show_where(in_node, at, curline);
  1019. X    putmess(errfile, PROBLEM);
  1020. X    putstr(errfile, " ");
  1021. X    putSmess(errfile, m2, Valid(arg) ? strval(arg) : "");
  1022. X    putnewline(errfile);
  1023. X    fflush(errfile);
  1024. X    at_nwl=Yes;
  1025. X}
  1026. X
  1027. X#define UNDERSTAND    MESS(3115, "*** There's something I don't understand")
  1028. X
  1029. X#define RESOLVE        MESS(3116, "*** There's something I can't resolve")
  1030. X
  1031. X#define COPE        MESS(3117, "*** Can't cope with problem")
  1032. X
  1033. X#define RECONCILE    MESS(3118, "*** Cannot reconcile the types")
  1034. X
  1035. XVisible Procedure pprerrV(m, v) int m; value v; {
  1036. X    if (still_ok)
  1037. X        message(UNDERSTAND, m, No, No, v);
  1038. X}
  1039. X
  1040. XVisible Procedure pprerr(m) int m; {
  1041. X    if (still_ok)
  1042. X        message(UNDERSTAND, m, No, No, Vnil);
  1043. X}
  1044. X
  1045. XVisible Procedure parerrV(m, v) int m; value v; {
  1046. X    if (still_ok)
  1047. X        message(UNDERSTAND, m, No, Yes, v);
  1048. X}
  1049. X
  1050. XVisible Procedure parerr(m) int m; {
  1051. X    if (still_ok)
  1052. X        message(UNDERSTAND, m, No, Yes, Vnil);
  1053. X}
  1054. X
  1055. XVisible Procedure fixerrV(m, v) int m; value v; {
  1056. X    if (still_ok)
  1057. X        message(RESOLVE, m, Yes, Yes, v);
  1058. X}
  1059. X
  1060. XVisible Procedure fixerr(m) int m; {
  1061. X    if (still_ok)
  1062. X        message(RESOLVE, m, Yes, Yes, Vnil);
  1063. X}
  1064. X
  1065. XVisible Procedure typerrV(m, v) int m; value v; {
  1066. X    if (still_ok)
  1067. X        message(RECONCILE, m, Yes, Yes, v);
  1068. X}
  1069. X
  1070. XVisible Procedure interrV(m, v) int m; value v; {
  1071. X    if (still_ok)
  1072. X        message(COPE, m, Yes, No, v);
  1073. X}
  1074. X
  1075. XVisible Procedure interr(m) int m; {
  1076. X    if (still_ok)
  1077. X        message(COPE, m, Yes, No, Vnil);
  1078. X}
  1079. X
  1080. XVisible Procedure checkerr() {
  1081. X    still_ok= No;
  1082. X    nline();
  1083. X    putmess(errfile, MESS(3119, "*** Your check failed"));
  1084. X    show_where(Yes, No, curline);
  1085. X    fflush(errfile);
  1086. X    at_nwl= Yes;
  1087. X}
  1088. X
  1089. XVisible Procedure int_signal() {
  1090. X    if (can_interrupt) {
  1091. X        interrupted= Yes; still_ok= No;
  1092. X        if (cntxt == In_wsgroup || cntxt == In_prmnv)
  1093. X            immexit(-1);
  1094. X    }
  1095. X    if (!interactive) {
  1096. X        if (ifile != stdin) fclose(ifile);
  1097. X        bye(1);
  1098. X    }
  1099. X    nline();
  1100. X    putmess(errfile, MESS(3120, "*** interrupted\n"));
  1101. X    fflush(errfile);
  1102. X    if (can_interrupt) {
  1103. X        if (cntxt == In_read) {
  1104. X            set_context(&read_context);
  1105. X            copy(uname);
  1106. X        }
  1107. X    }
  1108. X    at_nwl= Yes;
  1109. X}
  1110. X
  1111. XVisible bool testing= No;
  1112. X
  1113. XVisible Procedure bye(ex) int ex; {
  1114. X#ifdef GFX
  1115. X    if (gfx_mode != TEXT_MODE)
  1116. X        exit_gfx();
  1117. X#endif
  1118. X    at_nwl= Yes;
  1119. X/*    putperm(); */ /* shall be called via endall() */
  1120. X    endall();
  1121. X    immexit(ex);
  1122. X}
  1123. X
  1124. Xextern bool in_vtrm;
  1125. X
  1126. XVisible Procedure immexit(status) int status; {
  1127. X    if (in_vtrm)
  1128. X        endterm();
  1129. X    exit(status);
  1130. X}
  1131. X
  1132. XVisible Procedure initerr() {
  1133. X    still_ok= Yes; interrupted= No; curline= Vnil; curlino= zero;
  1134. X#ifdef TTY_ERRFILE
  1135. X    /* The idea of the following is, that we cannot use stderr
  1136. X     * for "abc cmd.file >out 2>err", since errors for READ
  1137. X     * commands must be visible for the user (who is entering
  1138. X     * them interactively, as reported in rd_interactive).
  1139. X     * The current solution is unix dependent; but stderr redirection
  1140. X     * seems impossible on non-unix anyway.
  1141. X     * When the first such system shows up it might be necessary
  1142. X     * to change all fprintf(errfile,...)'s to prerr's that print
  1143. X     * to the proper device (console or stderr file).
  1144. X     */
  1145. X    if (rd_interactive && (errfile= fopen("/dev/tty", "w")) == NULL)
  1146. X        errfile= stderr;
  1147. X#endif
  1148. X}
  1149. X
  1150. END_OF_FILE
  1151.   if test 8453 -ne `wc -c <'abc/bint3/i3err.c'`; then
  1152.     echo shar: \"'abc/bint3/i3err.c'\" unpacked with wrong size!
  1153.   fi
  1154.   # end of 'abc/bint3/i3err.c'
  1155. fi
  1156. if test -f 'abc/doc/abcintro.doc' -a "${1}" != "-c" ; then 
  1157.   echo shar: Will not clobber existing file \"'abc/doc/abcintro.doc'\"
  1158. else
  1159.   echo shar: Extracting \"'abc/doc/abcintro.doc'\" \(8974 characters\)
  1160.   sed "s/^X//" >'abc/doc/abcintro.doc' <<'END_OF_FILE'
  1161. XA SHORT INTRODUCTION TO THE ABC LANGUAGE
  1162. X
  1163. XThis article gives a quick overview of the programming language ABC
  1164. Xand its implementations, and gives a few examples of ABC programs.
  1165. XFull documentation about ABC is in the ABC Programmer's Handbook
  1166. X(details below).
  1167. X
  1168. XTHE LANGUAGE
  1169. XABC is an imperative language originally designed as a replacement for
  1170. XBASIC: interactive, very easy to learn, but structured, high-level,
  1171. Xand easy to use. ABC has been designed iteratively, and the present
  1172. Xversion is the 4th iteration. The previous versions were called B (not
  1173. Xto be confused with the predecessor of C).
  1174. X
  1175. XIt is suitable for general everyday programming, the sort of
  1176. Xprogramming that you would use BASIC, Pascal, or AWK for. It is not a
  1177. Xsystems-programming language. It is an excellent teaching language,
  1178. Xand because it is interactive, excellent for prototyping. It is much
  1179. Xfaster than Unix 'bc' for doing quick calculations.
  1180. X
  1181. XABC programs are typically very compact, around a quarter to a fifth
  1182. Xthe size of the equivalent Pascal or C program. However, this is not
  1183. Xat the cost of readability, on the contrary in fact (see the examples
  1184. Xbelow).
  1185. X
  1186. XABC is simple to learn due to the small number of types in the
  1187. Xlanguage (five). If you already know Pascal or something similar you
  1188. Xcan learn the whole language in an hour or so.  It is easy to use
  1189. Xbecause the data-types are very high-level.
  1190. X
  1191. XThe five types are:
  1192. X   numbers: unbounded length, with exact arithmetic the rule
  1193. X   texts (strings): also unbounded length
  1194. X   compounds: records without field names
  1195. X   lists: sorted collections of any one type of items (bags or multi-sets)
  1196. X   tables: generalised arrays with any one type of keys, any one type
  1197. X       of items (finite mappings).
  1198. X
  1199. XTHE ENVIRONMENT
  1200. XThe implementation includes a programming environment that makes
  1201. Xproducing programs very much easier, since it knows a lot about the
  1202. Xlanguage, and can therefore do much of the work for you. For instance,
  1203. Xif you type a W, the system suggests a command completion for you:
  1204. X    W?RITE ?
  1205. X
  1206. XIf that is what you want, you press [tab], and carry on typing the
  1207. Xexpression; if you wanted WHILE, you type an H, and the system changes
  1208. Xthe suggestion to match:
  1209. X    WH?ILE ?:
  1210. X
  1211. XThis mechanism works for commands you define yourself too. Similarly,
  1212. Xif you type an open bracket or quote, you get the closing bracket or
  1213. Xquote for free. You can ignore the suggestions if you want, and just
  1214. Xtype the commands full out.
  1215. X
  1216. XThere is support for workspaces for developing different programs.
  1217. XWithin each workspace variables are persistent, so that if you stop
  1218. Xusing ABC and come back later, your variables are still there as you
  1219. Xleft them. This obviates the need for file-handling facilities: there
  1220. Xis no conceptual difference between a variable and a file in ABC.
  1221. X
  1222. XThe language is strongly-typed, but without declarations. Types are
  1223. Xdetermined from context.
  1224. X
  1225. XEXAMPLES
  1226. XThe (second) best way to appreciate the power of ABC is to see some
  1227. Xexamples (the first is to use it). In what follows, >>> is the
  1228. Xprompt from ABC:
  1229. X
  1230. XNUMBERS
  1231. X    >>> WRITE 2**1000
  1232. X    107150860718626732094842504906000181056140481170553360744375038837
  1233. X    035105112493612249319837881569585812759467291755314682518714528569
  1234. X    231404359845775746985748039345677748242309854210746050623711418779
  1235. X    541821530464749835819412673987675591655439460770629145711964776865
  1236. X    42167660429831652624386837205668069376
  1237. X
  1238. X    >>> PUT 1/(2**1000) IN x
  1239. X    >>> WRITE 1 + 1/x
  1240. X    107150860718626732094842504906000181056140481170553360744375038837
  1241. X    035105112493612249319837881569585812759467291755314682518714528569
  1242. X    231404359845775746985748039345677748242309854210746050623711418779
  1243. X    541821530464749835819412673987675591655439460770629145711964776865
  1244. X    42167660429831652624386837205668069377
  1245. X
  1246. XTEXTS
  1247. X    >>> PUT ("ha " ^^ 3) ^ ("ho " ^^ 3) IN laugh
  1248. X    >>> WRITE laugh
  1249. X    ha ha ha ho ho ho 
  1250. X
  1251. X    >>> WRITE #laugh
  1252. X    18
  1253. X
  1254. X    >>> PUT "Hello! "^^1000 IN greeting
  1255. X    >>> WRITE #greeting
  1256. X    7000
  1257. X
  1258. XLISTS
  1259. X    >>> WRITE {1..10}
  1260. X    {1; 2; 3; 4; 5; 6; 7; 8; 9; 10}
  1261. X    >>> PUT {1..10} IN l
  1262. X    >>> REMOVE 5 FROM l
  1263. X    >>> INSERT 4 IN l
  1264. X    >>> INSERT pi IN l
  1265. X    >>> WRITE l
  1266. X    {1; 2; 3; 3.141592653589793; 4; 4; 6; 7; 8; 9; 10}
  1267. X
  1268. X    >>> PUT {} IN ll
  1269. X    >>> FOR i IN {1..3}:
  1270. X            INSERT {1..i} IN ll
  1271. X    >>> WRITE ll
  1272. X    {{1}; {1; 2}; {1; 2; 3}}
  1273. X    >>> FOR l IN ll:
  1274. X            WRITE l /
  1275. X    {1}
  1276. X    {1; 2}
  1277. X    {1; 2; 3}
  1278. X    >>> WRITE #ll
  1279. X    3
  1280. X
  1281. XCOMPOUNDS
  1282. X    >>> PUT ("Square root of 2", root 2) IN c
  1283. X    >>> WRITE c
  1284. X    ("Square root of 2", 1.414213562373095)
  1285. X    >>> PUT c IN name, value
  1286. X    >>> WRITE name
  1287. X    Square root of 2
  1288. X    >>> WRITE value
  1289. X    1.414213562373095
  1290. X
  1291. XA TELEPHONE LIST
  1292. XThis uses the table data-type. In use, tables resemble arrays:
  1293. X
  1294. X    >>> PUT {} IN tel
  1295. X    >>> PUT 4054 IN tel["Jennifer"]
  1296. X    >>> PUT 4098 IN tel["Timo"]
  1297. X    >>> PUT 4134 IN tel["Guido"]
  1298. X
  1299. X    >>> WRITE tel["Jennifer"]
  1300. X    4054
  1301. X
  1302. XYou can write all ABC values out. Tables are kept sorted on the keys:
  1303. X    >>> WRITE tel
  1304. X    {["Guido"]: 4134; ["Jennifer"]: 4054; ["Timo"]: 4098}
  1305. X
  1306. XThe keys function returns a list:
  1307. X    >>> WRITE keys tel
  1308. X    {"Guido"; "Jennifer"; "Timo"}
  1309. X
  1310. X    >>> FOR name IN keys tel:
  1311. X           WRITE name, ":", tel[name] /
  1312. X    Guido: 4134
  1313. X    Jennifer: 4054
  1314. X    Timo: 4098
  1315. X
  1316. XYou can define your own commands:
  1317. X
  1318. X    HOW TO DISPLAY t:
  1319. X       FOR name IN keys t:
  1320. X          WRITE name<<10, t[name] /
  1321. X
  1322. X    >>> DISPLAY tel
  1323. X    Guido      4134
  1324. X    Jennifer   4054
  1325. X    Timo       4098
  1326. X
  1327. XTo find the user of a given number, you can use a quantifier:
  1328. X    >>> IF SOME name IN keys tel HAS tel[name] = 4054:
  1329. X           WRITE name
  1330. X    Jennifer
  1331. X
  1332. XOr create the inverse table:
  1333. X    >>> PUT {} IN subscriber
  1334. X    >>> FOR name IN keys tel:
  1335. X           PUT name IN subscriber[tel[name]]
  1336. X
  1337. X    >>> WRITE subscriber[4054]
  1338. X    Jennifer
  1339. X
  1340. X    >>> WRITE subscriber
  1341. X    {[4054]: "Jennifer"; [4098]: "Timo"; [4134]: "Guido"}
  1342. X
  1343. XCommands and functions are polymorphic:
  1344. X    >>> DISPLAY subscriber
  1345. X    4054       Jennifer
  1346. X    4098       Timo
  1347. X    4134       Guido
  1348. X
  1349. XFunctions may return any type. Note that indentation is significant -
  1350. Xthere are no BEGIN-END's or { }'s:
  1351. X
  1352. X    HOW TO RETURN inverse t:
  1353. X       PUT {} IN inv
  1354. X       FOR k IN keys t:
  1355. X          PUT k IN inv[t[k]]
  1356. X       RETURN inv
  1357. X
  1358. X    >>> WRITE inverse tel
  1359. X    {[4054]: "Jennifer"; [4098]: "Timo"; [4134]: "Guido"}
  1360. X
  1361. X    >>> DISPLAY inverse inverse tel
  1362. X    Guido      4134
  1363. X    Jennifer   4054
  1364. X    Timo       4098
  1365. X
  1366. XA CROSS-REFERENCE INDEXER
  1367. X
  1368. X'Text files' are represented as tables of numbers to strings:
  1369. X
  1370. X    >>> DISPLAY poem
  1371. X    1         I've never seen a purple cow
  1372. X    2         I hope I never see one
  1373. X    3         But I can tell you anyhow
  1374. X    4         I'd rather see than be one
  1375. X
  1376. XThe following function takes such a document, and returns the
  1377. Xcross-reference index of the document: a table from words to lists of
  1378. Xline-numbers:
  1379. X
  1380. X    HOW TO RETURN index doc:
  1381. X       PUT {} IN where
  1382. X       FOR line.no IN keys doc:
  1383. X          TREAT LINE
  1384. X       RETURN where
  1385. X    TREAT LINE:
  1386. X       FOR word IN split doc[line.no]:
  1387. X          IF word not.in keys where:
  1388. X         PUT {} IN where[word]
  1389. X          INSERT line.no IN where[word]
  1390. X
  1391. XTREAT LINE here is a refinement, directly supporting
  1392. Xstepwise-refinement. 'split' is a function that splits a string into
  1393. Xits space-separated words:
  1394. X
  1395. X    >>> WRITE split "Hello world"
  1396. X    {[1]: "Hello"; [2]: "world"}
  1397. X
  1398. X    >>> DISPLAY index poem
  1399. X    But        {3}
  1400. X    I          {2; 2; 3}
  1401. X    I'd        {4}
  1402. X    I've       {1}
  1403. X    a          {1}
  1404. X    anyhow     {3}
  1405. X    be         {4}
  1406. X    can        {3}
  1407. X    cow        {1}
  1408. X    hope       {2}
  1409. X    never      {1; 2}
  1410. X    one        {2; 4}
  1411. X    purple     {1}
  1412. X    rather     {4}
  1413. X    see        {2; 4}
  1414. X    seen       {1}
  1415. X    tell       {3}
  1416. X    than       {4}
  1417. X    you        {3}
  1418. X
  1419. XMORE INFORMATION
  1420. XFull details of ABC and the implementations, along with many example
  1421. Xprograms are in the book "The ABC Programmer's Handbook" by Leo Geurts,
  1422. XLambert Meertens and Steven Pemberton, published by Prentice-Hall
  1423. X(ISBN 0-13-000027-2).
  1424. X
  1425. XSee also Steven Pemberton, "An Alternative Simple Language and
  1426. XEnvironment for PCs", IEEE Software, Vol. 4, No. 1, January 1987, pp.
  1427. X56-64.
  1428. X
  1429. XThere is an irregular newsletter available from us (address below),
  1430. Xand a mailing list for discussions; to join send your preferred email
  1431. Xaddress to abc-list-request@cwi.nl .
  1432. X
  1433. XIMPLEMENTATIONS
  1434. XThe sources for the Unix version have been posted to the
  1435. Xcomp.sources.unix group on Usenet; the binaries to comp.binaries.{mac,
  1436. Xibm.pc, atari.st}. They are also available from some servers, for
  1437. Xinstance by anonymous ftp from hp4nl.nluug.nl [192.16.202.2],
  1438. Xmcsun.eu.net [192.16.202.1], and uunet.uu.net [192.48.96.2], in the
  1439. Xdirectory {pub}/{programming}/languages/abc, or send the mail message
  1440. X    request: programming/languages/abc
  1441. X    topic: index
  1442. Xto info-server@hp4nl.nluug.nl, for a list of the available files, or use
  1443. X    topic: <filename>
  1444. Xto get one of the files.
  1445. X
  1446. XAs of this writing, the available files are:
  1447. X
  1448. X    index        for a list of all files available
  1449. X    abc.intro    for an overview of ABC
  1450. X            (also included with the implementations below)
  1451. X    abcst.arc    for the Atari ST version
  1452. X    abcpc.arc    for the IBM PC version
  1453. X    abc.mac.sit.hqx    for the Mac version
  1454. X    abc.unix.tar.Z    for the Unix version
  1455. X    README        for an explanation of how to unpack the above files
  1456. X
  1457. XADDRESS
  1458. X    ABC Implementations
  1459. X    CWI/AA
  1460. X    Kruislaan 413
  1461. X    1098 SJ AMSTERDAM
  1462. X    The Netherlands
  1463. X
  1464. X    Email: abc@cwi.nl
  1465. X
  1466. END_OF_FILE
  1467.   if test 8974 -ne `wc -c <'abc/doc/abcintro.doc'`; then
  1468.     echo shar: \"'abc/doc/abcintro.doc'\" unpacked with wrong size!
  1469.   fi
  1470.   # end of 'abc/doc/abcintro.doc'
  1471. fi
  1472. if test -f 'abc/ihdrs/i2par.h' -a "${1}" != "-c" ; then 
  1473.   echo shar: Will not clobber existing file \"'abc/ihdrs/i2par.h'\"
  1474. else
  1475.   echo shar: Extracting \"'abc/ihdrs/i2par.h'\" \(6116 characters\)
  1476.   sed "s/^X//" >'abc/ihdrs/i2par.h' <<'END_OF_FILE'
  1477. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  1478. X
  1479. X/***********************************************************************/
  1480. X
  1481. X#ifdef macintosh
  1482. X/* Avoid name conflict with standard header files: */
  1483. X#define compound b_compound
  1484. X#endif
  1485. X
  1486. X/* General parsing routines */
  1487. X
  1488. Xtypedef char *txptr;
  1489. X
  1490. X#define Eotc '\0'
  1491. X
  1492. X#define Char(tx)    (*(tx))
  1493. X#define Eol(tx)        (Char(tx) == '\n')
  1494. X#define Ceol(tx)    (Char(tx) == C_COMMENT || Eol(tx))
  1495. X#define Text(q)     (tx < q)
  1496. X
  1497. X#define Space(c)    ((c) == ' ' || (c) == '\t')
  1498. X
  1499. X#define Letter(c)    (islower(c))
  1500. X#define Cap(c)        (isupper(c))
  1501. X#define Dig(c)        (isdigit(c))
  1502. X
  1503. X#define Tagmark(tx) \
  1504. X        (Tagletmark(Char(tx)) || (Char(tx) == C_POINT && \
  1505. X        Tagletmark(Char(tx-1)) && Tagletmark(Char(tx+1)) ))
  1506. X#define Tagletmark(c) \
  1507. X    (Letter(c) || Dig(c) || (c) == C_APOSTROPHE || (c) == C_QUOTE)
  1508. X
  1509. X#define Keytagmark(tx) \
  1510. X    (keymark(tx) || Tagmark(tx))
  1511. X    
  1512. X#define Isexpr(c) \
  1513. X    (Letter(c) || (c) == C_OPEN || Dig(c) || (c) == C_POINT || \
  1514. X     (c) == C_APOSTROPHE || (c) == C_QUOTE || (c) == C_CUROPEN || \
  1515. X     (c) == C_ABOUT || (c) == C_TIMES || (c) == C_OVER || \
  1516. X     (c) == C_PLUS || (c) == C_MINUS || (c) == C_NUMBER)
  1517. X
  1518. Xtxptr fcol();
  1519. Xchar *keyword();
  1520. X
  1521. Xextern txptr tx, ceol, first_col;
  1522. Xextern intlet cur_ilev;
  1523. Xintlet ilev();
  1524. X
  1525. Xextern value res_cmdnames;
  1526. X
  1527. Xvalue cr_text();
  1528. X
  1529. X/* contexts: */
  1530. X#define In_share 's'
  1531. X#define In_ranger 'q'
  1532. X#define In_formal 'f'
  1533. X#define In_ref 'r'
  1534. X
  1535. X/* Expressions: */
  1536. X
  1537. Xparsetree expr();
  1538. Xparsetree singexpr();
  1539. X
  1540. X/* Targets: */
  1541. X
  1542. Xparsetree targ(); 
  1543. X
  1544. X/* Tests: */
  1545. X
  1546. Xparsetree test(); 
  1547. Xparsetree unp_test();
  1548. X
  1549. X/* Commands: */
  1550. X
  1551. Xparsetree cmd_suite();
  1552. Xparsetree cmd_seq();
  1553. Xparsetree ucmd_seq();
  1554. Xvalue tail_line();
  1555. X
  1556. X/* B units */
  1557. X
  1558. Xparsetree unit();
  1559. Xparsetree collateral();
  1560. Xparsetree compound();
  1561. Xparsetree idf();
  1562. Xextern literal idf_cntxt;
  1563. X
  1564. X/* signs */
  1565. X
  1566. X#define C_COLON        ':'
  1567. X#define S_COLON        ":"
  1568. X#define C_SEMICOLON    ';'
  1569. X#define S_SEMICOLON    ";"
  1570. X#define C_OPEN        '('
  1571. X#define S_OPEN        "("
  1572. X#define C_CLOSE        ')'
  1573. X#define S_CLOSE        ")"
  1574. X#define C_COMMA        ','
  1575. X#define S_COMMA        ","
  1576. X#define C_POINT        '.'
  1577. X#define S_POINT        "."
  1578. X#define C_APOSTROPHE    '\''
  1579. X#define S_APOSTROPHE    "'"
  1580. X#define C_QUOTE        '"'
  1581. X#define S_QUOTE        "\""
  1582. X#define C_CONVERT    '`'
  1583. X#define S_CONVERT    "`"
  1584. X#define C_CUROPEN    '{'
  1585. X#define S_CUROPEN    "{"
  1586. X#define C_CURCLOSE    '}'
  1587. X#define S_CURCLOSE    "}"
  1588. X#define C_SUB        '['
  1589. X#define S_SUB        "["
  1590. X#define C_BUS        ']'
  1591. X#define S_BUS        "]"
  1592. X#define C_BEHEAD    '@'
  1593. X#define S_BEHEAD    "@"
  1594. X#define C_CURTAIL    '|'
  1595. X#define S_CURTAIL    "|"
  1596. X#define C_ABOUT        '~'
  1597. X#define S_ABOUT        "~"
  1598. X#define C_PLUS        '+'
  1599. X#define S_PLUS        "+"
  1600. X#define C_MINUS        '-'
  1601. X#define S_MINUS        "-"
  1602. X#define C_TIMES        '*'
  1603. X#define S_TIMES        "*"
  1604. X#define C_OVER        '/'
  1605. X#define S_OVER        "/"
  1606. X#define C_JOIN        '^'
  1607. X#define S_JOIN        "^"
  1608. X#define C_NUMBER    '#'
  1609. X#define S_NUMBER    "#"
  1610. X#define C_LESS        '<'
  1611. X#define S_LESS        "<"
  1612. X#define C_EQUAL        '='
  1613. X#define S_EQUAL        "="
  1614. X#define C_GREATER    '>'
  1615. X#define S_GREATER    ">"
  1616. X#define S_POWER        "**"
  1617. X#define S_NUMERATOR    "*/"
  1618. X#define S_DENOMINATOR    "/\*"
  1619. X    /* \ is needed, else some C preprocessors see it as comment start! */
  1620. X#define S_REPEAT    "^^"
  1621. X#define S_LEFT_ADJUST    "<<"
  1622. X#define S_CENTER    "><"
  1623. X#define S_RIGHT_ADJUST    ">>"
  1624. X#define S_AT_MOST    "<="
  1625. X#define S_UNEQUAL    "<>"
  1626. X#define S_AT_LEAST    ">="
  1627. X#define S_RANGE        ".."
  1628. X
  1629. X#define C_COMMENT    '\\'
  1630. X#define S_COMMENT    "\\"
  1631. X#define C_NEWLINE    '/'
  1632. X#define S_NEWLINE    "/"
  1633. X
  1634. X#define open_sign    _sign_is(C_OPEN)
  1635. X#define point_sign    _sign_is(C_POINT)
  1636. X#define apostrophe_sign    _sign_is(C_APOSTROPHE)
  1637. X#define quote_sign    _sign_is(C_QUOTE)
  1638. X#define conv_sign    _sign_is(C_CONVERT)
  1639. X#define curlyopen_sign    _sign_is(C_CUROPEN)
  1640. X#define curlyclose_sign    _sign_is(C_CURCLOSE)
  1641. X#define sub_sign    _sign_is(C_SUB)
  1642. X#define behead_sign    _sign_is(C_BEHEAD)
  1643. X#define curtl_sign    _sign_is(C_CURTAIL)
  1644. X#define about_sign    _sign_is(C_ABOUT)
  1645. X#define plus_sign    _sign_is(C_PLUS)
  1646. X#define minus_sign    _sign_is(C_MINUS)
  1647. X#define number_sign    _sign_is(C_NUMBER)
  1648. X#define equals_sign    _sign_is(C_EQUAL)
  1649. X#define greater_sign    _sign_is(C_GREATER)
  1650. X
  1651. X#define comment_sign    _sign_is(C_COMMENT)
  1652. X
  1653. X#define reptext_sign    _sign2_is(S_REPEAT)
  1654. X#define leftadj_sign    _sign2_is(S_LEFT_ADJUST)
  1655. X#define center_sign    _sign2_is(S_CENTER)
  1656. X#define rightadj_sign    _sign2_is(S_RIGHT_ADJUST)
  1657. X#define at_most_sign    _sign2_is(S_AT_MOST)
  1658. X#define unequal_sign    _sign2_is(S_UNEQUAL)
  1659. X#define at_least_sign    _sign2_is(S_AT_LEAST)
  1660. X
  1661. X#define _sign_is(c) \
  1662. X    (Char(tx) == (c) ? (tx++, Yes) : No)
  1663. X#define _sign2_is(s) \
  1664. X    (Char(tx) == (s[0]) && Char(tx+1) == (s[1]) ? (tx+= 2, Yes) : No)
  1665. X
  1666. X#define nwl_sign    _nwl_sign()
  1667. X#define times_sign    _times_sign()
  1668. X#define over_sign    _over_sign()
  1669. X#define power_sign    _power_sign()
  1670. X#define numtor_sign    _numtor_sign()
  1671. X#define denomtor_sign    _denomtor_sign()
  1672. X#define join_sign    _join_sign()
  1673. X#define less_than_sign    _less_than_sign()
  1674. X#define greater_than_sign _greater_than_sign()
  1675. X
  1676. X/* keywords */
  1677. X
  1678. X#define atkw(kw, s)        (strcmp(kw, s) == 0)
  1679. X
  1680. X#define check_keyword(kw)    (atkw(kw, K_CHECK))
  1681. X#define delete_keyword(kw)     (atkw(kw, K_DELETE))
  1682. X#define insert_keyword(kw)     (atkw(kw, K_INSERT))
  1683. X#define pass_keyword(kw)    (atkw(kw, K_PASS))
  1684. X#define put_keyword(kw)     (atkw(kw, K_PUT))
  1685. X#define read_keyword(kw)     (atkw(kw, K_READ))
  1686. X#define remove_keyword(kw)     (atkw(kw, K_REMOVE))
  1687. X#define setrandom_keyword(kw)     (atkw(kw, K_SETRANDOM))
  1688. X#define write_keyword(kw)     (atkw(kw, K_WRITE))
  1689. X#define fail_keyword(kw)    (atkw(kw, K_FAIL))
  1690. X#define quit_keyword(kw)     (atkw(kw, K_QUIT))
  1691. X#define return_keyword(kw)    (atkw(kw, K_RETURN))
  1692. X#define report_keyword(kw)     (atkw(kw, K_REPORT))
  1693. X#define succeed_keyword(kw)     (atkw(kw, K_SUCCEED))
  1694. X#define if_keyword(kw)         (atkw(kw, K_IF))
  1695. X#define select_keyword(kw)     (atkw(kw, K_SELECT))
  1696. X#define while_keyword(kw)     (atkw(kw, K_WHILE))
  1697. X#define for_keyword(kw)     (atkw(kw, K_FOR))
  1698. X#define else_keyword(kw)     (atkw(kw, K_ELSE))
  1699. X#define not_keyword(kw)     (atkw(kw, K_NOT))
  1700. X#define some_keyword(kw)     (atkw(kw, K_SOME))
  1701. X#define each_keyword(kw)     (atkw(kw, K_EACH))
  1702. X#define no_keyword(kw)         (atkw(kw, K_NO))
  1703. X#define how_keyword(kw)     (atkw(kw, K_HOW))
  1704. X#define share_keyword(kw)     (atkw(kw, K_SHARE))
  1705. X
  1706. X#ifdef GFX
  1707. X
  1708. X#define spacefrom_keyword(kw)    (atkw(kw, K_SPACEFROM))
  1709. X#define linefrom_keyword(kw)    (atkw(kw, K_LINEFROM))
  1710. X#define clearscreen_keyword(kw)    (atkw(kw, K_CLEARSCREEN))
  1711. X
  1712. X#endif /* GFX */
  1713. END_OF_FILE
  1714.   if test 6116 -ne `wc -c <'abc/ihdrs/i2par.h'`; then
  1715.     echo shar: \"'abc/ihdrs/i2par.h'\" unpacked with wrong size!
  1716.   fi
  1717.   # end of 'abc/ihdrs/i2par.h'
  1718. fi
  1719. if test -f 'abc/lin/i1lta.c' -a "${1}" != "-c" ; then 
  1720.   echo shar: Will not clobber existing file \"'abc/lin/i1lta.c'\"
  1721. else
  1722.   echo shar: Extracting \"'abc/lin/i1lta.c'\" \(8268 characters\)
  1723.   sed "s/^X//" >'abc/lin/i1lta.c' <<'END_OF_FILE'
  1724. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  1725. X
  1726. X/* Access and update lists and tables */
  1727. X
  1728. X#include "b.h"
  1729. X#include "bint.h"
  1730. X#include "bobj.h"
  1731. X#include "i1tlt.h"
  1732. X
  1733. X#define INSERT_LIS    MESS(100, "inserting in non-list")
  1734. X#define INSERT_RAN    MESS(101, "cannot insert in large range")
  1735. X
  1736. X#define REMOVE_LIS    MESS(102, "removing from non-list")
  1737. X#define REMOVE_EMPTY    MESS(103, "removing from empty list")
  1738. X#define REMOVE_ENTRY    MESS(104, "removing non-existent list entry")
  1739. X#define REMOVE_RAN    MESS(105, "cannot remove from large range")
  1740. X
  1741. X#define RANGE_BIG    MESS(107, "exceedingly large range in display")
  1742. X
  1743. X#define REPLACE_TAB    MESS(115, "replacing in non-table")
  1744. X
  1745. X#define KEYS_TAB    MESS(116, "in keys t, t is not a table")
  1746. X
  1747. X#define SEL_TAB        MESS(117, "in t[k], t is not a table")
  1748. X#define SEL_EMPTY    MESS(118, "in t[k], t is empty")
  1749. X#define SEL_KEY        MESS(119, "in t[k], k is not a key of t")
  1750. X
  1751. X/* B lists */
  1752. X
  1753. X/* Rangedisplays will be set up as rangelists, only holding lwb and upb
  1754. X * iff they contain more than Minrange elements.
  1755. X * Minrange might even be just 1.
  1756. X */
  1757. X#define Minrange    (2)
  1758. X
  1759. XForward value spawn_range();
  1760. X
  1761. XVisible bool is_rangelist(v) value v; {
  1762. X    return (bool) Is_range(v);
  1763. X}
  1764. X
  1765. XVisible value list_elem(l, i) value l; intlet i; {
  1766. X    return List_elem(l, i);
  1767. X}
  1768. X
  1769. Xextern bool found_ok;
  1770. X
  1771. XVisible insert(v, ll) value v, *ll; {
  1772. X    intlet len; register value *lp, *lq;
  1773. X    intlet k; register intlet kk;
  1774. X    if (!Is_list(*ll)) {
  1775. X        interr(INSERT_LIS);
  1776. X        return;
  1777. X    }
  1778. X    if (Is_range(*ll)) {
  1779. X        value l = spawn_range(Lwb(*ll), Upb(*ll));
  1780. X        if (l == Vnil) {
  1781. X            interr(INSERT_RAN);
  1782. X            return;
  1783. X        }
  1784. X        release((value)(*ll));
  1785. X        *ll = l;
  1786. X    }
  1787. X    len= Length(*ll);
  1788. X    VOID found(list_elem, *ll, v, &k);
  1789. X    if (!found_ok) return;
  1790. X    if (Unique(*ll) && !Is_ELT(*ll)) {
  1791. X        xtndlt(ll, 1);
  1792. X        lq= Ats(*ll)+len; lp= lq-1;
  1793. X        for (kk= len; kk > k; kk--) *lq--= *lp--;
  1794. X        *lq= copy(v);
  1795. X    } else {
  1796. X        value w;
  1797. X        lp= Ats(*ll);
  1798. X        release(*ll);
  1799. X        *ll= grab(Lis, ++len);
  1800. X        lq= Ats(*ll);
  1801. X        for (kk= 0; kk < len; kk++) {
  1802. X            w= kk == k ? v : *lp++;
  1803. X            *lq++= copy (w);
  1804. X        }
  1805. X    }
  1806. X}
  1807. X
  1808. XVisible remove(v, ll) value v; value *ll; {
  1809. X    register value *lp, *lq;
  1810. X    intlet k, len;
  1811. X    if (!Is_list(*ll)) {
  1812. X        interr(REMOVE_LIS);
  1813. X        return;
  1814. X    }
  1815. X    if (Length(*ll) == 0) {
  1816. X        interr(REMOVE_EMPTY);
  1817. X        return;
  1818. X    }
  1819. X    if (Is_range(*ll)) {
  1820. X        value l = spawn_range(Lwb(*ll), Upb(*ll));
  1821. X        if (l == Vnil) {
  1822. X            interr(REMOVE_RAN);
  1823. X            return;
  1824. X        }
  1825. X        release((value)(*ll));
  1826. X        *ll = l;
  1827. X    }
  1828. X    if (!found(list_elem, *ll, v, &k))
  1829. X        interr(REMOVE_ENTRY);
  1830. X    else {
  1831. X        len= Length(*ll);
  1832. X        lp= Ats(*ll); /* lp[k] = v */
  1833. X        if (Unique(*ll)) {
  1834. X            release(*(lp+=k));
  1835. X            for (k= k; k < len; k++) {*lp= *(lp+1); lp++;}
  1836. X            xtndlt(ll, -1);
  1837. X        } else {
  1838. X            intlet kk= k;
  1839. X            lq= Ats(*ll);
  1840. X            release(*ll);
  1841. X            *ll= grab(Lis, --len);
  1842. X            lp= Ats(*ll);
  1843. X            for (k= 0; k < len; k++) {
  1844. X                if (k == kk) lq++;
  1845. X                *lp++= copy (*lq); lq++;
  1846. X            }
  1847. X        }
  1848. X    }
  1849. X}
  1850. X
  1851. XVisible value rangesize(lwb, upb) value lwb, upb; {
  1852. X    value d, r;
  1853. X    d = diff(upb, lwb);
  1854. X    r = sum(d, one);
  1855. X    release(d);
  1856. X    return r;
  1857. X}
  1858. X
  1859. XHidden value spawn_range(lo, hi) value lo, hi; {
  1860. X    value s;
  1861. X    value l, *lp;
  1862. X    value v, w;
  1863. X    int i;
  1864. X    intlet k, len;
  1865. X    bool enough_space();
  1866. X    
  1867. X    if (large(s = rangesize(lo, hi))
  1868. X        ||
  1869. X        (i = intval(s)) > Maxintlet
  1870. X        ||
  1871. X        !enough_space(Lis, len = (intlet) i)
  1872. X    ) {
  1873. X        release(s);
  1874. X        return Vnil;
  1875. X    }
  1876. X    release(s);
  1877. X    l = grab(Lis, len);
  1878. X    lp = Ats(l);
  1879. X    v = copy(lo);
  1880. X    for (k= 0; k < len; k++) {
  1881. X        *lp++ = copy(v);
  1882. X        v = sum(w = v, one);
  1883. X        release(w);
  1884. X    }
  1885. X    release(v);
  1886. X    return l;
  1887. X}
  1888. X
  1889. XHidden value mk_numrange(lo, hi) value lo, hi; {
  1890. X    value l, r;
  1891. X    
  1892. X    if (large(r= rangesize(lo, hi)) || intval(r) >= Minrange) {
  1893. X        l= grab(Ran, 2);
  1894. X        Lwb(l)= copy(lo);
  1895. X        Upb(l)= copy(hi);
  1896. X    }
  1897. X    else {
  1898. X        l= spawn_range(lo, hi);
  1899. X        if (l == Vnil)
  1900. X            interr(RANGE_BIG);
  1901. X    }
  1902. X    release(r);
  1903. X    return l;
  1904. X}
  1905. X
  1906. XHidden value i_range(lo, hi) value lo, hi; {
  1907. X    value r, res= Vnil;
  1908. X
  1909. X    if (compare(r= rangesize(lo, hi), one) < 0)
  1910. X        res= mk_elt();
  1911. X    else 
  1912. X        res= mk_numrange(lo, hi);
  1913. X    release(r);
  1914. X
  1915. X    return res;
  1916. X}
  1917. X
  1918. XHidden value mk_charrange(a, z) char a, z; {
  1919. X    value l= grab(Lis, (intlet) (z-a+1)); register value *ep= Ats(l);
  1920. X    char m[2];
  1921. X    m[1]= '\0';
  1922. X    for (m[0]= a; m[0] <= z; m[0]++) {
  1923. X        *ep++= mk_text(m);
  1924. X    }
  1925. X    return l;
  1926. X}
  1927. X
  1928. XHidden value c_range(lo, hi) value lo, hi; {
  1929. X    char a, z;
  1930. X
  1931. X    a= charval(lo); z= charval(hi);
  1932. X    if (z <= a-1) return mk_elt();
  1933. X    else return mk_charrange(a, z);
  1934. X}
  1935. X
  1936. XVisible value mk_range(v1, v2) value v1, v2; {
  1937. X    if (Is_text(v1)) return c_range(v1, v2);
  1938. X    else return i_range(v1, v2);
  1939. X}
  1940. X
  1941. XVisible relation range_comp(v, w) value v, w; {
  1942. X    /* Type(v) == Ran || Type(w) == Ran, and other type Is_list */
  1943. X    relation ci, cs;
  1944. X    value s, vs, ws, i, vi, wi, k;
  1945. X    
  1946. X    if (Is_range(v) && Is_range(w)) {
  1947. X        ci = compare(Lwb(v), Lwb(w));
  1948. X        if (ci == 0)
  1949. X            ci = compare(Upb(v), Upb(w));
  1950. X    }
  1951. X    else {
  1952. X        i = copy(one);
  1953. X        vs = size(v); ws = size(w);
  1954. X        if ((cs = compare(vs, ws)) <= 0)
  1955. X            s = copy(vs);
  1956. X        else
  1957. X            s = copy(ws);
  1958. X        release(vs); release(ws);
  1959. X        ci = 0;        /* for ELT */
  1960. X        while (numcomp(i, s) <= 0) {
  1961. X            vi = item(v, i); wi = item(w, i);
  1962. X            ci = compare(vi, wi);
  1963. X            release(vi); release(wi);
  1964. X            if (ci != 0)
  1965. X                break;
  1966. X            i = sum(k=i, one);
  1967. X            release(k);
  1968. X        }
  1969. X        release(i); release(s);
  1970. X        if (ci == 0)
  1971. X            ci = cs;
  1972. X    }
  1973. X    return ci;
  1974. X}
  1975. X/**********************************************************************/
  1976. X
  1977. X/* B tables */
  1978. X
  1979. XVisible value* key(v, k) value v; intlet k; { /* k in {0..size-1}; no copy */
  1980. X    return Key(v, k);
  1981. X}
  1982. X
  1983. XVisible value* assoc(v, k) value v; intlet k; { /* k in {0..size-1}; no copy */
  1984. X    return Assoc(v, k);
  1985. X}
  1986. X
  1987. XVisible value associate(v, k) value v; value k; {
  1988. X    value *p= adrassoc(v, k);
  1989. X    if (p != Pnil) return copy(*p);
  1990. X    interr(SEL_KEY);
  1991. X    return Vnil;
  1992. X}
  1993. X
  1994. XVisible value keys(ta) value ta; {
  1995. X    
  1996. X    if(!Is_table(ta)) {
  1997. X        interr(KEYS_TAB);
  1998. X        return grab(Lis, 0);
  1999. X    } else {
  2000. X        value li= grab(Lis, Length(ta)), *le, *te= (value *)Ats(ta);
  2001. X        int k, len= Length(ta);
  2002. X        le= (value *)Ats(li);
  2003. X        for (k= 0; k < len; k++) { *le++= copy(Cts(*te)); te++; }
  2004. X        return li;
  2005. X    }
  2006. X}
  2007. X
  2008. XVisible value key_elem(t, i) value t; intlet i; { /*The key of the i-th entry*/
  2009. X    return *Key(t, i);
  2010. X}
  2011. X
  2012. X/* adrassoc returns a pointer to the associate, rather than
  2013. X   the associate itself, so that the caller can decide if a copy
  2014. X   should be taken or not. If the key is not found, Pnil is returned. */
  2015. XVisible value* adrassoc(t, ke) value t, ke; {
  2016. X    intlet where;
  2017. X    if (Type(t) != Tab && Type(t) != ELT) {
  2018. X        interr(SEL_TAB);
  2019. X        return Pnil;
  2020. X    }
  2021. X    return found(key_elem, t, ke, &where) ? Assoc(t, where) : Pnil;
  2022. X}
  2023. X
  2024. XVisible Procedure uniq_assoc(ta, ke) value ta, ke; {
  2025. X    intlet k;
  2026. X    if (found(key_elem, ta, ke, &k)) {
  2027. X        uniql(Ats(ta)+k);
  2028. X        uniql(Assoc(ta,k));
  2029. X    } else syserr(MESS(120, "uniq_assoc called for non-existent table entry"));
  2030. X}
  2031. X
  2032. XVisible Procedure replace(v, ta, ke) value *ta, ke, v; {
  2033. X    intlet len; value *tp, *tq;
  2034. X    intlet k, kk;
  2035. X    uniql(ta);
  2036. X    if (Type(*ta) == ELT) (*ta)->type = Tab;
  2037. X    else if (Type(*ta) != Tab) {
  2038. X        interr(REPLACE_TAB);
  2039. X        return;
  2040. X    }
  2041. X    len= Length(*ta);
  2042. X    if (found(key_elem, *ta, ke, &k)) {
  2043. X        value *a;
  2044. X        uniql(Ats(*ta)+k);
  2045. X        a= Assoc(*ta, k);
  2046. X        /* uniql(a); */
  2047. X        release(*a);
  2048. X        *a= copy(v);
  2049. X        return;
  2050. X    } else if (found_ok) {
  2051. X        xtndlt(ta, 1);
  2052. X        tq= Ats(*ta)+len; tp= tq-1;
  2053. X        for (kk= len; kk > k; kk--) *tq--= *tp--;
  2054. X        *tq= grab(Com, 2);
  2055. X        Cts(*tq)= copy(ke);
  2056. X        Dts(*tq)= copy(v);
  2057. X    }
  2058. X}
  2059. X
  2060. XVisible bool in_keys(ke, tl) value ke, tl; {
  2061. X    intlet dummy;
  2062. X    if (Type(tl) == ELT) return No;
  2063. X    if (Type(tl) != Tab) syserr(KEYS_TAB);
  2064. X    return found(key_elem, tl, ke, &dummy);
  2065. X}
  2066. X
  2067. XVisible Procedure delete(tl, ke) value *tl, ke; {
  2068. X    intlet len, k; value *tp;
  2069. X    if (Type(*tl) == ELT) 
  2070. X        syserr(MESS(121, "deleting table entry from empty table"));
  2071. X    if (Type(*tl) != Tab)
  2072. X        syserr(MESS(122, "deleting table entry from non-table"));
  2073. X    tp= Ats(*tl); len= Length(*tl);
  2074. X    if (!found(key_elem, *tl, ke, &k))
  2075. X        syserr(MESS(123, "deleting non-existent table entry"));
  2076. X    if (Unique(*tl)) {
  2077. X        release(*(tp+=k));
  2078. X        for (k= k; k < len; k++) {*tp= *(tp+1); tp++;}
  2079. X        xtndlt(tl, -1);
  2080. X    } else {
  2081. X        intlet kk; value *tq= Ats(*tl);
  2082. X        release(*tl);
  2083. X        *tl= grab(Tab, --len);
  2084. X        tp= Ats(*tl);
  2085. X        for (kk= 0; kk < len; kk++) {
  2086. X            *tp++= copy (*tq); tq++;
  2087. X            if (kk == k) tq++;
  2088. X        }
  2089. X    }
  2090. X}
  2091. X
  2092. X#define Len(len) (len < 200 ? len : ((len-1)/8+1)*8)
  2093. X
  2094. XHidden Procedure
  2095. Xxtndlt(a, d)
  2096. X    value *a; intlet d;
  2097. X{
  2098. X    intlet len= Length(*a); intlet l1= Len(len), l2;
  2099. X    len+= d; l2= Len(len);
  2100. X    if (l1 != l2) {
  2101. X        regrab(a, l2);
  2102. X    }
  2103. X    (*a)->len= len;
  2104. X}
  2105. X
  2106. END_OF_FILE
  2107.   if test 8268 -ne `wc -c <'abc/lin/i1lta.c'`; then
  2108.     echo shar: \"'abc/lin/i1lta.c'\" unpacked with wrong size!
  2109.   fi
  2110.   # end of 'abc/lin/i1lta.c'
  2111. fi
  2112. echo shar: End of archive 16 \(of 25\).
  2113. cp /dev/null ark16isdone
  2114. MISSING=""
  2115. 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
  2116.     if test ! -f ark${I}isdone ; then
  2117.     MISSING="${MISSING} ${I}"
  2118.     fi
  2119. done
  2120. if test "${MISSING}" = "" ; then
  2121.     echo You have unpacked all 25 archives.
  2122.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2123. else
  2124.     echo You still must unpack the following archives:
  2125.     echo "        " ${MISSING}
  2126. fi
  2127. exit 0 # Just in case...
  2128.