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

  1. Subject:  v23i082:  ABC interactive programming environment, Part03/25
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 1668a0fa 4836bf62 71769fca ae7f365f
  5.  
  6. Submitted-by: Steven Pemberton <steven@cwi.nl>
  7. Posting-number: Volume 23, Issue 82
  8. Archive-name: abc/part03
  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/keys/keydef.c abc/stc/i2tca.c
  17. # Wrapped by rsalz@litchi.bbn.com on Mon Dec 17 13:27:52 1990
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. echo If this archive is complete, you will see the following message:
  20. echo '          "shar: End of archive 3 (of 25)."'
  21. if test -f 'abc/keys/keydef.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'abc/keys/keydef.c'\"
  23. else
  24.   echo shar: Extracting \"'abc/keys/keydef.c'\" \(29155 characters\)
  25.   sed "s/^X//" >'abc/keys/keydef.c' <<'END_OF_FILE'
  26. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1989. */
  27. X
  28. X/* abckeys -- create a key definitions file interactively */
  29. X
  30. X#include "b.h"
  31. X#include "bfil.h"
  32. X#include "bmem.h"
  33. X#include "feat.h"
  34. X#include "keys.h"
  35. X#include "getc.h"
  36. X#include "trm.h"
  37. X#include "release.h"
  38. X#include "keydef.h"
  39. X
  40. Xchar *getenv();
  41. X
  42. XVisible bool intrflag= No; /* not used; only definition needed here */
  43. X#ifdef SIGNAL
  44. X#include <signal.h>
  45. X#ifdef SIGTSTP
  46. XVisible bool suspflag= No; /* idem */
  47. X#endif
  48. X#endif
  49. XVisible bool in_vtrm= No;
  50. XVisible bool raw_newline= No;
  51. X
  52. XVisible Procedure immexit(status) int status; {
  53. X    endprocess(status);
  54. X}
  55. X
  56. X#ifndef NDEBUG
  57. XVisible bool dflag= No;
  58. X#endif
  59. X
  60. XVisible FILE *errfile= stderr;
  61. X
  62. X#ifdef VTRMTRACE
  63. XVisible FILE *vtrmfp= NULL;
  64. X    /* -V vtrmfile: trace typechecker on vtrmfile; abc only */
  65. X#endif
  66. X
  67. Xextern int errcount; /* Number of errors detected in key definitions */
  68. X
  69. Xextern string intr_char;
  70. X#ifdef CANSUSPEND
  71. Xextern string susp_char;
  72. X#endif
  73. X
  74. X/******************************************************************/
  75. X
  76. X#define SNULL ((string) NULL)
  77. X
  78. X/*
  79. X * definitions in deftab[0..nharddefs-1] are determined in ?1keys.c;
  80. X * hardcoded, read in from termcap, and/or taken from tty-chars
  81. X */
  82. X
  83. XVisible int nharddefs;
  84. X
  85. X/*
  86. X * definitions in deftab[nharddefs..nfiledefs-1] come from current keysfile
  87. X * (read in e1getc.c)
  88. X */
  89. X
  90. XHidden int nfiledefs;
  91. X
  92. X/*
  93. X * The new definitions the user supplies in this program are keep()ed
  94. X * in deftab[nfiledefs..ndefs-1]
  95. X */
  96. X
  97. X
  98. X/* 
  99. X * The table can than be written to the new keydefinitions file:
  100. X * first the definitions from the old keydefinitions file
  101. X * that are still valid, in [nharddefs.. nfiledefs-1],
  102. X * then the new ones, in [nfiledefs..ndefs-1].
  103. X */
  104. X
  105. Xtypedef struct oper {
  106. X    int code;        /* returned by inchar */
  107. X    string name;        /* operation name */
  108. X    int allowed;        /* may process */
  109. X    string descr;        /* long description */
  110. X} operation;
  111. X
  112. XHidden operation oplist[]= {
  113. X    {WIDEN,        S_WIDEN,    0, "Widen focus"},
  114. X    {EXTEND,    S_EXTEND,    0, "Extend focus"},
  115. X    {FIRST,        S_FIRST,    0, "Focus to first contained item"},
  116. X    {LAST,        S_LAST,        0, "Focus to last contained item"},
  117. X    {PREVIOUS,    S_PREVIOUS,    0, "Focus to previous item"},
  118. X    {NEXT,        S_NEXT,        0, "Focus to next item"},
  119. X    {UPLINE,    S_UPLINE,    0, "Focus to whole line above"},
  120. X    {DOWNLINE,    S_DOWNLINE,    0, "Focus to whole line below"},
  121. X    {UPARROW,    S_UPARROW,    0, "Make hole, move up"},
  122. X    {DOWNARROW,    S_DOWNARROW,    0, "Make hole, move down"},
  123. X    {LEFTARROW,    S_LEFTARROW,    0, "Make hole, move left"},
  124. X    {RITEARROW,    S_RITEARROW,    0, "Make hole, move right"},
  125. X    {GOTO,        S_GOTO,        0, "New focus at cursor position"},
  126. X    {ACCEPT,    S_ACCEPT,    0, "Accept suggestion, goto hole"},
  127. X    {NEWLINE,    S_NEWLINE,    0, "New line, or decrease indent"},
  128. X    {UNDO,        S_UNDO,        0, "Undo effect of last key pressed"},
  129. X    {REDO,        S_REDO,        0, "Redo last UNDOne key"},
  130. X    {COPY,        S_COPY,        0, "Copy focus to/from buffer"},
  131. X    {DELETE,    S_DELETE,    0, "Delete focus (to buffer if empty)"},
  132. X    {RECORD,    S_RECORD,    0, "Start/stop recording keystrokes"},
  133. X    {PLAYBACK,    S_PLAYBACK,    0, "Play back recorded keystrokes"},
  134. X    {REDRAW,    S_LOOK,        0, "Redisplay the screen"},
  135. X    {HELP,        S_HELP,        0, "Display summary of keys"},
  136. X    {EXIT,        S_EXIT,        0, "Finish unit or execute command"},
  137. X    {CANCEL,    S_INTERRUPT,    0, "Interrupt a computation"},
  138. X    {SUSPEND,    S_SUSPEND,    0, "Suspend the process"},
  139. X    {IGNORE,    S_IGNORE,    0, "Unbind this key sequence"},
  140. X    {TERMINIT,    S_TERMINIT,    0, "string to be sent to the screen at startup"},
  141. X    {TERMDONE,    S_TERMDONE,    0, "string to be sent to the screen upon exit"},
  142. X    /* last entry, op->name == SNULL : */
  143. X    {0,         SNULL,         0, SNULL} 
  144. X};
  145. X
  146. X#define ONULL ((operation *) NULL)
  147. X
  148. XHidden operation *findoperation(name) string name; {
  149. X    operation *op;
  150. X
  151. X    for (op= oplist; op->name != SNULL; op++) {
  152. X        if (strcmp(op->name, name) == 0)
  153. X            return op;
  154. X    }
  155. X    return ONULL;
  156. X}
  157. X
  158. XVisible Procedure confirm_operation(code, name) int code; string name; {
  159. X    operation *op;
  160. X
  161. X    for (op= oplist; op->name != SNULL; op++) {
  162. X        if (code == op->code) {
  163. X            op->allowed= 1;
  164. X            op->name= name; /* to be sure */
  165. X        }
  166. X    }
  167. X}
  168. X
  169. X#define Inchar()     (cvchar(trminput()))
  170. X
  171. X#define Printable(c)    (isascii(c) && (isprint(c) || (c) == ' '))
  172. X#define CRLF(c)        (Creturn(c) || Clinefeed(c))
  173. X#define Creturn(c)    ((c) == '\r')
  174. X#define Clinefeed(c)    ((c) == '\n')
  175. X#define Cbackspace(c)    ((c) == '\b')
  176. X#define Ctab(c)        ((c) == '\t')
  177. X#define Cspace(c)    ((c) == ' ')
  178. X
  179. X#define Empty(d)    (strlen(d) == 0)
  180. X#define Val(d)        ((d) != SNULL && !Empty(d))
  181. X
  182. X#define Equal(s1, s2)    (strcmp(s1, s2) == 0)
  183. X
  184. X/****************************************************************************/
  185. X
  186. XHidden string newfile= SNULL;    /* name for new keydefinitions file */
  187. X
  188. Xmain(argc, argv) int argc; char *argv[]; {
  189. X    string arg0= argv[0];
  190. X    string cp;
  191. X    int c;
  192. X
  193. X    cp= strrchr(arg0, DELIM);
  194. X    if (cp)
  195. X        arg0= cp+1;
  196. X
  197. X    initfmt();
  198. X
  199. X    if (argc != 1) /* no arguments allowed */
  200. X        usage(arg0);
  201. X
  202. X    init();
  203. X    
  204. X    checking();
  205. X    
  206. X    process();
  207. X    
  208. X    fini();
  209. X    
  210. X    exit(0);
  211. X}
  212. X
  213. X/****************************************************************************/
  214. X
  215. X/* immediate exit */
  216. X
  217. XHidden Procedure usage(name) string name; {
  218. X    putSstr(errfile, "*** Usage: %s\n", name);
  219. X    exit(1);
  220. X}
  221. X
  222. XHidden Procedure endprocess(status) int status; {
  223. X    fini_term();
  224. X    exit(status);
  225. X}
  226. X
  227. XVisible Procedure syserr(s) string s; {
  228. X    putSstr(errfile, "*** System error: %s\n", s);
  229. X    endprocess(-1);
  230. X}
  231. X
  232. XVisible Procedure memexh() {
  233. X    static bool beenhere= No;
  234. X    if (beenhere) endprocess(-1);
  235. X    beenhere= Yes;
  236. X    putstr(errfile, "*** Sorry, memory exhausted\n");
  237. X    endprocess(-1);
  238. X}
  239. X
  240. X/****************************************************************************/
  241. X
  242. XHidden Procedure init() {
  243. X#ifdef MEMTRACE
  244. X    initmem();
  245. X#endif
  246. X
  247. X    initmess();
  248. X    initfile();
  249. X    initkeys();        /* fills deftab and ndefs in e1getc.c */
  250. X    nfiledefs= ndefs;
  251. X    
  252. X    init_newfile();
  253. X    init_ignore();
  254. X    init_strings();
  255. X    init_term();
  256. X    init_bindings();
  257. X    init_buffers();
  258. X}
  259. X
  260. XHidden Procedure fini() {
  261. X#ifdef MEMTRACE
  262. X    fini_buffers();
  263. X#endif
  264. X    fini_term();
  265. X}
  266. X
  267. X
  268. X/****************************************************************************/
  269. X
  270. XHidden Procedure checking() {
  271. X    if (!Val(intr_char)) {
  272. X        putdata(E_INTERRUPT, 0);
  273. X        endprocess(1);
  274. X    }
  275. X}
  276. X
  277. X/****************************************************************************/
  278. X
  279. X#define DNULL (tabent *) NULL
  280. X
  281. XHidden tabent *finddefentry(code) int code;  {
  282. X    tabent *d;
  283. X
  284. X    for (d= deftab+ndefs-1; d >= deftab; d--) {
  285. X        if (code == d->code)
  286. X            return d;
  287. X    }
  288. X    return DNULL;
  289. X}
  290. X
  291. XHidden tabent *terminit= DNULL;
  292. XHidden tabent *termdone= DNULL;
  293. X
  294. XHidden Procedure init_strings() {
  295. X    terminit= finddefentry(TERMINIT);
  296. X    termdone= finddefentry(TERMDONE);
  297. X}
  298. X
  299. X/* Output a string to the terminal */
  300. X
  301. XHidden Procedure outstring(str) string str; {
  302. X    fputs(str, stdout);
  303. X    putnewline(stdout);
  304. X    fflush(stdout);
  305. X}
  306. X
  307. XHidden bool inisended= No;
  308. X
  309. XHidden Procedure sendinistring() {
  310. X    if (terminit != DNULL && Val(terminit->def)) {
  311. X        outstring(terminit->def);
  312. X        redrawscreen();
  313. X        inisended= Yes;
  314. X    }
  315. X    else clearwindow();
  316. X}
  317. X
  318. XHidden Procedure sendendstring() {
  319. X    if (!inisended)
  320. X        return;
  321. X    if (termdone != DNULL && Val(termdone->def)) {
  322. X        outstring(termdone->def);
  323. X    }
  324. X}
  325. X
  326. X/****************************************************************************/
  327. X
  328. X/* screen stuff */
  329. X
  330. XHidden struct screen {
  331. X    int yfirst, ylast;
  332. X    int width;
  333. X    int y, x;
  334. X} win;
  335. X
  336. XHidden Procedure init_term() {
  337. X    int height, width, flags;
  338. X    int err;
  339. X
  340. X    err= trmstart(&height, &width, &flags);
  341. X    if (err != TE_OK) {
  342. X        if (err <= TE_DUMB)
  343. X            putstr(errfile,
  344. X"*** Bad $TERM or termcap, or dumb terminal\n");
  345. X        else if (err == TE_BADSCREEN)
  346. X            putstr(errfile,
  347. X"*** Bad SCREEN environment\n");
  348. X        else
  349. X            putstr(errfile,
  350. X"*** Cannot reach keyboard or screen\n");
  351. X
  352. X        exit(1);
  353. X    }
  354. X    in_vtrm= Yes;
  355. X    raw_newline= Yes;
  356. X    win.yfirst= 0;
  357. X    win.ylast= height-1;
  358. X    win.width= width-1;
  359. X    win.y= win.yfirst;
  360. X    win.x= 0;
  361. X    
  362. X#define MINWIDTH 75
  363. X#define MINHEIGHT 24
  364. X
  365. X    if (width < MINWIDTH || height < MINHEIGHT) {
  366. X        put2Dstr(errfile,
  367. X"*** Sorry, too small screen size; needed at least %dx%d; giving up\n",
  368. X        MINHEIGHT, MINWIDTH);
  369. X        endprocess(1);
  370. X    }
  371. X
  372. X    if (errcount != 0) /* errors found reading definitions */
  373. X        asktocontinue(win.ylast);
  374. X#ifdef DUMPKEYS
  375. X    if (dflag && errcount == 0) 
  376. X        asktocontinue(win.ylast);
  377. X#endif
  378. X    clearscreen(); 
  379. X}
  380. X
  381. X/* 
  382. X * clearing the screen is done by scrolling instead of putting empty data
  383. X * because there are systems (MSDOS, ANSI) where the latter leaves rubbish
  384. X * on the screen
  385. X */
  386. XHidden Procedure clearscreen() {
  387. X    trmscrollup(0, win.ylast, win.ylast + 1);
  388. X}
  389. X
  390. XHidden int hlp_yfirst;
  391. XHidden int hlp_nlines;
  392. X
  393. X#define Upd_bindings() putbindings(hlp_yfirst)
  394. X
  395. XHidden Procedure init_bindings() {
  396. X    setup_bindings(win.width, &hlp_nlines);
  397. X}
  398. X
  399. XHidden int nscrolls= 0;
  400. X
  401. XHidden Procedure set_windows(yfirst) int yfirst; {
  402. X    hlp_yfirst= yfirst;
  403. X    win.yfirst= hlp_yfirst + hlp_nlines + 1;
  404. X    win.y= win.yfirst;
  405. X    win.x= 0;
  406. X    nscrolls= 0;
  407. X}
  408. X
  409. XHidden Procedure clearwindow() {
  410. X    trmputdata(win.yfirst, win.ylast, 0, "");
  411. X    win.y= win.yfirst;
  412. X    win.x= 0;
  413. X    nscrolls= 0;
  414. X    trmsync(win.y, win.x);
  415. X}
  416. X
  417. XHidden Procedure redrawscreen() {
  418. X    bind_all_changed();
  419. X    clearscreen();
  420. X    set_windows(0);
  421. X    Upd_bindings();
  422. X}
  423. X
  424. XHidden Procedure fini_term() {
  425. X    if (in_vtrm) {
  426. X#ifdef MEMTRACE
  427. X        fini_bindings();
  428. X#endif
  429. X        nextline();
  430. X        sendendstring();
  431. X        trmend();
  432. X    }
  433. X    in_vtrm= No;
  434. X}
  435. X
  436. X/* TODO: indent > width-1 */
  437. X
  438. X#define Too_width(data, bound) (strlen(data) > (bound))
  439. X
  440. XHidden Procedure putdata(data, indent) string data; int indent; {
  441. X    static string buf= SNULL;
  442. X    int width= win.width;
  443. X    int len;
  444. X    string q;
  445. X
  446. X    if (data == SNULL)
  447. X        return;
  448. X    if (buf == SNULL)
  449. X        buf= (string) getmem((unsigned) width+1);
  450. X
  451. X    if (indent == 0 && strlen(data) > 0 && win.x > 0)
  452. X        nextline();
  453. X
  454. X    while (Too_width(data, width-indent)) {
  455. X        q= data + width-1-indent;
  456. X        while (q - data > 0 && *q != ' ')
  457. X            --q;
  458. X        len= q - data;
  459. X        if (len > 0 && len < width-indent)
  460. X            ++len;
  461. X        else
  462. X            len= width-indent;
  463. X        strncpy(buf, data, len);
  464. X        buf[len]= '\0';
  465. X        data+= len;
  466. X        trmputdata(win.y, win.y, indent, buf);
  467. X        nextline();
  468. X        indent= 0;
  469. X    }
  470. X    trmputdata(win.y, win.y, indent, data);
  471. X    win.x= indent+strlen(data);
  472. X    trmsync(win.y, win.x);
  473. X}
  474. X
  475. X#define CONTINUE_GIVEN (nscrolls == 1)
  476. X
  477. XHidden Procedure nextline() {
  478. X    if (win.y == win.ylast-1) {
  479. X        if (nscrolls == 0 || nscrolls == (win.ylast - win.yfirst)) {
  480. X            asktocontinue(win.ylast);
  481. X            nscrolls= 0;
  482. X        }
  483. X        trmscrollup(win.yfirst, win.ylast, 1);
  484. X        nscrolls++;
  485. X    }
  486. X    else {
  487. X        win.y++;
  488. X        nscrolls= 0;
  489. X    }
  490. X    trmsync(win.y, win.x= 0);
  491. X}
  492. X
  493. X#define SOBIT 0200
  494. X#define MAXBUFFER 81
  495. X
  496. XHidden string mkstandout(data) string data; {
  497. X    static char buffer[MAXBUFFER];
  498. X    string cp;
  499. X    
  500. X    strcpy(buffer, data);
  501. X    for (cp= buffer; *cp; cp++)
  502. X        *cp |= SOBIT;
  503. X
  504. X    return (string) buffer;
  505. X}
  506. X
  507. X#define CONTINUE_PROMPT "Press [SPACE] to continue "
  508. X
  509. XHidden Procedure asktocontinue(y) int y; {
  510. X    int c;
  511. X    string data= mkstandout(CONTINUE_PROMPT);
  512. X
  513. X    trmputdata(y, y, 0, data);
  514. X        /*
  515. X         * putdata() isn't called to avoid a call of nextline();
  516. X         * there is no harm in that if the data can fit on one line
  517. X         */
  518. X    trmsync(y, strlen(data));
  519. X    for (;;) {
  520. X        c= Inchar();
  521. X        if (Cspace(c) || c == EOF)
  522. X            break;
  523. X        trmbell();
  524. X    }
  525. X    trmputdata(y, y, 0, "");
  526. X}
  527. X
  528. X/****************************************************************************/
  529. X
  530. X/* buffer stuff */
  531. X
  532. XHidden char fmtbuf[BUFSIZ];    /* to make formatted messages */
  533. X
  534. XHidden bufadm definpbuf;    /* to save definitions from input */
  535. XHidden bufadm repinpbuf;    /* to save representations from input */
  536. XHidden bufadm reprbuf;        /* to save reprs from defs */
  537. X
  538. XHidden Procedure init_buffers() {
  539. X    bufinit(&definpbuf);
  540. X    bufinit(&repinpbuf);
  541. X    bufinit(&reprbuf);
  542. X}
  543. X
  544. X#ifdef MEMTRACE
  545. X
  546. XHidden Procedure fini_buffers() {
  547. X    buffree(&definpbuf);
  548. X    buffree(&repinpbuf);
  549. X    buffree(&reprbuf);
  550. X}
  551. X
  552. X#endif
  553. X
  554. XHidden string getbuf(bp) bufadm *bp; {
  555. X    bufpush(bp, '\0');
  556. X    return (string) bp->buf;
  557. X}
  558. X
  559. X/****************************************************************************/
  560. X
  561. X#ifndef NULL_EXTENDED
  562. X
  563. X#define MAXAVAILABLE 100
  564. X
  565. XHidden int available[MAXAVAILABLE];    /* save chars from trmavail() */
  566. XHidden int navailable= 0;        /* nr of available chars */
  567. XHidden int iavailable= 0;        /* next available character */
  568. X
  569. X/*
  570. X * attempt to recognize key sequences using trmavail();
  571. X * it works if the user presses the keys one after another not too fast;
  572. X * be careful: if trmavail() isn't implemented it still has to work!
  573. X * returns -1 for EOF, 0 for extended chars, >0 for 'normal' chars.
  574. X */
  575. X
  576. XHidden int inchar() {
  577. X    int c;
  578. X    
  579. X    if (iavailable != navailable) {        /* char in buffer */
  580. X        c= available[iavailable++];
  581. X        if (iavailable == navailable)
  582. X            iavailable= navailable= 0;
  583. X        return c;
  584. X    }
  585. X
  586. X    c= Inchar();    /* returns -1 or >0 */
  587. X
  588. X    while (c != EOF && trmavail() == 1) {
  589. X        available[navailable++]= c;
  590. X        c= Inchar();
  591. X    }
  592. X    if (navailable == 0)            /* no char available */
  593. X        return c;
  594. X    else {
  595. X        available[navailable++]= c;
  596. X        return 0;
  597. X    }
  598. X}
  599. X
  600. XHidden string findrepr(def) string def; {
  601. X    tabent *d;
  602. X    string findoldrepr();
  603. X    string rep;
  604. X
  605. X    for (d= deftab+ndefs-1; d >= deftab; d--) {
  606. X        if (Val(d->def) && Equal(d->def, def) && Val(d->rep))
  607. X            return d->rep;
  608. X    }
  609. X    return findoldrepr(def);
  610. X}
  611. X
  612. X/*
  613. X * try to find a representation for thw whole sequence in the buffer
  614. X */
  615. X
  616. XHidden bool knownkeysequence(key, rep) string *key, *rep; {
  617. X    string pkey;
  618. X    int n;
  619. X
  620. X    if (navailable < 2)            /* no sequence */
  621. X        return No;
  622. X
  623. X    /* make sequence */
  624. X    *key= pkey= (string) getmem((unsigned) (navailable+1));
  625. X    for (n= 0; n < navailable; n++)
  626. X        *pkey++= available[n];
  627. X    *pkey= '\0';
  628. X
  629. X    if ((*rep= findrepr(*key)) != SNULL) {
  630. X        iavailable= navailable= 0;     /* empty buffer */
  631. X        return Yes;
  632. X    }
  633. X    freemem((ptr) *key);
  634. X    return No;
  635. X}
  636. X
  637. X#endif /* ! NULL_EXTENDED */
  638. X
  639. X/****************************************************************************/
  640. X
  641. X/*
  642. X * get a key sequence from input, delimited by \r (or \n)
  643. X * if you want that delimiter in your binding,
  644. X * enclose the entire binding with single or double quotes
  645. X */
  646. X
  647. X#define NEW_KEY    "Press new key(s) for %s (%s)"
  648. X
  649. X#define Quote(c) ((c) == '\"' || (c) == '\'')
  650. X
  651. XHidden string ask_definition(op, prepr) operation *op; string *prepr; {
  652. X    int c;
  653. X    string def;
  654. X    string repr;
  655. X    bufadm *dp= &definpbuf;
  656. X    bufadm *rp= &reprbuf;
  657. X    char quot_repr[20];
  658. X    bool quoting= No;
  659. X    bool first= Yes;
  660. X
  661. X    sprintf(fmtbuf, NEW_KEY, op->name, op->descr);
  662. X    putdata(fmtbuf, 0);
  663. X    nextline();
  664. X
  665. X    bufreinit(dp);
  666. X    bufreinit(rp);
  667. X
  668. X    for (;; first= No) {
  669. X
  670. X#ifdef NULL_EXTENDED
  671. X
  672. X        c= Inchar();
  673. X        
  674. X#else /* ! NULL_EXTENDED */
  675. X
  676. X        c= inchar();
  677. X        if (c == 0) { /* there are chars in the buffer */
  678. X            if (knownkeysequence(&def, &repr)) {
  679. X                savputrepr(rp, repr);    /* save and put repr */
  680. X                bufcpy(dp, def);    /* save key */
  681. X                freemem((ptr) def);
  682. X                continue;
  683. X            }
  684. X            else c= inchar(); /* get char out of buffer */
  685. X                      /* note: c != 0 */
  686. X        }
  687. X
  688. X#endif /* ! NULL_EXTENDED */
  689. X
  690. X        if (c == EOF)
  691. X            break;
  692. X        if (Eok(c)) {        /* end of key sequence */
  693. X            if (!quoting)
  694. X                break;
  695. X            if (Equal(repr, quot_repr)) {
  696. X                    /* pop quote from key buffer: */    
  697. X                --(dp->ptr);
  698. X                    /* pop quote from rep buffer: */
  699. X                rp->ptr-= strlen(repr) + 1;
  700. X                break;
  701. X            }
  702. X        }
  703. X        if (first && Quote(c)) {
  704. X            quoting= Yes;
  705. X            repr= reprchar(c);
  706. X            strcpy(quot_repr, repr);
  707. X            putdata(repr, win.x);    /* no save */
  708. X            putdata(" ", win.x);    
  709. X            repr= "";        /* to prevent equality above */
  710. X        }
  711. X        else {
  712. X            repr= reprchar(c);
  713. X            savputrepr(rp, repr);    /* save and put repr */
  714. X            bufpush(dp, c);        /* save key */
  715. X        }
  716. X    }
  717. X    *prepr= getbuf(rp);
  718. X
  719. X    return getbuf(dp);
  720. X}
  721. X
  722. X/* save and put the representation */
  723. X
  724. XHidden Procedure savputrepr(rp, repr) bufadm *rp; string repr; {
  725. X    if (strlen(repr) > 0) {
  726. X        /* save */
  727. X        if (rp->ptr != rp->buf) /* not the first time */
  728. X            bufpush(rp, ' '); 
  729. X        bufcpy(rp, repr);
  730. X
  731. X        /* put */
  732. X        putdata(repr, win.x);
  733. X        putdata(" ", win.x);
  734. X    }
  735. X}
  736. X
  737. XHidden string new_definition(op, prepr) operation *op; string *prepr; {
  738. X    string def;
  739. X
  740. X    if (op == ONULL)
  741. X        return SNULL;
  742. X    for (;;) {
  743. X        def= ask_definition(op, prepr);
  744. X        if (op->code < 0) /* string-valued */
  745. X            return def;
  746. X        if (!illegal(def))
  747. X            return def;
  748. X    }
  749. X}
  750. X
  751. XHidden bool illegal(def) string def; {
  752. X    if (Empty(def))
  753. X        return No;
  754. X    if  (Printable(*def)) {
  755. X        sprintf(fmtbuf, E_ILLEGAL, *def);
  756. X        putdata(fmtbuf, 0);
  757. X        return Yes;
  758. X    }
  759. X    for (; *def; def++) {
  760. X        if (is_spchar(*def)) {
  761. X            putdata(E_SPCHAR, 0);
  762. X            return Yes;
  763. X        }
  764. X    }
  765. X    return No;
  766. X}
  767. X
  768. X/****************************************************************************/
  769. X
  770. X/*
  771. X * getinput() reads characters from input delimited by \r or \n 
  772. X */
  773. XHidden string getinput(bp)  bufadm *bp; {
  774. X    int c;
  775. X    char echo[2];
  776. X
  777. X    echo[1]= '\0';
  778. X    bufreinit(bp);
  779. X    for (;;) {
  780. X        c= Inchar();
  781. X        if (c == EOF || CRLF(c))
  782. X            break;
  783. X
  784. X        if (Cbackspace(c)) {
  785. X            if (bp->ptr == bp->buf)        /* no chars */
  786. X                trmbell();
  787. X            else {
  788. X                if (win.x == 0) {    /* begin of line */
  789. X                    --win.y;
  790. X                    win.x= win.width;
  791. X                }
  792. X                putdata("", --win.x);
  793. X                --(bp->ptr);    /* pop character from buffer */
  794. X            }
  795. X        }
  796. X        else if (Printable(c)) {
  797. X            echo[0]= c;
  798. X            putdata(echo, win.x);
  799. X            bufpush(bp, c);
  800. X        }
  801. X        else trmbell();
  802. X    }
  803. X    return getbuf(bp);
  804. X}
  805. X
  806. X/****************************************************************************/
  807. X
  808. X#define ALPHA_REP "Enter an alpha-numeric representation for this definition"
  809. X
  810. X#define DFLT_REP " [default %s] "
  811. X
  812. XHidden string ask_representation(dfltrep) string dfltrep; {
  813. X    int len= strlen(DFLT_REP) + strlen(dfltrep);
  814. X    char *dflt= (char *) getmem((unsigned) (len+1));
  815. X    /* we don't use fmtbuf, because the 'dfltrep' can be very long */
  816. X
  817. X    putdata(ALPHA_REP, 0);
  818. X    sprintf(dflt, DFLT_REP, dfltrep);
  819. X    putdata(dflt, 0);
  820. X    freemem((ptr) dflt);
  821. X    return getinput(&repinpbuf);
  822. X}
  823. X
  824. XHidden string new_representation(dfltrep, def) string dfltrep, def; {
  825. X    string repr;
  826. X
  827. X    for (;;) {
  828. X        repr= ask_representation(dfltrep);
  829. X
  830. X        if (Empty(repr)) /* accept default */
  831. X            return dfltrep;
  832. X        if (unlawful(repr) || rep_in_use(repr, def))
  833. X            continue; 
  834. X        return repr;
  835. X    }
  836. X}
  837. X
  838. XHidden string representation(def) string def; {
  839. X    bufadm *rp= &reprbuf;
  840. X    string repr;
  841. X
  842. X    bufreinit(rp);
  843. X
  844. X    for (; *def; def++) {
  845. X        repr= reprchar(*def);
  846. X        if (strlen(repr) > 0) {
  847. X            bufcpy(rp, repr);
  848. X            if (*(def+1) != '\0') {
  849. X                bufpush(rp, ' ');
  850. X            }
  851. X        }
  852. X    }
  853. X    return getbuf(rp);
  854. X}
  855. X
  856. XHidden bool unlawful(rep) string rep; {
  857. X    for (; *rep; rep++) {
  858. X        if (!Printable(*rep)) {
  859. X            putdata(E_UNLAWFUL, 0);
  860. X            return Yes;
  861. X        }
  862. X    }
  863. X
  864. X    return No;
  865. X}
  866. X
  867. XHidden bool rep_in_use(rep, def) string rep, def; {
  868. X    tabent *d;
  869. X
  870. X    for (d= deftab; d < deftab+ndefs; d++) {
  871. X        if (Val(d->rep) && Equal(rep, d->rep)
  872. X            &&
  873. X            Val(d->def) && !Equal(def, d->def)
  874. X            &&
  875. X            d->code != DELBIND
  876. X           ) {
  877. X            sprintf(fmtbuf, E_IN_USE, d->name);
  878. X            putdata(fmtbuf, 0); 
  879. X            return Yes;
  880. X        }
  881. X    }
  882. X    return No;
  883. X}
  884. X
  885. X/****************************************************************************/
  886. X
  887. XHidden Procedure keep(code, name, def, rep) int code; string name, def, rep; {
  888. X    if (ndefs == MAXDEFS) {
  889. X        putdata(E_TOO_MANY, 0);
  890. X        return;
  891. X    }
  892. X    undefine(code, def);
  893. X    deftab[ndefs].code= code;
  894. X    deftab[ndefs].name= name;
  895. X    deftab[ndefs].def= (string) savestr(def);
  896. X    deftab[ndefs].rep= (string) savestr(rep);
  897. X    ndefs++;
  898. X}
  899. X
  900. XHidden Procedure store(code, name, def, rep) int code; string name, def, rep; {
  901. X    tabent *d;
  902. X
  903. X    if (code > 0) {
  904. X        keep(code, name, def, rep);
  905. X    }
  906. X    else {    /* code < 0; string-valued entry */
  907. X        /* find the place matching name to replace definition */
  908. X            for (d= deftab; d < deftab+ndefs; ++d) {
  909. X            if (code == d->code) {
  910. X                               d->def= (string) savestr(def);
  911. X                               d->rep= (string) savestr(rep);
  912. X                               break;
  913. X            }
  914. X        }
  915. X    }
  916. X    bind_changed(code);
  917. X}
  918. X
  919. X/****************************************************************************/
  920. X
  921. X#define I_OP_PROMPT "Enter operation [? for help]: "
  922. X#define OP_PROMPT   "Enter operation: "
  923. X
  924. XHidden string ask_name(prompt) string prompt; {
  925. X    putdata(prompt, 0);
  926. X    return getinput(&definpbuf);
  927. X}
  928. X
  929. XHidden Procedure print_heading() {
  930. X    sprintf(fmtbuf, ABC_RELEASE, RELEASE);
  931. X    putdata(fmtbuf, 0);
  932. X    nextline();
  933. X    putdata(COPYRIGHT, 0);
  934. X    nextline();
  935. X    putdata(HEADING, 0);
  936. X    nextline();
  937. X    nextline();
  938. X}
  939. X
  940. XHidden Procedure process() {
  941. X    operation *op;
  942. X    string name;
  943. X    bool show;
  944. X    bool del;
  945. X    bool first= Yes;
  946. X    int ysave;
  947. X
  948. X    print_heading();
  949. X
  950. X    ysave= win.y;
  951. X
  952. X    set_windows(win.y);
  953. X    Upd_bindings();
  954. X
  955. X    for (;;) {
  956. X        if (first) {
  957. X            name= ask_name(I_OP_PROMPT);
  958. X            scrolloff_heading(ysave);
  959. X            first= No;
  960. X        }
  961. X        else {
  962. X            setpromptline();
  963. X            name= ask_name(OP_PROMPT);
  964. X        }
  965. X        if (Empty(name))
  966. X            continue;
  967. X        if (Equal(name, "?")) {
  968. X            help();
  969. X            continue;
  970. X        }
  971. X        show= *name == '=';
  972. X        del= *name == '-';
  973. X        if (show || del) name++;
  974. X
  975. X        if (is_quit(name)) {
  976. X            if (!del)
  977. X                putkeydefs();
  978. X            break;
  979. X        }
  980. X        else if (is_init(name)) {
  981. X            nextline();
  982. X            sendinistring();
  983. X            continue;
  984. X        }
  985. X
  986. X        sprintf(fmtbuf, "[%s]", name);
  987. X        op= findoperation(fmtbuf);
  988. X
  989. X        if (op == ONULL || !op->allowed) {
  990. X            putdata(E_UNKNOWN, 0);
  991. X            continue;
  992. X        }
  993. X        if (!show && spec_operation(op)) {
  994. X            sprintf(fmtbuf, E_NOTALLOWED, name);
  995. X            putdata(fmtbuf, 0);
  996. X            continue;
  997. X        }
  998. X
  999. X        if (show)
  1000. X            showbindings(op);
  1001. X        else if (del)
  1002. X            delbindings(op);
  1003. X        else
  1004. X            definebinding(op);
  1005. X    }
  1006. X}
  1007. X
  1008. XHidden bool is_quit(name) string name; {
  1009. X    if (Equal(name, "q") || Equal(name, "quit"))
  1010. X        return Yes;
  1011. X    return No;
  1012. X}
  1013. X
  1014. XHidden bool is_init(name) string name; {
  1015. X    if (Equal(name, "init"))
  1016. X        return Yes;
  1017. X    return No;
  1018. X}
  1019. X
  1020. XHidden bool spec_operation(op) operation *op; {
  1021. X    if (op->code == CANCEL || op->code == SUSPEND)
  1022. X        return Yes;
  1023. X    return No;
  1024. X}
  1025. X
  1026. XHidden Procedure scrolloff_heading(n) int n; {
  1027. X    int y= win.y, x= win.x;        /* save old values */
  1028. X
  1029. X    trmscrollup(0, win.ylast, n);
  1030. X    set_windows(0);
  1031. X    win.y= y - n;
  1032. X    win.x= x;
  1033. X}
  1034. X
  1035. XHidden Procedure setpromptline() {
  1036. X    if (win.y != win.yfirst || win.x > 0) {
  1037. X        if (win.x > 0)
  1038. X            nextline();
  1039. X        if (!CONTINUE_GIVEN)
  1040. X            nextline();
  1041. X        if (CONTINUE_GIVEN)
  1042. X            clearwindow();
  1043. X    }
  1044. X}
  1045. X
  1046. X/****************************************************************************/
  1047. X
  1048. XHidden Procedure definebinding(op) operation *op; {
  1049. X    string def, rep;
  1050. X
  1051. X    clearwindow();
  1052. X    def= new_definition(op, &rep);
  1053. X    if (!Val(def))
  1054. X        return;
  1055. X
  1056. X#ifndef KNOWN_KEYBOARD
  1057. X    rep= new_representation(rep, def);
  1058. X#else
  1059. X    if (op->code == TERMINIT || op->code == TERMDONE)
  1060. X        rep= new_representation(rep, def);
  1061. X#endif
  1062. X
  1063. X    store(op->code, op->name, def, rep);
  1064. X    Upd_bindings();
  1065. X}
  1066. X
  1067. X#define SHOW_PROMPT "Showing the bindings for %s (%s):"
  1068. X
  1069. XHidden Procedure showbindings(op) operation *op; {
  1070. X    tabent *d;
  1071. X
  1072. X    clearwindow();
  1073. X    sprintf(fmtbuf, SHOW_PROMPT, op->name, op->descr);
  1074. X    putdata(fmtbuf, 0);
  1075. X
  1076. X    for (d= deftab+ndefs-1; d >= deftab; d--) {
  1077. X        if (d->code != op->code || !Val(d->def) || !Val(d->rep))
  1078. X            continue;
  1079. X        putdata(d->rep, 0);
  1080. X    }
  1081. X}
  1082. X
  1083. XHidden Procedure delbindings(op) operation *op; {
  1084. X    tabent *d;
  1085. X
  1086. X    for (d= deftab; d < deftab+ndefs; d++) {
  1087. X        if (d->code == op->code && Val(d->def)) {
  1088. X            store(DELBIND, S_IGNORE, d->def, d->rep);
  1089. X            d->def= d->rep= SNULL;
  1090. X            bind_changed(d->code);
  1091. X        }
  1092. X    }
  1093. X    Upd_bindings();
  1094. X    clearwindow();
  1095. X}
  1096. X
  1097. X/****************************************************************************/
  1098. X
  1099. XHidden tabent savedeftab[MAXDEFS];
  1100. XHidden int nsaveharddefs= 0;
  1101. XHidden int nsavefiledefs= 0;
  1102. X
  1103. X
  1104. XVisible Procedure saveharddefs() {
  1105. X    tabent *d, *h;
  1106. X    
  1107. X    for (d= deftab, h= savedeftab; d < deftab+nharddefs; d++) {
  1108. X        if (Val(d->name) && Val(d->def)) {
  1109. X            h->code= d->code;
  1110. X            h->name= d->name;
  1111. X            h->def= d->def;
  1112. X            h->rep= d->rep;
  1113. X            h++;
  1114. X        }
  1115. X    }
  1116. X    nsaveharddefs= h-savedeftab;
  1117. X}
  1118. X
  1119. XVisible Procedure savefiledefs() {
  1120. X    tabent *d, *h;
  1121. X    
  1122. X    d= deftab + nharddefs;
  1123. X    h= savedeftab + nsaveharddefs;
  1124. X    for (; d < deftab + ndefs; d++) {
  1125. X        if (Val(d->name) && Val(d->def)) {
  1126. X            h->code= d->code;
  1127. X            h->name= d->name;
  1128. X            h->def= d->def;
  1129. X            h->rep= d->rep;
  1130. X            h++;
  1131. X        }
  1132. X    }
  1133. X    nsavefiledefs= h-savedeftab;
  1134. X}
  1135. X
  1136. XHidden bool a_harddef(d) tabent *d; {
  1137. X    tabent *h;
  1138. X
  1139. X    if (!Val(d->def))
  1140. X        return No;
  1141. X    for (h= savedeftab; h < savedeftab+nsaveharddefs; h++) {
  1142. X        if (Equal(d->def, h->def) && 
  1143. X            Equal(d->rep, h->rep) &&    /* TODO: needed ? */
  1144. X            (d->code == h->code ||
  1145. X             d->code == IGNORE ||
  1146. X             d->code == DELBIND
  1147. X            )
  1148. X           )
  1149. X            return Yes;
  1150. X    }
  1151. X    return No;
  1152. X}
  1153. X
  1154. XHidden Procedure init_ignore() {
  1155. X    tabent *d;
  1156. X    
  1157. X    for (d= deftab+nharddefs; d < deftab+ndefs; d++) {
  1158. X        if (d->code == IGNORE && a_harddef(d))
  1159. X            /* don't show it in the bindings window */
  1160. X            d->code= DELBIND;
  1161. X    }
  1162. X}
  1163. X
  1164. X#ifndef NULL_EXTENDED
  1165. X
  1166. XHidden string findoldrepr(def) string def; {
  1167. X    tabent *h;
  1168. X
  1169. X    h= savedeftab + nsavefiledefs - 1;
  1170. X    for (; h >= savedeftab; h--) {
  1171. X        if (Val(h->def) && Equal(h->def, def) && Val(h->rep))
  1172. X            return h->rep;
  1173. X    }
  1174. X    return SNULL;
  1175. X}
  1176. X
  1177. X#endif /* ! NULL_EXTENDED */
  1178. X
  1179. X/****************************************************************************/
  1180. X
  1181. XFILE *keyfp;            /* fileptr for key definitions file */
  1182. X
  1183. XHidden Procedure putkeydefs() {
  1184. X    openkeyfile();
  1185. X    put_table();
  1186. X    put_strings();
  1187. X    closekeyfile();
  1188. X}
  1189. X
  1190. XHidden Procedure init_newfile() {
  1191. X    char *termname;
  1192. X    string termfile;
  1193. X    
  1194. X#ifdef KEYSPREFIX
  1195. X    if ((termname= getenv("TERM")) != NULL) {
  1196. X        termfile= (string) getmem((unsigned) strlen(KEYSPREFIX)+strlen(termname));
  1197. X        strcpy(termfile, KEYSPREFIX);
  1198. X        strcat(termfile, termname);
  1199. X    }
  1200. X    else
  1201. X#endif /*KEYSPREFIX*/
  1202. X        termfile= savestr(NEWFILE);
  1203. X    
  1204. X    if (bwsdefault
  1205. X        && (D_exists(bwsdefault) || Mkdir(bwsdefault) == 0)
  1206. X        && F_writable(bwsdefault))
  1207. X    {
  1208. X        newfile= makepath(bwsdefault, termfile);
  1209. X    }
  1210. X    else {
  1211. X        putSstr(errfile,
  1212. X        "Cannot use directory \"%s\" for private keydefinitions file\n",
  1213. X            bwsdefault);
  1214. X        putSstr(errfile,
  1215. X        "Cannot use directory \"%s\" for private keydefinitions file",
  1216. X            bwsdefault);
  1217. X        
  1218. X        newfile= termfile;
  1219. X    }
  1220. X}
  1221. X
  1222. X#define MAKE_KEYFILE "Producing key definitions file %s."
  1223. X
  1224. XHidden Procedure openkeyfile() {
  1225. X    keyfp= fopen(newfile, "w");
  1226. X    nextline();
  1227. X    if (keyfp == NULL) {
  1228. X        sprintf(fmtbuf, E_KEYFILE, newfile);
  1229. X        putdata(fmtbuf, 0);
  1230. X        keyfp= stdout;
  1231. X    }
  1232. X    else {
  1233. X        sprintf(fmtbuf, MAKE_KEYFILE, newfile);
  1234. X        putdata(fmtbuf, 0);
  1235. X    }
  1236. X    freemem(newfile);
  1237. X}
  1238. X
  1239. XHidden Procedure closekeyfile() {
  1240. X    fclose(keyfp);
  1241. X}
  1242. X
  1243. XHidden Procedure put_table() {
  1244. X    tabent *d;
  1245. X    
  1246. X    for (d= deftab+nharddefs; d < deftab+ndefs; d++) {
  1247. X        if (Val(d->def)) {
  1248. X            if (d->code != IGNORE) {
  1249. X                if (d->code == DELBIND) {
  1250. X                    if (!a_harddef(d))
  1251. X                        continue;
  1252. X                }
  1253. X                else if (a_harddef(d))
  1254. X                    continue;
  1255. X            }
  1256. X            put_def(d->name, d->def, d->rep);
  1257. X        }
  1258. X    }
  1259. X}
  1260. X
  1261. XHidden Procedure put_strings() {
  1262. X    if (terminit != DNULL && Val(terminit->def)) {
  1263. X        string rep= terminit->rep;
  1264. X        put_def(S_TERMINIT, terminit->def, Val(rep) ? rep : "");
  1265. X    }
  1266. X    else put_def(S_TERMINIT, "", "");
  1267. X
  1268. X    if (termdone != DNULL && Val(termdone->def)) {
  1269. X        string rep= termdone->rep;
  1270. X        put_def(S_TERMDONE, termdone->def, Val(rep) ? rep : "");
  1271. X    }
  1272. X    else put_def(S_TERMDONE, "", "");
  1273. X}
  1274. X
  1275. X#define NAMESPACE 15 /* TODO: e1getc.c accepts until 20 */
  1276. X
  1277. XHidden Procedure put_def(name, def, rep) string name, def, rep; {
  1278. X    int i;
  1279. X    string s;
  1280. X
  1281. X    i= 0;
  1282. X    for (s= name; *s; s++) {
  1283. X        putchr(keyfp, *s);
  1284. X        i++;
  1285. X    }
  1286. X    while (i < NAMESPACE) {
  1287. X        putchr(keyfp, ' ');
  1288. X        i++;
  1289. X    }
  1290. X    putstr(keyfp, " = ");
  1291. X    putchr(keyfp, '"');
  1292. X    for (s= def; *s != '\0'; ++s) {
  1293. X        if (*s == '"')
  1294. X            putchr(keyfp, '\\');
  1295. X        if (Printable(*s))
  1296. X            putchr(keyfp, *s);
  1297. X        else
  1298. X            putDstr(keyfp, "\\%03o", (int) (*s&0377));
  1299. X    }
  1300. X    putchr(keyfp, '"');
  1301. X    putSstr(keyfp, " = \"%s\"\n", rep);
  1302. X}
  1303. X
  1304. X/****************************************************************************/
  1305. X
  1306. X#define HELP_PROMPT    "Press [SPACE] to continue, [RETURN] to exit help" 
  1307. X
  1308. XHidden Procedure help() {
  1309. X    clearwindow();
  1310. X    shorthelp();
  1311. X    if (morehelp()) {
  1312. X        clearwindow();
  1313. X        longhelp();
  1314. X    }
  1315. X    else
  1316. X        clearwindow();
  1317. X}
  1318. X
  1319. XHidden Procedure shorthelp() {
  1320. X    putdata(" name: (re)define binding for \"name\",", 0);
  1321. X    putdata("-name: remove all the bindings for \"name\"", 0);
  1322. X    putdata("=name: show all the bindings for \"name\"", 0);
  1323. X    putdata(" quit: exit this program, saving the changes", 0);
  1324. X    putdata("-quit: exit this program", 0);
  1325. X    putdata(" init: send term-init string to screen", 0);
  1326. X}
  1327. X
  1328. XHidden bool morehelp() {
  1329. X    int c;
  1330. X    int y= win.y+1;
  1331. X    string prompt= mkstandout(HELP_PROMPT);
  1332. X    bool ans;
  1333. X
  1334. X    if (y < win.ylast)
  1335. X        y++;
  1336. X    trmputdata(y, y, 0, prompt);
  1337. X    trmsync(y, strlen(prompt));
  1338. X
  1339. X    for (;;) {
  1340. X        c= Inchar();
  1341. X        if (c == EOF || CRLF(c))
  1342. X            { ans= No; break; }
  1343. X        else if (Cspace(c))
  1344. X            { ans= Yes; break; }
  1345. X        else
  1346. X            trmbell();
  1347. X    }
  1348. X    trmputdata(y, y, 0, "");
  1349. X    return ans;
  1350. X}
  1351. X
  1352. XHidden Procedure longhelp() {
  1353. X
  1354. Xputdata("    While (re)defining a binding, the program will ask you to enter \
  1355. Xa key sequence; end it with [RETURN].", 0);
  1356. X
  1357. Xputdata("If you want [RETURN] in your binding, enclose the whole binding \
  1358. Xwith single or double quotes.", 0);
  1359. X
  1360. X#ifndef KNOWN_KEYBOARD
  1361. X
  1362. Xputdata("It will then ask you how to represent this key in the bindings \
  1363. Xwindow; the default can be accepted with [RETURN].", 0);
  1364. X
  1365. X#endif /* KNOWN_KEYBOARD */
  1366. X
  1367. Xputdata("    [term-init] and [term-done] are the names for the strings that \
  1368. Xshould be sent to the screen upon startup and exit, respectively (for \
  1369. Xprogramming function keys or setting background colours etc).", 0);
  1370. X
  1371. Xsprintf(fmtbuf,
  1372. X"    This program will not allow you to use your interrupt character (%s) in \
  1373. Xany keybinding, since the ABC system always binds this to %s.",
  1374. X    representation(intr_char), S_INTERRUPT);
  1375. Xputdata(fmtbuf, 0);
  1376. X
  1377. X#ifdef CANSUSPEND
  1378. X
  1379. Xif (susp_char != SNULL) {
  1380. Xsprintf(fmtbuf, "The same holds for your suspend character (%s), bound to %s.",
  1381. X    representation(susp_char), S_SUSPEND);
  1382. Xputdata(fmtbuf, 0);
  1383. X            }
  1384. X#endif /* CANSUSPEND */
  1385. X
  1386. Xputdata("You can use this idiosyncrasy to cancel a binding while typing \
  1387. Xby including your interrupt character.", 0);
  1388. X
  1389. Xputdata("   The space in the window above sometimes isn't sufficient to \
  1390. Xshow all the bindings. You will recognize this situation by a marker \
  1391. X('*') after the name. Hence the option '=name'.", 0);
  1392. X
  1393. X}
  1394. END_OF_FILE
  1395.   if test 29155 -ne `wc -c <'abc/keys/keydef.c'`; then
  1396.     echo shar: \"'abc/keys/keydef.c'\" unpacked with wrong size!
  1397.   fi
  1398.   # end of 'abc/keys/keydef.c'
  1399. fi
  1400. if test -f 'abc/stc/i2tca.c' -a "${1}" != "-c" ; then 
  1401.   echo shar: Will not clobber existing file \"'abc/stc/i2tca.c'\"
  1402. else
  1403.   echo shar: Extracting \"'abc/stc/i2tca.c'\" \(21735 characters\)
  1404.   sed "s/^X//" >'abc/stc/i2tca.c' <<'END_OF_FILE'
  1405. X/* Copyright (c) Stichting Mathematisch Centrum, amsterdam, 1988. */
  1406. X
  1407. X/* ABC type check */
  1408. X
  1409. X#include "b.h"
  1410. X#include "bmem.h"
  1411. X#include "bfil.h"
  1412. X#include "bint.h"
  1413. X#include "bobj.h"
  1414. X#include "b0lan.h"
  1415. X#include "i2nod.h"
  1416. X#include "i2par.h"
  1417. X#include "i2stc.h"
  1418. X#include "i3env.h"    /* for curline and curlino */
  1419. X#include "i3sou.h"    /* for is_udfpr and args */
  1420. X
  1421. X#define WRONG_ARGUMENT    MESS(2300, "wrong argument of type_check()")
  1422. X#define WARNING_DUMMY    MESS(2301, "next line must be impossible as a refinement name, e.g. with a space:")
  1423. X#define RETURNED_VALUE    GMESS(2302, "returned value")
  1424. X#define WRONG_RETURN    MESS(2303, "RETURN not in function or expression refinement")
  1425. X#define EMPTY_STACK    MESS(2304, "Empty polytype stack")
  1426. X
  1427. X/* ******************************************************************** */
  1428. X
  1429. Xchar *tc_code[NTYPES] = {    /* Type checker table; */
  1430. X                /* see comment below for meaning of codes */
  1431. X/* How-to's */
  1432. X
  1433. X    /* HOW_TO */ "-s-csH",
  1434. X    /* YIELD */ "--p-YcysF",
  1435. X    /* TEST */ "--p-csP",
  1436. X    /* REFINEMENT */ "--Rcys",
  1437. X
  1438. X/* Commands */
  1439. X
  1440. X    /* SUITE */ "Lc-c",
  1441. X    /* PUT */ "eeU",
  1442. X    /* INSERT */ "e}eU",
  1443. X    /* REMOVE */ "e}eU",
  1444. X    /* SET_RANDOM */ "e*",
  1445. X    /* DELETE */ "e*",
  1446. X    /* CHECK */ "t*",
  1447. X    /* SHARE */ "",
  1448. X    /* PASS */ "",
  1449. X
  1450. X    /* WRITE */ "-?e*",
  1451. X    /* WRITE1 */ "-?e*",
  1452. X    /* READ */ "eeU",
  1453. X    /* READ_RAW */ "e'U",
  1454. X
  1455. X    /* IF */ "t*-c",
  1456. X    /* WHILE */ "Lt*-c",
  1457. X    /* FOR */ "e#eU-c",
  1458. X
  1459. X    /* SELECT */ "-c",
  1460. X    /* TEST_SUITE */ "L?t*-cc",
  1461. X    /* ELSE */ "L-c",
  1462. X
  1463. X    /* QUIT */ "",
  1464. X    /* RETURN */ "erU",
  1465. X    /* REPORT */ "t*",
  1466. X    /* SUCCEED */ "",
  1467. X    /* FAIL */ "",
  1468. X
  1469. X    /* USER_COMMAND */ "A-sC",
  1470. X    /* EXTENDED_COMMAND */ "",
  1471. X
  1472. X/* Expressions, targets, tests */
  1473. X
  1474. X    /* TAG */ "T",
  1475. X    /* COMPOUND */ "e",
  1476. X
  1477. X/* Expressions, targets */
  1478. X
  1479. X    /* COLLATERAL */ ":(<e,>)",
  1480. X    /* SELECTION */ "we~e~]U",
  1481. X    /* BEHEAD */ "e'UenU'",
  1482. X    /* CURTAIL */ "e'UenU'",
  1483. X
  1484. X/* Expressions, tests */
  1485. X
  1486. X    /* UNPARSED */ "v",
  1487. X
  1488. X/* Expressions */
  1489. X
  1490. X    /* MONF */ "-eM",
  1491. X    /* DYAF */ "e-eD",
  1492. X    /* NUMBER */ "n",
  1493. X    /* TEXT_DIS */ "-s'",
  1494. X    /* TEXT_LIT */ "-s",
  1495. X    /* TEXT_CONV */ "e*s",
  1496. X    /* ELT_DIS */ "v{",
  1497. X    /* LIST_DIS */ ":e<eu>}",
  1498. X    /* RANGE_BNDS */ "e.ueu",
  1499. X    /* TAB_DIS */ ":ee<~eu~eu>]",
  1500. X
  1501. X/* Tests */
  1502. X
  1503. X    /* AND */ "t*t",
  1504. X    /* OR */ "t*t",
  1505. X    /* NOT */ "t",
  1506. X    /* SOME_IN */ "e#eUt",
  1507. X    /* EACH_IN */ "e#eUt",
  1508. X    /* NO_IN */ "e#eUt",
  1509. X    /* MONPRD */ "-em",
  1510. X    /* DYAPRD */ "e-ed",
  1511. X    /* LESS_THAN */ "eeu",
  1512. X    /* AT_MOST */ "eeu",
  1513. X    /* GREATER_THAN */ "eeu",
  1514. X    /* AT_LEAST */ "eeu",
  1515. X    /* EQUAL */ "eeu",
  1516. X    /* UNEQUAL */ "eeu",
  1517. X    /* Nonode */ "",
  1518. X
  1519. X    /* TAGformal */ "T",
  1520. X    /* TAGlocal */ "T",
  1521. X    /* TAGglobal */ "T",
  1522. X    /* TAGrefinement */ "T",
  1523. X    /* TAGzerfun */ "Z",
  1524. X    /* TAGzerprd */ "z",
  1525. X
  1526. X    /* ACTUAL */ "-?aes",
  1527. X    /* FORMAL */ "-?fes",
  1528. X
  1529. X#ifdef GFX
  1530. X    /* SPACE */ "eeU",
  1531. X    /* LINE */ "eeU",
  1532. X    /* CLEAR */ "",
  1533. X#endif
  1534. X
  1535. X    /* COLON_NODE */ "c"
  1536. X
  1537. X};
  1538. X
  1539. X/************************************************************************/
  1540. X
  1541. XHidden char *zerf[]= {
  1542. X    F_pi, "n",
  1543. X    F_e, "n",
  1544. X    F_random, "n",
  1545. X    F_now, "(6n,0n,1n,2n,3n,4n,5)",
  1546. X    NULL
  1547. X};
  1548. X
  1549. XHidden char *monf[]= {
  1550. X    S_ABOUT, "nUn",
  1551. X    S_PLUS, "nUn",
  1552. X    S_MINUS, "nUn",
  1553. X    S_NUMERATOR, "nUn",
  1554. X    S_DENOMINATOR, "nUn",
  1555. X    F_root, "nUn",
  1556. X    F_abs, "nUn",
  1557. X    F_sign, "nUn",
  1558. X    F_floor, "nUn",
  1559. X    F_ceiling, "nUn",
  1560. X    F_round, "nUn",
  1561. X    F_exactly, "nUn",
  1562. X    F_sin, "nUn",
  1563. X    F_cos, "nUn",
  1564. X    F_tan, "nUn",
  1565. X    F_arctan, "nUn",
  1566. X    F_exp, "nUn",
  1567. X    F_log, "nUn", 
  1568. X    F_lower, "'U'",
  1569. X    F_upper, "'U'",
  1570. X    F_stripped, "'U'",
  1571. X    F_split, "'Un']",
  1572. X    F_keys, "wv]%U}",
  1573. X    S_NUMBER, "v#Un",
  1574. X    F_min, "w#%U",
  1575. X    F_max, "w#%U",
  1576. X    F_choice, "w#%U",
  1577. X    F_radius, "(2n,0n,1)Un",
  1578. X    F_angle, "(2n,0n,1)Un",
  1579. X    NULL
  1580. X};
  1581. X
  1582. XHidden char *dyaf[]= {
  1583. X    S_PLUS, "nUnUn",
  1584. X    S_MINUS, "nUnUn",
  1585. X    S_TIMES, "nUnUn",
  1586. X    S_OVER, "nUnUn",
  1587. X    S_POWER, "nUnUn", 
  1588. X    F_root, "nUnUn", 
  1589. X    F_round, "nUnUn",
  1590. X    F_mod, "nUnUn",
  1591. X    F_sin, "nUnUn",
  1592. X    F_cos, "nUnUn",
  1593. X    F_tan, "nUnUn",
  1594. X    F_arctan, "nUnUn",
  1595. X    F_log, "nUnUn",
  1596. X    S_JOIN, "'U'U'",
  1597. X    S_BEHEAD, "nU'U'",
  1598. X    S_CURTAIL, "nU'U'",
  1599. X    S_REPEAT, "nU'U'",
  1600. X    S_LEFT_ADJUST, "nU*'",
  1601. X    S_CENTER, "nU*'",
  1602. X    S_RIGHT_ADJUST, "nU*'",
  1603. X    S_NUMBER, "~#Un",
  1604. X    F_min, "~#ux",
  1605. X    F_max, "~#ux",
  1606. X    F_item, "nUw%#U",
  1607. X    F_angle, "(2n,0n,1)UnUn",
  1608. X#ifdef B_COMPAT
  1609. X    F_thof, "~nUw%#U",
  1610. X#endif
  1611. X    NULL
  1612. X};
  1613. X
  1614. XHidden char *zerp[]= {
  1615. X    NULL
  1616. X};
  1617. X
  1618. XHidden char *monp[]= {
  1619. X    P_exact, "nu",
  1620. X    NULL
  1621. X};
  1622. X
  1623. XHidden char *dyap[]= {
  1624. X    P_in, "~#u",
  1625. X    P_notin, "~#u",
  1626. X    NULL
  1627. X};
  1628. X
  1629. X/*********************************************************************
  1630. X
  1631. XMeaning of codes:
  1632. X
  1633. XH,F,P    calculate and store typecode for
  1634. X    (H)command, F(unction), or P(redicate) definition
  1635. Xf    count a formal parameter for a command definition
  1636. Xp    set number of formal parameters for a function or predicate definition
  1637. X    (also register that a next M,D,m or d concern the parameters
  1638. X     and not a use of the function or predicate
  1639. X     [the parstree's for FPR_FORMALS and e.g. MONF's are identical:-])
  1640. X
  1641. XC    typecheck user defined command, actuals are on the stack
  1642. XA,a    initialize/augment number of actual parameters for a used
  1643. X    user defined command
  1644. Xq,Q    check for one/excessive actual parameter(s)
  1645. X    (these are only used in typecodes for command definitions)
  1646. XZ,M,D,z,m,d
  1647. X    if (this if the FPR_FORMALS subtree 
  1648. X        of a function or predicate definition)
  1649. X    then
  1650. X        interchange formals on the stack for d,D
  1651. X        return
  1652. X    else
  1653. X        replace codestring t by the proper one for this
  1654. X        (user defined or predefined) function or predicate;
  1655. X        (the actual parameters are already on the stack)
  1656. X
  1657. XV[0-9]+    push a new external type, with ident="NN.nn"
  1658. X    where NN is the current ext_level and nn is the value of [0-9]+
  1659. X    (this code only occurs in typecode's of how-to definitions)
  1660. X
  1661. Xc,s,e,t typecheck c(ommand), s(ubnode), e(xpression) or t(est)
  1662. X        in subnode Fld(v, f++)
  1663. X        As side effects, c sets curline for error messages,
  1664. X        and e and t push a polytype on the stack.
  1665. X-       skip subnode f++
  1666. XL       curlino= subnode f++
  1667. X
  1668. Xu       pop(x); pop(y); push(unify(x, y)); p_release(x); p_release(y);
  1669. XU       pop(x); pop(y); p_release(unify(x, y))); p_release(x); p_release(y);
  1670. X
  1671. XY       set returned value name for Yield
  1672. XR       set returned value name for Refinement
  1673. Xy       release returned value name for yield/refinement
  1674. Xr       push(type of returned value);
  1675. X
  1676. X*       pop(x); p_release(x)
  1677. X?       skip code "e*" or "t*" if subnode f is NilTree
  1678. X~       interchange: pop(x); pop(y); push(x); push(y);
  1679. X%    pop(u); interchange like ~; push(u)
  1680. X'       push(mk_text());
  1681. Xn       push(mk_number());
  1682. X.       push(mk_text_or_number());
  1683. X{       push(mk_elt());
  1684. X}       pop(x); push(mk_list(x));
  1685. X#       pop(x); push(mk_tlt(x));
  1686. X]       pop(a); pop(k); push(mk_table(k, a));
  1687. XT       push(tag(subnode f++));
  1688. Xw       x= mk_newvar(); push(x); push(copy(x));
  1689. Xv       push(mk_newvar());
  1690. X
  1691. X
  1692. XSimple loop facility:
  1693. X:       init loop over subnode f; f=FF and nf=Nfields(subnode)
  1694. X<       indicator for start of loop body; if f>=nf goto ">"
  1695. X>       indicator for end of loop body; if f<nf, go back to "<"
  1696. X
  1697. XCoumpound types: (N is a number of digits, with decimal value N)
  1698. X(N      push(mkt_compound(N))
  1699. X,>      pop subtype, pop compound, putsubtype f in compound, push compound
  1700. X,N      pop subtype, pop compound, putsubtype N in compound, push compound
  1701. X)    no action, used for legibility,
  1702. X        e.g. (2(2n,0n,1),1n,2) for compound in compound.
  1703. XCOLLATERALS don't use N, but combine with the loop facility, as indicated.
  1704. X
  1705. X*************************************************************************/
  1706. X
  1707. XHidden value ret_name= Vnil;
  1708. X/*
  1709. X * if in commandsuite of expression- or test-refinement: 
  1710. X *    holds refinement name;
  1711. X * if in commandsuite of yield unit:
  1712. X *     holds ABC-text RETURNED_VALUE 
  1713. X *        (used in error messages, 
  1714. X *         no confusion with refinement names should be possible)
  1715. X * else
  1716. X *    Vnil
  1717. X * Used in tc_node(RETURN expr)
  1718. X */
  1719. X
  1720. X/************************************************************************/
  1721. X
  1722. X/* For the inter-unit typecheck we need codes 
  1723. X * for "externally used variable types".
  1724. X * These codes look like "V1", "V2", etc., for the first, second etc used
  1725. X * external variable type.
  1726. X * When used in user defined commands, functions or precidate calls,
  1727. X * we turn these into types (kind="Variable", id="N.1" or "N.2" etc)
  1728. X * where N stands for the number of the currently used user defined;
  1729. X * N is augmented for every use of some user defined command, function
  1730. X * or predicate, and is kept in ext_level.
  1731. X */
  1732. XHidden int ext_level= 0;
  1733. X
  1734. X/* nformals counts the number of formal parameters of a how-to.
  1735. X * For functions and predicate definitions it also acts
  1736. X * as a boolean to know when a MONF (etc) is an FPR_FORMAL,
  1737. X * or part of an expression.
  1738. X */
  1739. X#define FPR_PARAMETERS (-1)
  1740. XHidden int nformals= 0;
  1741. XHidden int nactuals= 0;
  1742. X
  1743. X/************************************************************************/
  1744. X
  1745. X/************************************************************************/
  1746. X
  1747. XForward polytype pt_pop();
  1748. XForward polytype external_type();
  1749. X
  1750. XForward string get_code();
  1751. XForward string fpr_code();
  1752. X
  1753. XVisible Procedure type_check(v) parsetree v; {
  1754. X    typenode n;
  1755. X
  1756. X    if (!still_ok || v == NilTree)
  1757. X        return;
  1758. X    n= nodetype(v);
  1759. X    curline= v; curlino= one;
  1760. X    pts_init();
  1761. X    usetypetable(mk_elt());
  1762. X    start_vars();
  1763. X    ret_name= Vnil;
  1764. X    ext_level= 0;
  1765. X    nformals= 0;
  1766. X    if (Unit(n) || Command(n) || Expression(n)) {
  1767. X        tc_node(v);
  1768. X        if (!interrupted && Expression(n))
  1769. X            p_release(pt_pop());
  1770. X    }
  1771. X    else syserr(WRONG_ARGUMENT);
  1772. X    end_vars();
  1773. X    deltypetable();
  1774. X    pts_free();
  1775. X}
  1776. X
  1777. X#define FF First_fieldnr
  1778. X#define Fld(v, f) (*(Branch(v, f)))
  1779. X
  1780. XHidden Procedure tc_node(v) parsetree v; {
  1781. X    string t;
  1782. X    string t_saved= NULL;
  1783. X    int f;
  1784. X    int nf;
  1785. X    int len;    /* length of compound */
  1786. X    polytype x, y, u;
  1787. X    
  1788. X    if (v == NilTree)
  1789. X        return;
  1790. X    
  1791. X    t= tc_code[nodetype(v)];
  1792. X    f= FF;
  1793. X    
  1794. X#ifdef TYPETRACE
  1795. X    t_typecheck((int)nodetype(v), t);
  1796. X#endif
  1797. X    
  1798. X    while (*t) {
  1799. X    
  1800. X    switch (*t) {
  1801. X    
  1802. X    case 'p':    /* formal parameter(s) of func or pred */
  1803. X        switch (nodetype(Fld(v, f))) {
  1804. X        case TAG:
  1805. X            nformals= 0;
  1806. X            break;
  1807. X        case MONF: case MONPRD:
  1808. X            nformals= FPR_PARAMETERS;
  1809. X            tc_node(Fld(v, f));
  1810. X            nformals= 1;
  1811. X            break;
  1812. X        case DYAF: case DYAPRD:
  1813. X            nformals= FPR_PARAMETERS;
  1814. X            tc_node(Fld(v, f));
  1815. X            nformals= 2;
  1816. X            break;
  1817. X        }
  1818. X        f++;
  1819. X        break;
  1820. X    case 'f':    /* formal parameter of command definition */
  1821. X        nformals++;
  1822. X        break;
  1823. X    case 'H':
  1824. X    case 'F':
  1825. X    case 'P':
  1826. X        put_code(v, *t);
  1827. X        break;
  1828. X    
  1829. X    case 'A':
  1830. X        nactuals= 0;
  1831. X        break;
  1832. X    case 'a':
  1833. X        nactuals++;
  1834. X        break;
  1835. X    case 'C':
  1836. X        /* user defined Command, actuals are on the stack */
  1837. X        ext_level++;
  1838. X        t= get_code(Fld(v, UNIT_NAME), Cmd);
  1839. X        if (t != NULL)
  1840. X            t_saved= t;
  1841. X        else
  1842. X            t= "Q";
  1843. X        continue;    /* skips t++ */
  1844. X    case 'q':
  1845. X        if (nactuals <= 0)
  1846. X            return;    /* breaks loop over formals in excess */
  1847. X        /* else: */
  1848. X        nactuals--;
  1849. X        break;
  1850. X    case 'Q':
  1851. X        while (nactuals > 0) {
  1852. X            p_release(pt_pop());
  1853. X            nactuals--;
  1854. X        }
  1855. X        break;
  1856. X    
  1857. X    case 'Z':
  1858. X        ext_level++;
  1859. X        t_saved= t= fpr_code(Fld(v, TAG_NAME), Zfd, zerf, "T");
  1860. X        continue;    /* skips t++ */
  1861. X    case 'M':
  1862. X        if (nformals == FPR_PARAMETERS)
  1863. X            return;
  1864. X        ext_level++;
  1865. X        t_saved= t= fpr_code(Fld(v, MON_NAME), Mfd, monf, "*v");
  1866. X        continue;    /* skips t++ */
  1867. X    case 'D':
  1868. X        if (nformals == FPR_PARAMETERS) {
  1869. X            return;
  1870. X        }
  1871. X        ext_level++;
  1872. X        t_saved= t= fpr_code(Fld(v, DYA_NAME), Dfd, dyaf, "**v");
  1873. X        continue;    /* skips t++ */
  1874. X    case 'z':
  1875. X        ext_level++;
  1876. X        t_saved= t= fpr_code(Fld(v, TAG_NAME), Zpd, zerp, "T");
  1877. X        continue;    /* skips t++ */
  1878. X    case 'm':
  1879. X        if (nformals == FPR_PARAMETERS)
  1880. X            return;
  1881. X        ext_level++;
  1882. X        t_saved= t= fpr_code(Fld(v, MON_NAME), Mpd, monp, "");
  1883. X        continue;    /* skips t++ */
  1884. X    case 'd':
  1885. X        if (nformals == FPR_PARAMETERS) {
  1886. X            return;
  1887. X        }
  1888. X        ext_level++;
  1889. X        t_saved= t= fpr_code(Fld(v, DYA_NAME), Dpd, dyap, "*");
  1890. X        continue;    /* skips t++ */
  1891. X    
  1892. X    case 'V':
  1893. X        x= external_type(&t);
  1894. X        pt_push(x);
  1895. X        continue;    /* skipping t++ ! */
  1896. X    
  1897. X    case 'c':
  1898. X        curline= Fld(v, f);
  1899. X        end_vars();
  1900. X        start_vars();
  1901. X        /* FALLTHROUGH */
  1902. X    case 's': /* just subnode, without curline setting */
  1903. X    case 'e': /* 'e' and 't' leave polytype on stack */
  1904. X    case 't':
  1905. X        tc_node(Fld(v, f));
  1906. X        f++;
  1907. X        break;
  1908. X    case '-':
  1909. X        f++;
  1910. X        break;
  1911. X    case 'Y':
  1912. X        ret_name= mk_text(RETURNED_VALUE);
  1913. X        break;
  1914. X    case 'y':
  1915. X        if (ret_name != Vnil)
  1916. X            release(ret_name);
  1917. X        ret_name= Vnil;
  1918. X        break;
  1919. X    case 'R':
  1920. X        set_ret_name((value) Fld(v, REF_NAME));
  1921. X        break;
  1922. X    case 'r':
  1923. X        if (ret_name != Vnil) {
  1924. X            pt_push(mkt_var(copy(ret_name)));
  1925. X        }
  1926. X        else {
  1927. X            interr(WRONG_RETURN);
  1928. X            /* skip final U in tc_code for RETURN: */
  1929. X            p_release(pt_pop());
  1930. X            return;
  1931. X        }
  1932. X        break;
  1933. X    case 'L':
  1934. X        curlino= Fld(v, f);
  1935. X        f++;
  1936. X        break;
  1937. X    case '?':
  1938. X        if (Fld(v, f) == NilTree) {
  1939. X            /* skip tc_code "t*" or "e*" */
  1940. X            t+=2;
  1941. X            f++;
  1942. X            /* to prevent p_release(not pushed e or t) */
  1943. X        }
  1944. X        break;
  1945. X    case 'U':
  1946. X    case 'u':
  1947. X        y= pt_pop();
  1948. X        x= pt_pop();
  1949. X        unify(x, y, &u);
  1950. X        p_release(x);
  1951. X        p_release(y);
  1952. X        if (*t == 'U')
  1953. X            p_release(u);
  1954. X        else
  1955. X            pt_push(u);
  1956. X        break;
  1957. X    case '*':
  1958. X        p_release(pt_pop());
  1959. X        break;
  1960. X    case '\'':
  1961. X        pt_push(mkt_text());
  1962. X        break;
  1963. X    case 'n':
  1964. X        pt_push(mkt_number());
  1965. X        break;
  1966. X    case '.':
  1967. X        pt_push(mkt_tn());
  1968. X        break;
  1969. X    case '{':
  1970. X        pt_push(mkt_lt(pt_pop()));
  1971. X        break;
  1972. X    case '}':
  1973. X        pt_push(mkt_list(pt_pop()));
  1974. X        break;
  1975. X    case '#':
  1976. X        pt_push(mkt_tlt(pt_pop()));
  1977. X        break;
  1978. X    case ']':
  1979. X        y= pt_pop();
  1980. X        x= pt_pop();
  1981. X        pt_push(mkt_table(x, y));
  1982. X        break;
  1983. X    case 'x':
  1984. X        x= pt_pop();
  1985. X        if (t_is_error(kind(x)))
  1986. X            pt_push(mkt_error());
  1987. X        else
  1988. X            pt_push(p_copy(asctype(bottomtype(x))));
  1989. X        p_release(x);
  1990. X        break;
  1991. X    case 'v':
  1992. X        pt_push(mkt_newvar());
  1993. X        break;
  1994. X    case 'w':
  1995. X        x= mkt_newvar();
  1996. X        pt_push(x);
  1997. X        pt_push(p_copy(x));
  1998. X        break;
  1999. X    case '~':
  2000. X        x= pt_pop();
  2001. X        y= pt_pop();
  2002. X        pt_push(x);
  2003. X        pt_push(y);
  2004. X        break;
  2005. X    case '%':
  2006. X        u= pt_pop();
  2007. X        x= pt_pop();
  2008. X        y= pt_pop();
  2009. X        pt_push(x);
  2010. X        pt_push(y);
  2011. X        pt_push(u);
  2012. X        break;
  2013. X    case 'T':
  2014. X        x= mkt_var(copy(Fld(v, f)));
  2015. X        add_var(x);
  2016. X        pt_push(x);
  2017. X        /* f++ unnecessary */
  2018. X        break;
  2019. X    case ':':    /* initialize loop over subnode */
  2020. X        /* f == FF */
  2021. X        v= Fld(v, f);
  2022. X        nf= Nfields(v);
  2023. X        break;
  2024. X    case '<':    /* start of loop body (after init part) */
  2025. X        if (f >= nf) /* init part ate the one-and-only subfield */
  2026. X            while (*t != '>') ++t;
  2027. X        break;
  2028. X    case '>':    /* end of loop body */
  2029. X        if (f < nf)
  2030. X            while (*t != '<') --t;
  2031. X        break;
  2032. X    case '(':
  2033. X        ++t;
  2034. X        if (*t == '<') {
  2035. X            /* COLLATERAL above */
  2036. X            len= nf;
  2037. X        }
  2038. X        else {
  2039. X            /* code for compound in fpr_code */
  2040. X            len= 0;
  2041. X            while ('0' <= *t && *t <= '9') {
  2042. X                len= 10*len + *t - '0';
  2043. X                ++t;
  2044. X            }
  2045. X        }
  2046. X        pt_push(mkt_compound(len));
  2047. X        continue;
  2048. X    case ',':
  2049. X        ++t;
  2050. X        if (*t == '>') {
  2051. X            len= f-1;
  2052. X        }
  2053. X        else {
  2054. X            len= 0;
  2055. X            while ('0' <= *t && *t <= '9') {
  2056. X                len= 10*len + *t - '0';
  2057. X                ++t;
  2058. X            }
  2059. X        }
  2060. X        x= pt_pop();
  2061. X        u= pt_pop();
  2062. X        putsubtype(x, u, len);
  2063. X        pt_push(u);
  2064. X        continue;
  2065. X    case ')':
  2066. X        /* just there to end number in compound in compound */
  2067. X        break;
  2068. X
  2069. X    } /* end switch (*t) */
  2070. X    
  2071. X    t++;
  2072. X    
  2073. X    } /* end while (*t) */
  2074. X
  2075. X    if (t_saved != NULL)
  2076. X            freestr(t_saved);
  2077. X}
  2078. X
  2079. X/************************************************************************/
  2080. X
  2081. X/* table mapping pname's to type_code's for how-to definitions */
  2082. X
  2083. XHidden value abctypes= Vnil;
  2084. XHidden bool typeschanges;
  2085. X
  2086. X#define tc_exists(pname, cc)    (in_env(abctypes, pname, cc))
  2087. X#define def_typecode(pname, tc)    (e_replace(tc, &abctypes, pname), \
  2088. X                    typeschanges= Yes)
  2089. X#define del_typecode(pname)    (e_delete(&abctypes, pname), \
  2090. X                    typeschanges= Yes)
  2091. X
  2092. X/* get and put table mapping pname's to typecode's of how-to's
  2093. X * to file when entering or leaving workspace.
  2094. X */
  2095. XVisible Procedure initstc() {
  2096. X    value fn;
  2097. X    
  2098. X    if (Valid(abctypes)) {
  2099. X        release(abctypes);
  2100. X        abctypes= Vnil;
  2101. X    }
  2102. X    if (F_exists(typesfile)) {
  2103. X        fn= mk_text(typesfile);
  2104. X        abctypes= getval(fn, In_prmnv);
  2105. X        if (!still_ok) {
  2106. X            if (Valid(abctypes))
  2107. X                release(abctypes);
  2108. X            abctypes= mk_elt();
  2109. X            still_ok= Yes;
  2110. X        }
  2111. X        release(fn);
  2112. X    }
  2113. X    else abctypes= mk_elt();
  2114. X    typeschanges= No;
  2115. X}
  2116. X
  2117. XVisible Procedure endstc() {
  2118. X    value fn;
  2119. X    int len;
  2120. X    
  2121. X    if (!typeschanges || !Valid(abctypes))
  2122. X        return;
  2123. X    fn= mk_text(typesfile);
  2124. X    /* Remove the file if the permanent environment is empty */
  2125. X    len= length(abctypes);
  2126. X    if (len == 0)
  2127. X        f_delete(fn);
  2128. X    else
  2129. X        putval(fn, abctypes, Yes, In_prmnv);
  2130. X    release(fn);
  2131. X    typeschanges= No;
  2132. X    
  2133. X    if (terminated) return;
  2134. X    release(abctypes); abctypes= Vnil;
  2135. X}
  2136. X
  2137. XVisible Procedure rectypes() {
  2138. X    value fn;
  2139. X    
  2140. X    if (Valid(abctypes))
  2141. X        release(abctypes);
  2142. X    abctypes= mk_elt();
  2143. X    if (F_exists(typesfile)) {
  2144. X        fn= mk_text(typesfile);
  2145. X        f_delete(fn);
  2146. X        release(fn);
  2147. X    }
  2148. X}
  2149. X
  2150. X/************************************************************************/
  2151. X
  2152. XVisible value stc_code(pname) value pname; {
  2153. X    value *tc;
  2154. X    
  2155. X    if (tc_exists(pname, &tc))
  2156. X        return copy(*tc);
  2157. X    /* else: */
  2158. X    return Vnil;
  2159. X}    
  2160. X
  2161. XHidden value old_abctypes;
  2162. XHidden bool old_typeschanges;
  2163. X
  2164. XVisible Procedure del_types() {
  2165. X    old_abctypes= copy(abctypes);
  2166. X    old_typeschanges= typeschanges;
  2167. X    release(abctypes);
  2168. X    abctypes= mk_elt();
  2169. X    typeschanges= Yes;
  2170. X}
  2171. X
  2172. XVisible Procedure adjust_types(no_change) bool no_change; {
  2173. X    if (no_change) {
  2174. X        /* recover old inter-unit typetable */
  2175. X        release(abctypes);
  2176. X        abctypes= old_abctypes;
  2177. X        typeschanges= old_typeschanges;
  2178. X    }
  2179. X    else {
  2180. X        release(old_abctypes);
  2181. X    }
  2182. X}
  2183. X
  2184. X/************************************************************************/
  2185. X
  2186. X/* Calculate code for how-to definition and put into typetable */
  2187. X/* formals are on the stack */
  2188. X
  2189. XForward value type_code();
  2190. X
  2191. XHidden Procedure put_code(v, type) parsetree v; char type; {
  2192. X    value howcode, fmlcode;
  2193. X    value pname, *tc;
  2194. X    polytype x;
  2195. X    int f;
  2196. X    
  2197. X    pname= get_pname(v);
  2198. X    if (tc_exists(pname, &tc))
  2199. X        del_typecode(pname);    
  2200. X        /* do not use old code for possibly edited how-to */
  2201. X    
  2202. X    new_externals();
  2203. X    
  2204. X    howcode= mk_text("");
  2205. X    for (f= nformals; f > 0; f--) {
  2206. X        if (type == 'H') {
  2207. X            howcode= conc(howcode, mk_text("q"));
  2208. X        }
  2209. X        fmlcode= type_code(x=pt_pop()); p_release(x);
  2210. X        howcode= conc(howcode, fmlcode);
  2211. X        howcode= conc(howcode, mk_text("U"));
  2212. X    }
  2213. X    if (type == 'H') {
  2214. X        howcode= conc(howcode, mk_text("Q"));
  2215. X    }
  2216. X    else if (type == 'P')
  2217. X        howcode= conc(howcode, mk_text("v"));
  2218. X    else {
  2219. X        x= mkt_var(mk_text(RETURNED_VALUE));
  2220. X        howcode= conc(howcode, type_code(x));
  2221. X        p_release(x);
  2222. X    }
  2223. X    
  2224. X    def_typecode(pname, howcode);
  2225. X    release(pname); release(howcode);
  2226. X}
  2227. X
  2228. XHidden value type_code(p) polytype p; {
  2229. X    typekind p_kind;
  2230. X    polytype tp;
  2231. X    polytype ext;
  2232. X    value tc;
  2233. X    intlet k, len;
  2234. X    char buf[20];
  2235. X    
  2236. X    p_kind = kind(p);
  2237. X    if (t_is_number(p_kind)) {
  2238. X        return mk_text("n");
  2239. X    }
  2240. X    else if (t_is_text(p_kind)) {
  2241. X        return mk_text("'");
  2242. X    }
  2243. X    else if (t_is_tn(p_kind)) {
  2244. X        return mk_text(".");
  2245. X    }
  2246. X    else if (t_is_compound(p_kind)) {
  2247. X        len= nsubtypes(p);
  2248. X        tc= mk_text("(");
  2249. X        sprintf(buf, "%d", len);
  2250. X        tc= conc(tc, mk_text(buf));
  2251. X        for (k = 0; k < len; k++) {
  2252. X            tc= conc(tc, type_code(subtype(p, k)));
  2253. X            sprintf(buf, ",%d", k);
  2254. X            tc= conc(tc, mk_text(buf));
  2255. X        }
  2256. X        return conc(tc, mk_text(")"));
  2257. X    }
  2258. X    else if (t_is_error(p_kind)) {
  2259. X        return mk_text("v");
  2260. X    }
  2261. X    else if (t_is_table(p_kind)) {
  2262. X        tc = type_code(keytype(p));
  2263. X        tc = conc(tc, type_code(asctype(p)));
  2264. X        return conc(tc, mk_text("]"));
  2265. X    }
  2266. X    else if (t_is_list(p_kind)) {
  2267. X        tc = type_code(asctype(p));
  2268. X        return conc(tc, mk_text("}"));
  2269. X    }
  2270. X    else if (t_is_lt(p_kind)) {
  2271. X        tc = type_code(asctype(p));
  2272. X        return conc(tc, mk_text("{"));
  2273. X    }
  2274. X    else if (t_is_tlt(p_kind)) {
  2275. X        tc = type_code(asctype(p));
  2276. X        return conc(tc, mk_text("#"));
  2277. X    }
  2278. X    else if (t_is_var(p_kind)) {
  2279. X        tp = bottomtype(p);
  2280. X        if (!t_is_var(kind(tp)))
  2281. X            return type_code(tp);
  2282. X        else {
  2283. X            ext= mkt_ext();
  2284. X            repl_type_of(tp, ext);
  2285. X            return type_code(ext);
  2286. X        }
  2287. X    }
  2288. X    else if (t_is_ext(p_kind)) {
  2289. X        return conc(mk_text("V"), convert(ident(p), No, Yes));
  2290. X    }
  2291. X    else {
  2292. X        return mk_text("v"); /* cannot happen */
  2293. X    }
  2294. X    /* NOTREACHED */
  2295. X}
  2296. X
  2297. X/************************************************************************/
  2298. X
  2299. X/* retrieve the codes for user defined commands and for
  2300. X * user defined and predefined functions and predicates
  2301. X * from the respective tables
  2302. X */
  2303. X
  2304. XHidden string get_code(name, type) value name; int type; {
  2305. X    value pname;
  2306. X    value *aa;
  2307. X
  2308. X    pname= permkey(name, type);
  2309. X    if (tc_exists(pname, &aa))
  2310. X        return savestr(strval(*aa));
  2311. X    /* else: */
  2312. X    return NULL;        
  2313. X}
  2314. X
  2315. XHidden string pre_fpr_code(fn, func) value fn; char *func[]; {
  2316. X    int i;
  2317. X    string f= strval(fn);
  2318. X    
  2319. X    for (i= 0;  ; i+=2) {
  2320. X        if (func[i] == NULL)
  2321. X            return NULL;
  2322. X        if (strcmp(f, func[i]) == 0)
  2323. X            return (string) savestr(func[i+1]);
  2324. X    }
  2325. X    /*NOTREACHED*/
  2326. X}
  2327. X
  2328. XHidden string fpr_code(name, type, functab, defcode)
  2329. Xvalue name; literal type; char *functab[]; string defcode;
  2330. X{
  2331. X    string t;
  2332. X    
  2333. X    if (is_udfpr(name, type))
  2334. X        t= get_code(name, type);
  2335. X    else
  2336. X        t= pre_fpr_code(name, functab);
  2337. X    
  2338. X    if (t == NULL)
  2339. X        t= savestr(defcode);
  2340. X    
  2341. X    return t;
  2342. X}
  2343. X
  2344. X/************************************************************************/
  2345. X
  2346. XHidden polytype external_type(pt) string *pt; {
  2347. X    int n;
  2348. X    string t;
  2349. X    polytype x;
  2350. X    char buf[20];
  2351. X    
  2352. X    n= 0;
  2353. X    t= *pt;
  2354. X    for (++t; '0' <= *t && *t <= '9'; t++) {
  2355. X        n= n*10 + *t-'0';
  2356. X    }
  2357. X    sprintf(buf, "%d.%d", ext_level, n);
  2358. X    x= mkt_var(mk_text(buf));
  2359. X    *pt= t;
  2360. X    return x;
  2361. X}
  2362. X
  2363. X/************************************************************************/
  2364. X
  2365. XHidden Procedure set_ret_name(name) value name; {
  2366. X    value n1;
  2367. X    
  2368. X    n1= curtail(name, one);
  2369. X        /* should check for expression refinement */
  2370. X    if (!Cap(charval(n1)))
  2371. X        ret_name= copy(name);
  2372. X    release(n1);
  2373. X}
  2374. X
  2375. X/************************************************************************/
  2376. X
  2377. X/* PolyTypes Stack */
  2378. X
  2379. X#define STACKINCR 100
  2380. X
  2381. XHidden polytype *pts_start;
  2382. XHidden polytype *pts_top;
  2383. XHidden polytype *pts_end;
  2384. X
  2385. XHidden Procedure pts_init() {
  2386. X    pts_start= (polytype *) getmem((unsigned) (STACKINCR * sizeof(polytype)));
  2387. X    pts_top= pts_start;
  2388. X    pts_end= pts_start + STACKINCR;
  2389. X    *(pts_top)= (polytype) Vnil;
  2390. X}
  2391. X
  2392. XHidden Procedure pts_free() {
  2393. X    if (interrupted) {
  2394. X        for (--pts_top; pts_top >= pts_start; --pts_top) {
  2395. X            p_release(*pts_top);
  2396. X        }
  2397. X    }
  2398. X    freemem((ptr) pts_start);
  2399. X}
  2400. X
  2401. XHidden Procedure pts_grow() {
  2402. X    int oldtop= pts_top - pts_start;
  2403. X    int syze= (pts_end - pts_start) + STACKINCR;
  2404. X    
  2405. X    regetmem((ptr *) &(pts_start), (unsigned) (syze * sizeof(polytype)));
  2406. X    pts_top= pts_start + oldtop;
  2407. X    pts_end= pts_start + syze;
  2408. X}
  2409. X
  2410. XHidden Procedure pt_push(pt) polytype pt; {
  2411. X    if (pts_top >= pts_end)
  2412. X        pts_grow();
  2413. X    *pts_top++= pt;
  2414. X}
  2415. X
  2416. XHidden polytype pt_pop() {
  2417. X#ifndef NDEBUG
  2418. X    if (pts_top <= pts_start)
  2419. X        syserr(EMPTY_STACK);
  2420. X#endif
  2421. X    return *--pts_top;
  2422. X}
  2423. END_OF_FILE
  2424.   if test 21735 -ne `wc -c <'abc/stc/i2tca.c'`; then
  2425.     echo shar: \"'abc/stc/i2tca.c'\" unpacked with wrong size!
  2426.   fi
  2427.   # end of 'abc/stc/i2tca.c'
  2428. fi
  2429. echo shar: End of archive 3 \(of 25\).
  2430. cp /dev/null ark3isdone
  2431. MISSING=""
  2432. 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
  2433.     if test ! -f ark${I}isdone ; then
  2434.     MISSING="${MISSING} ${I}"
  2435.     fi
  2436. done
  2437. if test "${MISSING}" = "" ; then
  2438.     echo You have unpacked all 25 archives.
  2439.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2440. else
  2441.     echo You still must unpack the following archives:
  2442.     echo "        " ${MISSING}
  2443. fi
  2444. exit 0 # Just in case...
  2445.