home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso / altsrc / articles / 1000-1999 / 1594 < prev    next >
Internet Message Format  |  1990-12-27  |  54KB

  1. From: mip@IDA.LiU.SE (Mikael Patel)
  2. Newsgroups: alt.sources
  3. Subject: TILE Forth Release 2.0, package 6 of 6
  4. Message-ID: <1963@majestix.ida.liu.se>
  5. Date: 16 Jul 90 18:59:37 GMT
  6.  
  7.  
  8. #! /bin/sh
  9. # This is a shell archive.  Remove anything before this line, then unpack
  10. # it by saving it into a file and typing "sh file".  To overwrite existing
  11. # files, type "sh file -c".  You can also feed this as standard input via
  12. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  13. # will see the following message at the end:
  14. #        "End of archive 6 (of 6)."
  15. # Contents:  src/kernel.c
  16. # Wrapped by mip@mina on Fri Jun 29 16:49:14 1990
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f src/kernel.c -a "${1}" != "-c" ; then 
  19.   echo shar: Will not over-write existing file \"src/kernel.c\"
  20. else
  21. echo shar: Extracting \"src/kernel.c\" \(49941 characters\)
  22. sed "s/^X//" >src/kernel.c <<'END_OF_src/kernel.c'
  23. X/*
  24. X  C BASED FORTH-83 MULTI-TASKING KERNEL
  25. X
  26. X  Copyright (c) 1988-1990 by Mikael R.K. Patel
  27. X
  28. X  Computer Aided Design Laboratory (CADLAB)
  29. X  Department of Computer and Information Science
  30. X  Linkoping University
  31. X  S-581 83 LINKOPING
  32. X  SWEDEN
  33. X
  34. X  Email: mip@ida.liu.se
  35. X
  36. X  Started on: 30 June 1988
  37. X
  38. X  Last updated on: 25 June 1990
  39. X
  40. X  Dependencies:
  41. X      (cc) kernel.h, error.h, memory.h, io.c, compiler.v,
  42. X         locals.v, string.v, float.v, memory.v, queues.v,
  43. X         multi-tasking.v, and exceptions.v.
  44. X
  45. X  Description:
  46. X       Virtual Forth machine and kernel code supporting multi-tasking of
  47. X       light weight processes. A pure 32-bit Forth-83 Standard implementation.
  48. X
  49. X       Extended with floating point numbers, argument binding and local
  50. X       variables, exception handling, queue data management, multi-tasking,
  51. X       symbol hiding and casting, forwarding, null terminated string,
  52. X       memory allocation, file search paths, and source library module
  53. X       loading.
  54. X  
  55. X       The kernel does not implement the block word set. All code is
  56. X       stored as text files.
  57. X
  58. X  Copying:
  59. X       This program is free software; you can redistribute it and/or modify
  60. X       it under the terms of the GNU General Public License as published by
  61. X       the Free Software Foundation; either version 1, or (at your option)
  62. X       any later version.
  63. X
  64. X       This program is distributed in the hope that it will be useful,
  65. X       but WITHOUT ANY WARRANTY; without even the implied warranty of
  66. X       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  67. X       GNU General Public License for more details.
  68. X
  69. X       You should have received a copy of the GNU General Public License
  70. X       along with this program; see the file COPYING.  If not, write to
  71. X       the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  72. X
  73. X*/
  74. X
  75. X#include "kernel.h"
  76. X#include "memory.h"
  77. X#include "error.h"
  78. X#include "io.h"
  79. X
  80. X
  81. X/* EXTERNAL DECLARATIONS */
  82. X
  83. Xextern VOID io_dispatch();
  84. X
  85. X
  86. X/* INTERNAL FORWARD DECLARATIONS */
  87. X
  88. Xextern code_entry qnumber;
  89. Xextern code_entry terminate;
  90. Xextern code_entry abort_entry;
  91. Xextern entry toexception;
  92. Xextern entry span;
  93. Xextern entry state;
  94. Xextern code_entry vocabulary;
  95. X
  96. X
  97. X/* VOCABULARY LISTING PARAMETERS */
  98. X
  99. X#define COLUMNWIDTH 15
  100. X#define LINEWIDTH 75
  101. X
  102. X
  103. X/* CONTROL STRUCTURE MARKERS */
  104. X
  105. X#define ELSE 1
  106. X#define THEN 2
  107. X#define AGAIN 4
  108. X#define UNTIL 8
  109. X#define WHILE 16
  110. X#define REPEAT 32
  111. X#define LOOP 64
  112. X#define PLUSLOOP 128
  113. X#define OF 256
  114. X#define ENDOF 512
  115. X#define ENDCASE 1024
  116. X#define SEMICOLON 2048
  117. X
  118. X
  119. X/* MULTI-TASKING MACHINE REGISTERS */
  120. X
  121. XINT32 verbose;            /* Application or programming mode */
  122. XINT32 quited;            /* Interpreter toploop state */
  123. XINT32 running;            /* Task switch flag */
  124. XINT32 tasking;            /* Multi-tasking flag */
  125. X
  126. XTASK tp;            /* Task pointer */
  127. XTASK foreground;        /* Foreground task pointer */
  128. X
  129. X
  130. X/* FORTH MACHINE REGISTERS */
  131. X
  132. XUNIV tos;            /* Top of stack register */
  133. XPTR sp;                /* Parameter stack pointer */
  134. XPTR s0;                /* Bottom of parameter stack pointer */
  135. X
  136. XPTR32 ip;            /* Instruction pointer */
  137. XPTR32 rp;            /* Return stack pointer */
  138. XPTR32 r0;            /* Bottom of return stack pointer */
  139. X
  140. XPTR32 fp;            /* Argument frame pointer */
  141. XPTR32 ep;            /* Exception frame pointer */
  142. X
  143. X
  144. X/* VOCABULARY SEARCH LISTS */
  145. X
  146. X#define CONTEXTSIZE 64
  147. X
  148. Xstatic VOCABULARY_ENTRY current = &forth;
  149. Xstatic VOCABULARY_ENTRY context[CONTEXTSIZE] = {&forth};
  150. X
  151. X
  152. X/* ENTRY LOOKUP CACHE, SIZE AND HASH FUNCTION */
  153. X
  154. X#define CACHESIZE 256
  155. X#define hash(s) ((s[0] + (s[1] << 4)) & (CACHESIZE - 1))
  156. X
  157. Xstatic ENTRY cache[CACHESIZE];
  158. X
  159. X
  160. X/* DICTIONARY AREA FOR THREADED CODE AND DATA */
  161. X
  162. XPTR32 dictionary;
  163. XPTR32 dp;
  164. X
  165. X
  166. X/* INTERNAL STRUCTURE AND SIZES */
  167. X
  168. Xstatic INT32 hld;
  169. Xstatic ENTRY thelast = NIL;
  170. X
  171. X#define PADSIZE 84
  172. Xstatic CHAR thepad[PADSIZE];
  173. X
  174. X#define TIBSIZE 256
  175. Xstatic CHAR thetib[TIBSIZE];
  176. X    
  177. X
  178. X/* INNER MULTI-TASKING FORTH VIRTUAL MACHINE */
  179. X
  180. XVOID doinner()
  181. X{
  182. X    INT32 e;
  183. X
  184. X    /* Exception marking and handler */
  185. X    if (e = setjmp(restart)) {
  186. X    spush(e, INT32);
  187. X    doraise();
  188. X    }
  189. X    
  190. X    /* Run virtual machine until task switch */
  191. X    running = TRUE;
  192. X    while (running) {
  193. X
  194. X    /* Fetch next thread to execute */
  195. X    register ENTRY p = (ENTRY) *ip++;
  196. X
  197. X    /* Select on type of entry */
  198. X    switch (p -> code) {
  199. X      case CODE:
  200. X        ((SUBR) (p -> parameter))(); 
  201. X        break;
  202. X      case COLON:
  203. X        rpush(ip);
  204. X        fjump(p -> parameter);
  205. X        break;
  206. X      case VARIABLE:
  207. X        spush(&(p -> parameter), PTR32);
  208. X        break;
  209. X      case CONSTANT:
  210. X        spush(p -> parameter, INT32);
  211. X        break;
  212. X      case VOCABULARY:
  213. X        doappend((VOCABULARY_ENTRY) p);
  214. X        break;
  215. X      case CREATE:
  216. X        spush(p -> parameter, INT32);
  217. X        break;
  218. X      case USER:
  219. X        spush(((INT32) tp) + p -> parameter, INT32);
  220. X        break;
  221. X      case LOCAL:
  222. X        spush(*((PTR32) (INT32) fp - p -> parameter), INT32);
  223. X        break;
  224. X      case FORWARD:
  225. X        if (p -> parameter)
  226. X        docall((ENTRY) p -> parameter);
  227. X        else {
  228. X        if (io_source())
  229. X            (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  230. X        (VOID) fprintf(io_errf, "%s: unresolved forward entry\n", p -> name);
  231. X        doabort();
  232. X        }
  233. X        break;
  234. X      case EXCEPTION:
  235. X        spush(p, ENTRY);
  236. X        break;
  237. X      case FIELD:
  238. X        unary(p -> parameter +, INT32);
  239. X        break;
  240. X      default: /* DOES: FORTH LEVEL INTERPRETATION */
  241. X        rpush(ip);
  242. X        spush(p -> parameter, INT32);
  243. X        fjump(p -> code);
  244. X        break;
  245. X    }
  246. X    }
  247. X}
  248. X
  249. XVOID docommand()
  250. X{
  251. X    INT32 e;
  252. X
  253. X    /* Exception marking and handler */
  254. X    if (e = setjmp(restart)) {
  255. X    spush(e, INT32);
  256. X    doraise();
  257. X    return;
  258. X    }
  259. X
  260. X    /* Execute command on top of stack */
  261. X    doexecute();
  262. X
  263. X    /* Check if this affects the virtual machine */
  264. X    if (rp != r0) {
  265. X    tasking = TRUE;
  266. X
  267. X    /* Run the virtual machine and allow user extension */
  268. X    while (tasking) {
  269. X        doinner();
  270. X        io_dispatch();
  271. X    }
  272. X    }
  273. X}
  274. X
  275. XVOID docall(p)
  276. X    ENTRY p;
  277. X{
  278. X    /* Select on type of entry */
  279. X    switch (p -> code) {
  280. X      case CODE:
  281. X    ((SUBR) (p -> parameter))(); 
  282. X    return;    
  283. X      case COLON:
  284. X    rpush(ip);
  285. X    fjump(p -> parameter);
  286. X    return;
  287. X      case VARIABLE:
  288. X    spush(&(p -> parameter), PTR32);
  289. X    return;
  290. X      case CONSTANT:
  291. X    spush(p -> parameter, INT32);
  292. X    return;
  293. X      case VOCABULARY:
  294. X    doappend((VOCABULARY_ENTRY) p);
  295. X    return;
  296. X      case CREATE:
  297. X    spush(p -> parameter, INT32);
  298. X    return;
  299. X      case USER:
  300. X    spush(((INT32) tp) + p -> parameter, INT32);
  301. X    return;
  302. X      case LOCAL:
  303. X    spush(*((PTR32) (INT32) fp - p -> parameter), INT32);
  304. X    return;
  305. X      case FORWARD:
  306. X    if (p -> parameter)
  307. X        docall((ENTRY) p -> parameter);
  308. X    else {
  309. X        if (io_source())
  310. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  311. X        (VOID) fprintf(io_errf, "%s: unresolved forward entry\n", p -> name);
  312. X        doabort();
  313. X    }
  314. X    return;
  315. X      case EXCEPTION:
  316. X    spush(p, ENTRY);
  317. X    return;
  318. X      case FIELD:
  319. X    unary(p -> parameter +, INT32);
  320. X    return;
  321. X      default: /* DOES: FORTH LEVEL INTERPRETATION */
  322. X    rpush(ip);
  323. X    spush(p -> parameter, INT32);
  324. X    fjump(p -> code);
  325. X    return;
  326. X    }
  327. X}
  328. X
  329. XVOID doappend(p)
  330. X    VOCABULARY_ENTRY p;
  331. X{
  332. X    INT32 v;
  333. X    
  334. X    /* Flush the entry cache */
  335. X    spush(FALSE, BOOL);
  336. X    dorestore();
  337. X
  338. X    /* Check if the vocabulary is a member of the current search set */
  339. X    for (v = 0; v < CONTEXTSIZE; v++)
  340. X
  341. X    /* If a member then rotate the vocabulary first */
  342. X    if (p == context[v]) {
  343. X        for (; v; v--) context[v] = context[v - 1];
  344. X        context[0] = p;
  345. X        return;
  346. X    }
  347. X
  348. X    /* If not a member, then insert first into the search set */
  349. X    for (v = CONTEXTSIZE - 1; v > 0; v--) context[v] = context[v - 1];
  350. X    context[0] = p;
  351. X}    
  352. X
  353. X
  354. X/* VOCABULARY ROOT AND EXTERNAL VOCABULARIES */
  355. X
  356. Xvocabulary_entry forth = {NIL, "forth", NORMAL, VOCABULARY, (ENTRY) &vocabulary, (ENTRY) &qnumber};
  357. X
  358. X
  359. X/* COMPILER EXTENSIONS */
  360. X
  361. X#include "compiler.v"
  362. X  
  363. XNORMAL_VOCABULARY(compiler, forth, "compiler", &backwardresolve, NIL);
  364. X
  365. X
  366. X/* LOCAL VARIABLES AND ARGUMENT BINDING */
  367. X
  368. X#include "locals.v"
  369. X
  370. XNORMAL_VOCABULARY(locals, compiler, "locals", &curlebracket, NIL);
  371. X
  372. X
  373. X/* NULL TERMINATED STRING */
  374. X
  375. X#include "string.v"
  376. X
  377. XNORMAL_VOCABULARY(string, locals, "string", &sprint, NIL); 
  378. X
  379. X
  380. X/* FLOATING POINT */
  381. X
  382. X#include "float.v"
  383. X
  384. XNORMAL_VOCABULARY(float_entry, string, "float", &qfloat, &qfloat); 
  385. X
  386. X
  387. X/* MEMORY MANAGEMENT */
  388. X
  389. X#include "memory.v"
  390. X
  391. XNORMAL_VOCABULARY(memory, float_entry, "memory", &free_entry, NIL); 
  392. X
  393. X
  394. X/* DOUBLE LINKED LISTS */
  395. X
  396. X#include "queues.v"
  397. X
  398. XNORMAL_VOCABULARY(queues, memory, "queues", &dequeue, NIL);
  399. X
  400. X
  401. X/* MULTI-TASKING EXTENSIONS */
  402. X
  403. X#include "multi-tasking.v"
  404. X
  405. XNORMAL_VOCABULARY(multitasking, queues, "multi-tasking", &terminate, NIL);
  406. X
  407. X
  408. X/* SIGNAL AND EXCEPTION MANAGEMENT */
  409. X
  410. X#include "exceptions.v"
  411. X
  412. XNORMAL_VOCABULARY(exceptions, multitasking, "exceptions", &raise, NIL);
  413. X
  414. X
  415. X/* LOGIC: FORTH-83 VOCABULARY */
  416. X
  417. XNORMAL_CONSTANT(false, exceptions, "false", FALSE);
  418. X
  419. XNORMAL_CONSTANT(true, false, "true", TRUE);
  420. X
  421. XVOID doboolean()
  422. X{
  423. X    compare(!= 0, INT32);
  424. X}
  425. X
  426. XNORMAL_CODE(boolean, true, "boolean", doboolean);
  427. X
  428. XVOID donot()
  429. X{
  430. X    unary(~, INT32);
  431. X}
  432. X
  433. XNORMAL_CODE(not, boolean, "not", donot);
  434. X
  435. XVOID doand()
  436. X{
  437. X    binary(&, INT32);
  438. X}
  439. X
  440. XNORMAL_CODE(and, not, "and", doand);
  441. X
  442. XVOID door()
  443. X{
  444. X    binary(|, INT32);
  445. X}
  446. X
  447. XNORMAL_CODE(or, and, "or", door);
  448. X
  449. XVOID doxor()
  450. X{
  451. X    binary(^, INT32);
  452. X}
  453. X
  454. XNORMAL_CODE(xor, or, "xor", doxor);
  455. X
  456. XVOID doqwithin()
  457. X{
  458. X    register INT32 value;
  459. X    register INT32 upper;
  460. X    register INT32 lower;
  461. X    
  462. X    upper = spop(INT32);
  463. X    lower = spop(INT32);
  464. X    value = spop(INT32);
  465. X    
  466. X    spush((value > upper) || (value < lower) ? FALSE : TRUE, BOOL);
  467. X}
  468. X    
  469. XNORMAL_CODE(qwithin, xor, "?within", doqwithin);
  470. X
  471. X
  472. X/* STACK MANIPULATION */
  473. X
  474. XVOID dodepth()
  475. X{
  476. X    register PTR32 t;
  477. X
  478. X    t = (PTR32) sp;
  479. X    spush(((PTR32) s0 - t), INT32);
  480. X}
  481. X
  482. XNORMAL_CODE(depth, qwithin, "depth", dodepth);
  483. X
  484. XVOID dodrop()
  485. X{
  486. X    sdrop();
  487. X}
  488. X
  489. XNORMAL_CODE(drop, depth, "drop", dodrop);
  490. X
  491. XVOID donip()
  492. X{
  493. X    snip();
  494. X}
  495. X
  496. XNORMAL_CODE(nip, drop, "nip", donip);
  497. X
  498. XVOID doswap()
  499. X{
  500. X    sswap();
  501. X}
  502. X
  503. XNORMAL_CODE(swap, nip, "swap", doswap);
  504. X
  505. XVOID dorot()
  506. X{
  507. X    srot();
  508. X}
  509. X
  510. XNORMAL_CODE(rot, swap, "rot", dorot);
  511. X
  512. XVOID dodashrot()
  513. X{
  514. X    sdashrot();
  515. X}
  516. X
  517. XNORMAL_CODE(dashrot, rot, "-rot", dodashrot);
  518. X
  519. XVOID doroll()
  520. X{
  521. X    register UNIV e;
  522. X    register PTR s;
  523. X
  524. X    /* Fetch roll parameters: number and element */
  525. X    e = snth(tos.INT32);
  526. X
  527. X    /* Roll the stack */
  528. X    for (s = sp + tos.INT32; s > sp; s--) *s = *(s - 1);
  529. X    sp++;
  530. X    
  531. X    /* And assign the new top of stack */
  532. X    tos = e;
  533. X}
  534. X
  535. XNORMAL_CODE(roll, dashrot, "roll", doroll);
  536. X
  537. XVOID doqdup()
  538. X{
  539. X    if (tos.INT32) sdup();
  540. X}
  541. X
  542. XNORMAL_CODE(qdup, roll, "?dup", doqdup);
  543. X
  544. XVOID dodup()
  545. X{
  546. X    sdup();
  547. X}
  548. X
  549. XNORMAL_CODE(dup_entry, qdup, "dup", dodup);
  550. X
  551. XVOID doover()
  552. X{
  553. X    sover();
  554. X}
  555. X
  556. XNORMAL_CODE(over, dup_entry, "over", doover);
  557. X
  558. XVOID dotuck()
  559. X{
  560. X    stuck();
  561. X}
  562. X
  563. XNORMAL_CODE(tuck, over, "tuck", dotuck);
  564. X
  565. XVOID dopick()
  566. X{
  567. X    tos = snth(tos.INT32);
  568. X}
  569. X
  570. XCOMPILATION_CODE(pick, tuck, "pick", dopick);
  571. X
  572. XVOID dotor()
  573. X{
  574. X    rpush(spop(INT32));
  575. X}
  576. X
  577. XCOMPILATION_CODE(tor, pick, ">r", dotor);
  578. X
  579. XVOID dofromr()
  580. X{
  581. X    spush(rpop(), INT32);
  582. X}
  583. X
  584. XCOMPILATION_CODE(fromr, tor, "r>", dofromr);
  585. X
  586. XVOID docopyr()
  587. X{
  588. X    spush(*rp, INT32);
  589. X}
  590. X
  591. XCOMPILATION_CODE(copyr, fromr, "r@", docopyr);
  592. X
  593. XVOID dotwotor()
  594. X{
  595. X    rpush(spop(INT32));
  596. X    rpush(spop(INT32));
  597. X}
  598. X
  599. XCOMPILATION_CODE(twotor, copyr, "2>r", dotwotor);
  600. X
  601. XVOID dotwofromr()
  602. X{
  603. X    spush(rpop(), INT32);
  604. X    spush(rpop(), INT32);
  605. X}
  606. X
  607. XCOMPILATION_CODE(twofromr, twotor, "2r>", dotwofromr);
  608. X
  609. XVOID dotwodrop()
  610. X{
  611. X    sndrop(1);
  612. X}
  613. X
  614. XNORMAL_CODE(twodrop, twofromr, "2drop", dotwodrop);
  615. X
  616. XVOID dotwoswap()
  617. X{
  618. X    register UNIV t;
  619. X
  620. X    t = tos;
  621. X    tos = snth(1);
  622. X    snth(1) = t;
  623. X
  624. X    t = snth(0);
  625. X    snth(0) = snth(2);
  626. X    snth(2) = t;
  627. X}
  628. X
  629. XNORMAL_CODE(twoswap, twodrop, "2swap", dotwoswap);
  630. X
  631. XVOID dotworot()
  632. X{
  633. X    register UNIV t;
  634. X
  635. X    t = tos;
  636. X    tos = snth(3);
  637. X    snth(3) = snth(1);
  638. X    snth(1) = t;
  639. X    
  640. X    t = snth(0);
  641. X    snth(0) = snth(4);
  642. X    snth(4) = snth(2);
  643. X    snth(2) = t;
  644. X}
  645. X
  646. XNORMAL_CODE(tworot, twoswap, "2rot", dotworot);
  647. X
  648. XVOID dotwodup()
  649. X{
  650. X    spush(snth(1).INT32, INT32);
  651. X    spush(snth(1).INT32, INT32);
  652. X}
  653. X
  654. XNORMAL_CODE(twodup, tworot, "2dup", dotwodup);
  655. X
  656. XVOID dotwoover()
  657. X{
  658. X    spush(snth(3).INT32, INT32);
  659. X    spush(snth(3).INT32, INT32);
  660. X}
  661. X
  662. XNORMAL_CODE(twoover, twodup, "2over", dotwoover);
  663. X
  664. X
  665. X/* COMPARISON */
  666. X
  667. XVOID dolessthan()
  668. X{
  669. X    relation(<, INT32);
  670. X}
  671. X
  672. XNORMAL_CODE(lessthan, twoover, "<", dolessthan);
  673. X
  674. XVOID doequals()
  675. X{
  676. X    relation(==, INT32);
  677. X}
  678. X
  679. XNORMAL_CODE(equals, lessthan, "=", doequals);
  680. X
  681. XVOID dogreaterthan()
  682. X{
  683. X    relation(>, INT32);
  684. X}
  685. X
  686. XNORMAL_CODE(greaterthan, equals, ">", dogreaterthan);
  687. X
  688. XVOID dozeroless()
  689. X{
  690. X    compare(< 0, INT32);
  691. X}
  692. X
  693. XNORMAL_CODE(zeroless, greaterthan, "0<", dozeroless);
  694. X
  695. XVOID dozeroequals()
  696. X{
  697. X    compare(== 0, INT32);
  698. X}
  699. X
  700. XNORMAL_CODE(zeroequals, zeroless, "0=", dozeroequals);
  701. X
  702. XVOID dozerogreater()
  703. X{
  704. X    compare(> 0, INT32);
  705. X}
  706. X
  707. XNORMAL_CODE(zerogreater, zeroequals, "0>", dozerogreater);
  708. X
  709. XVOID doulessthan()
  710. X{
  711. X    relation(<, NUM32);
  712. X}
  713. X
  714. XNORMAL_CODE(ulessthan, zerogreater, "u<", doulessthan);
  715. X
  716. X
  717. X/* CONSTANTS */
  718. X
  719. XNORMAL_CONSTANT(nil, ulessthan, "nil", NIL);
  720. X
  721. XNORMAL_CONSTANT(minusfour, nil, "-4", -4);
  722. X
  723. XNORMAL_CONSTANT(minustwo, minusfour, "-2", -2);
  724. X
  725. XNORMAL_CONSTANT(minusone, minustwo, "-1", -1);
  726. X
  727. XNORMAL_CONSTANT(zero, minusone, "0", 0);
  728. X
  729. XNORMAL_CONSTANT(one, zero, "1", 1);
  730. X
  731. XNORMAL_CONSTANT(two, one, "2", 2);
  732. X
  733. XNORMAL_CONSTANT(four, two, "4", 4);
  734. X
  735. X
  736. X/* ARITHMETRIC */
  737. X
  738. XVOID doplus()
  739. X{
  740. X    binary(+, INT32);
  741. X}
  742. X
  743. XNORMAL_CODE(plus, four, "+", doplus);
  744. X
  745. XVOID dominus()
  746. X{
  747. X    binary(-, INT32);
  748. X}
  749. X
  750. XNORMAL_CODE(minus, plus, "-", dominus);
  751. X
  752. XVOID dooneplus()
  753. X{
  754. X    unary(++, INT32);
  755. X}
  756. X
  757. XNORMAL_CODE(oneplus, minus, "1+", dooneplus);
  758. X
  759. XVOID dooneminus()
  760. X{
  761. X    unary(--, INT32);
  762. X}
  763. X
  764. XNORMAL_CODE(oneminus, oneplus, "1-", dooneminus);
  765. X
  766. XVOID dotwoplus()
  767. X{
  768. X    unary(2 +, INT32);
  769. X}
  770. X
  771. XNORMAL_CODE(twoplus, oneminus, "2+", dotwoplus);
  772. X
  773. XVOID dotwominus()
  774. X{
  775. X    unary(-2 +, INT32);
  776. X}
  777. X
  778. XNORMAL_CODE(twominus, twoplus, "2-", dotwominus);
  779. X
  780. XVOID dotwotimes()
  781. X{
  782. X    tos.INT32 <<= 1;
  783. X}
  784. X
  785. XNORMAL_CODE(twotimes, twominus, "2*", dotwotimes);
  786. X
  787. XVOID doleftshift()
  788. X{
  789. X    binary(<<, INT32);
  790. X}
  791. X
  792. XNORMAL_CODE(leftshift, twotimes, "<<", doleftshift);
  793. X
  794. XVOID dotimes()
  795. X{
  796. X    binary(*, INT32);
  797. X}
  798. X
  799. XNORMAL_CODE(times_entry, leftshift, "*", dotimes);
  800. X
  801. XVOID doumtimes()
  802. X{
  803. X    binary(*, NUM32);
  804. X}
  805. X
  806. XNORMAL_CODE(utimes_entry, times_entry, "um*", doumtimes);
  807. X
  808. XVOID doumdividemod()
  809. X{
  810. X    register NUM32 t;
  811. X
  812. X    t = snth(0).NUM32;
  813. X    snth(0).NUM32 = t % tos.NUM32;
  814. X    tos.NUM32 = t / tos.NUM32;
  815. X}
  816. X
  817. XNORMAL_CODE(umdividemod, utimes_entry, "um/mod", doumdividemod);
  818. X
  819. XVOID dotwodivide()
  820. X{
  821. X    tos.INT32 >>= 1;
  822. X}
  823. X
  824. XNORMAL_CODE(twodivide, umdividemod, "2/", dotwodivide);
  825. X
  826. XVOID dorightshift()
  827. X{
  828. X    binary(>>, INT32);
  829. X}
  830. X
  831. XNORMAL_CODE(rightshift, twodivide, ">>", dorightshift);
  832. X
  833. XVOID dodivide()
  834. X{
  835. X    binary(/, INT32);
  836. X}
  837. X
  838. XNORMAL_CODE(divide, rightshift, "/", dodivide);
  839. X
  840. XVOID domod()
  841. X{
  842. X    binary(%, INT32);
  843. X}
  844. X
  845. XNORMAL_CODE(mod, divide, "mod", domod);
  846. X
  847. XVOID dodividemod()
  848. X{
  849. X    register INT32 t;
  850. X
  851. X    t = snth(0).INT32;
  852. X    snth(0).INT32 = t % tos.INT32;
  853. X    tos.INT32 = t / tos.INT32;
  854. X}
  855. X
  856. XNORMAL_CODE(dividemod, mod, "/mod", dodividemod);
  857. X
  858. XVOID dotimesdividemod()
  859. X{
  860. X    register INT32 t;
  861. X
  862. X    t = spop(INT32);
  863. X    tos.INT32 = tos.INT32 * snth(0).INT32;
  864. X    snth(0).INT32 = tos.INT32 % t;
  865. X    tos.INT32 = tos.INT32 / t;
  866. X}
  867. X
  868. XNORMAL_CODE(timesdividemod, dividemod, "*/mod", dotimesdividemod);
  869. X
  870. XVOID dotimesdivide()
  871. X{
  872. X    register INT32 t;
  873. X
  874. X    t = spop(INT32);
  875. X    binary(*, INT32);
  876. X    spush(t, INT32);
  877. X    binary(/, INT32);
  878. X}
  879. X
  880. XNORMAL_CODE(timesdivide, timesdividemod, "*/", dotimesdivide);
  881. X
  882. XVOID domin()
  883. X{
  884. X    register INT32 t;
  885. X
  886. X    t = spop(INT32);
  887. X    tos.INT32 = (t < tos.INT32 ? t : tos.INT32);
  888. X}
  889. X
  890. XNORMAL_CODE(min, timesdivide, "min", domin);
  891. X
  892. XVOID domax()
  893. X{
  894. X    register INT32 t;
  895. X
  896. X    t = spop(INT32);
  897. X    tos.INT32 = (t > tos.INT32 ? t : tos.INT32);
  898. X}
  899. X
  900. XNORMAL_CODE(max, min, "max", domax);
  901. X
  902. XVOID doabs()
  903. X{
  904. X    tos.INT32 = (tos.INT32 < 0 ? - tos.INT32 : tos.INT32);
  905. X}
  906. X
  907. XNORMAL_CODE(abs_entry, max, "abs", doabs);
  908. X
  909. XVOID donegate()
  910. X{
  911. X    unary(-, INT32);
  912. X}
  913. X
  914. XNORMAL_CODE(negate, abs_entry, "negate", donegate);
  915. X
  916. X
  917. X/* MEMORY */
  918. X
  919. XVOID dofetch()
  920. X{
  921. X    unary(*(PTR32), INT32);
  922. X}
  923. X
  924. XNORMAL_CODE(fetch, negate, "@", dofetch);
  925. X
  926. XVOID dostore()
  927. X{
  928. X    register PTR32 t;
  929. X
  930. X    t = spop(PTR32);
  931. X    *t = spop(INT32);
  932. X}
  933. X
  934. XNORMAL_CODE(store, fetch, "!", dostore);
  935. X
  936. XVOID dowfetch()
  937. X{
  938. X    unary(*(PTR16), INT32);
  939. X}
  940. X
  941. XNORMAL_CODE(wfetch, store, "w@", dowfetch);
  942. X
  943. XVOID dowstore()
  944. X{
  945. X    register PTR16 t;
  946. X
  947. X    t = spop(PTR16);
  948. X    *t = spop(INT32);
  949. X}
  950. X
  951. XNORMAL_CODE(wstore, wfetch, "w!", dowstore);
  952. X
  953. XVOID docfetch()
  954. X{
  955. X    unary(*(CSTR), INT32);
  956. X}
  957. X
  958. XNORMAL_CODE(cfetch, wstore, "c@", docfetch);
  959. X
  960. XVOID docstore()
  961. X{
  962. X    register CSTR t;
  963. X
  964. X    t = spop(CSTR);
  965. X    *t = spop(INT32);
  966. X}
  967. X
  968. XNORMAL_CODE(cstore, cfetch, "c!", docstore);
  969. X
  970. XVOID doffetch()
  971. X{
  972. X    register INT32 pos;
  973. X    register INT32 width;
  974. X
  975. X    width = spop(INT32);
  976. X    pos = spop(INT32);
  977. X    tos.INT32 = (tos.INT32 >> pos) & ~(-1 << width);
  978. X}
  979. X
  980. XNORMAL_CODE(ffetch, cstore, "f@", doffetch);
  981. X
  982. XVOID dolessffetch()
  983. X{
  984. X    register INT32 pos;
  985. X    register INT32 width;
  986. X
  987. X    width = spop(INT32);
  988. X    pos = spop(INT32);
  989. X    tos.INT32 = (tos.INT32 >> pos) & ~(-1 << width);
  990. X    if ((1 << (width - 1)) & tos.INT32) {
  991. X    tos.INT32 = (tos.INT32) | (-1 << width);
  992. X    }
  993. X}
  994. X
  995. XNORMAL_CODE(lessffetch, ffetch, "<f@", dolessffetch);
  996. X
  997. XVOID dofstore()
  998. X{
  999. X    register INT32 pos;
  1000. X    register INT32 width;
  1001. X    register INT32 value;
  1002. X
  1003. X    width = spop(INT32);
  1004. X    pos = spop(INT32);
  1005. X    value = spop(INT32);
  1006. X    tos.INT32 = ((tos.INT32 & ~(-1 << width)) << pos) | (value & ~((~(-1 << width)) << pos));
  1007. X}
  1008. X
  1009. XNORMAL_CODE(fstore, lessffetch, "f!", dofstore);
  1010. X
  1011. XVOID dobfetch()
  1012. X{
  1013. X    register INT32 bit;
  1014. X
  1015. X    bit = spop(INT32);
  1016. X    tos.INT32 = (((tos.INT32 >> bit) & 1) ? TRUE : FALSE);
  1017. X}
  1018. X
  1019. XNORMAL_CODE(bfetch, fstore, "b@", dobfetch);
  1020. X
  1021. XVOID dobstore()
  1022. X{
  1023. X    register INT32 bit;
  1024. X    register INT32 value;
  1025. X
  1026. X    bit = spop(INT32);
  1027. X    value = spop(INT32);
  1028. X    tos.INT32 = (tos.INT32 ? (value | (1 << bit)) : (value & ~(1 << bit)));
  1029. X}
  1030. X
  1031. XNORMAL_CODE(bstore, bfetch, "b!", dobstore);
  1032. X
  1033. XVOID doplusstore()
  1034. X{
  1035. X    register PTR32 t;
  1036. X
  1037. X    t = spop(PTR32);
  1038. X    *t += spop(INT32);
  1039. X}
  1040. X
  1041. XNORMAL_CODE(plusstore, bstore, "+!", doplusstore);
  1042. X
  1043. XVOID dotwofetch()
  1044. X{
  1045. X    register PTR32 t;
  1046. X
  1047. X    t = tos.PTR32;
  1048. X    spush(*t++, INT32);
  1049. X    snth(0).INT32 = *t;
  1050. X}
  1051. X
  1052. XNORMAL_CODE(twofetch, plusstore, "2@", dotwofetch);
  1053. X
  1054. XVOID dotwostore()
  1055. X{
  1056. X    register PTR32 t;
  1057. X
  1058. X    t = spop(PTR32);
  1059. X    *t++ = spop(INT32);
  1060. X    *t = spop(INT32);
  1061. X}
  1062. X
  1063. XNORMAL_CODE(twostore, twofetch, "2!", dotwostore);
  1064. X
  1065. X
  1066. X/* STRINGS */
  1067. X
  1068. XVOID docmove()
  1069. X{
  1070. X    register INT32 n;
  1071. X    register CSTR to;
  1072. X    register CSTR from;
  1073. X
  1074. X    n = spop(INT32);
  1075. X    to = spop(CSTR);
  1076. X    from = spop(CSTR);
  1077. X
  1078. X    while (--n != -1) *to++ = *from++;
  1079. X}
  1080. X
  1081. XNORMAL_CODE(cmove, twostore, "cmove", docmove);
  1082. X
  1083. XVOID docmoveup()
  1084. X{
  1085. X    register INT32 n;
  1086. X    register CSTR to;
  1087. X    register CSTR from;
  1088. X
  1089. X    n = spop(INT32);
  1090. X    to = spop(CSTR);
  1091. X    from = spop(CSTR);
  1092. X
  1093. X    to += n;
  1094. X    from += n;
  1095. X    while (--n != -1) *--to = *--from;
  1096. X}
  1097. X
  1098. XNORMAL_CODE(cmoveup, cmove, "cmove>", docmoveup);
  1099. X
  1100. XVOID dofill()
  1101. X{
  1102. X    register INT32 with;
  1103. X    register INT32 n;
  1104. X    register CSTR from;
  1105. X
  1106. X    with = spop(INT32);
  1107. X    n = spop(INT32);
  1108. X    from = spop(CSTR);
  1109. X
  1110. X    while (--n != -1) *from++ = with;
  1111. X}
  1112. X
  1113. XNORMAL_CODE(fill, cmoveup, "fill", dofill);
  1114. X
  1115. XVOID docount()
  1116. X{
  1117. X    register CSTR t;
  1118. X
  1119. X    t = spop(CSTR);
  1120. X    spush(*t++, INT32);
  1121. X    spush(t, CSTR);
  1122. X}
  1123. X
  1124. XNORMAL_CODE(count, fill, "count", docount);
  1125. X
  1126. XVOID dobounds()
  1127. X{
  1128. X    register CSTR n;
  1129. X
  1130. X    n = snth(0).CSTR;
  1131. X    snth(0).CSTR = snth(0).CSTR + tos.INT32;
  1132. X    tos.CSTR = n;
  1133. X}
  1134. X
  1135. XNORMAL_CODE(bounds, count, "bounds", dobounds);
  1136. X
  1137. XVOID dodashtrailing()
  1138. X{
  1139. X    register CSTR p;
  1140. X
  1141. X    p = snth(0).CSTR + tos.INT32;
  1142. X    tos.INT32 += 1;
  1143. X    while (--tos.INT32 && (*--p == ' '));
  1144. X}
  1145. X
  1146. XNORMAL_CODE(dashtrailing, bounds, "-trailing", dodashtrailing);
  1147. X
  1148. XVOID dodashmatch()
  1149. X{
  1150. X    register INT32 n;
  1151. X    register CSTR s;
  1152. X    register CSTR t;
  1153. X    
  1154. X    n = spop(INT32);
  1155. X    s = spop(CSTR);
  1156. X    t = spop(CSTR);
  1157. X
  1158. X    if (n) {
  1159. X    while ((n) && (*s++ == *t++)) n--;
  1160. X    spush(n ? TRUE : FALSE, BOOL);
  1161. X    }
  1162. X    else {
  1163. X    spush(TRUE, BOOL);
  1164. X    }
  1165. X}
  1166. X
  1167. XNORMAL_CODE(dashmatch, dashtrailing, "-match", dodashmatch);
  1168. X
  1169. X
  1170. X/* NUMERICAL CONVERSION */
  1171. X
  1172. XNORMAL_VARIABLE(base, dashmatch, "base", 10);
  1173. X
  1174. XVOID dobinary()
  1175. X{
  1176. X    base.parameter = 2;
  1177. X}
  1178. X
  1179. XNORMAL_CODE(binary_entry, base, "binary", dobinary);
  1180. X
  1181. XVOID dooctal()
  1182. X{
  1183. X    base.parameter = 8;
  1184. X}
  1185. X
  1186. XNORMAL_CODE(octal, binary_entry, "octal", dooctal);
  1187. X
  1188. XVOID dodecimal()
  1189. X{
  1190. X    base.parameter = 10;
  1191. X}
  1192. X
  1193. XNORMAL_CODE(decimal, octal, "decimal", dodecimal);
  1194. X
  1195. XVOID dohex()
  1196. X{
  1197. X    base.parameter = 16;
  1198. X}
  1199. X
  1200. XNORMAL_CODE(hex, decimal, "hex", dohex);
  1201. X
  1202. XVOID doconvert()
  1203. X{
  1204. X    register CHAR c;
  1205. X    register INT32 b;
  1206. X    register INT32 n;
  1207. X    
  1208. X    b = base.parameter;
  1209. X    n = snth(0).INT32;
  1210. X
  1211. X    for (;;) {
  1212. X    c = *tos.CSTR;
  1213. X    if (c < '0' || c > 'z' || (c > '9' && c < 'a')) {
  1214. X        snth(0).INT32 = n;
  1215. X        return;
  1216. X    }
  1217. X    else {
  1218. X        if (c > '9') c = c - 'a' + ':';
  1219. X        c = c - '0';
  1220. X        if (c < 0 || c >= b) {
  1221. X        snth(0).INT32 = n;
  1222. X        return;
  1223. X        }
  1224. X        n = (n * b) + c;
  1225. X        tos.INT32 += 1;
  1226. X    }
  1227. X    }
  1228. X}
  1229. X
  1230. XNORMAL_CODE(convert, hex, "convert", doconvert);
  1231. X
  1232. XVOID dolesssharp()
  1233. X{
  1234. X    hld = (INT32) thepad + PADSIZE;
  1235. X}
  1236. X
  1237. XNORMAL_CODE(lesssharp, convert, "<#", dolesssharp);
  1238. X
  1239. XVOID dosharp()
  1240. X{
  1241. X    register NUM32 n;
  1242. X
  1243. X    n = tos.NUM32;
  1244. X    tos.NUM32 = n / (unsigned INT32) base.parameter;
  1245. X    n = n % (unsigned INT32) base.parameter;
  1246. X    *(CSTR) --hld = n + ((n > 9) ? 'a' - 10 : '0');
  1247. X}
  1248. X
  1249. XNORMAL_CODE(sharp, lesssharp, "#", dosharp);
  1250. X
  1251. XVOID dosharps()
  1252. X{
  1253. X    do { dosharp(); } while (tos.INT32);
  1254. X}
  1255. X
  1256. XNORMAL_CODE(sharps, sharp, "#s", dosharps);
  1257. X
  1258. XVOID dohold()
  1259. X{
  1260. X    *(CSTR) --hld = spop(INT32);
  1261. X}
  1262. X
  1263. XNORMAL_CODE(hold, sharps, "hold", dohold);
  1264. X
  1265. XVOID dosign()
  1266. X{
  1267. X    INT32 flag;
  1268. X
  1269. X    flag = spop(INT32);
  1270. X    if (flag < 0) *(CSTR) --hld = '-';
  1271. X}
  1272. X
  1273. XNORMAL_CODE(sign, hold, "sign", dosign);
  1274. X
  1275. XVOID dosharpgreater()
  1276. X{
  1277. X    tos.INT32 = hld;
  1278. X    spush((INT32) thepad + PADSIZE - hld, INT32);
  1279. X}
  1280. X
  1281. XNORMAL_CODE(sharpgreater, sign, "#>", dosharpgreater);
  1282. X
  1283. XVOID doqnumber()
  1284. X{
  1285. X    CSTR s0;
  1286. X    CSTR s1;
  1287. X    
  1288. X    s0 = spop(CSTR);
  1289. X    spush(0, INT32);
  1290. X    if (*s0 == '-') {
  1291. X    spush(s0 + 1, CSTR);
  1292. X    }
  1293. X    else {
  1294. X    spush(s0, CSTR);
  1295. X    }
  1296. X    doconvert();
  1297. X    s1 = spop(CSTR);
  1298. X    if (*s1 == '\0') {
  1299. X    if (*s0 == '-') unary(-, INT32);
  1300. X    spush(TRUE, BOOL);
  1301. X    }
  1302. X    else {
  1303. X    tos.CSTR = s0;
  1304. X    spush(FALSE, BOOL);
  1305. X    }
  1306. X}
  1307. X
  1308. XNORMAL_CODE(qnumber, sharpgreater, "?number", doqnumber);
  1309. X
  1310. X
  1311. X/* CONTROL STRUCTURES */
  1312. X
  1313. XINT32 docheck(this)
  1314. X    int this;
  1315. X{
  1316. X    ENTRY last;
  1317. X    INT32 follow = spop(INT32);
  1318. X
  1319. X    /* Check if the symbol is in the follow set */
  1320. X    if (this & follow) {
  1321. X
  1322. X    /* Return true is so */
  1323. X    return TRUE;
  1324. X    }
  1325. X    else {
  1326. X
  1327. X    /* Else report a control structure error */
  1328. X    dolast();
  1329. X    last = spop(ENTRY);
  1330. X    if (io_source())
  1331. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  1332. X    (VOID) fprintf(io_errf, "%s: illegal control structure\n", last -> name);
  1333. X    doabort();
  1334. X
  1335. X    return FALSE;
  1336. X    }
  1337. X}
  1338. X
  1339. XVOID dodo()
  1340. X{
  1341. X    spush(&parendo, CODE_ENTRY);
  1342. X    dothread();
  1343. X    doforwardmark();
  1344. X    dobackwardmark();
  1345. X    spush(LOOP+PLUSLOOP, INT32);
  1346. X}
  1347. X
  1348. XCOMPILATION_IMMEDIATE_CODE(do_entry, qnumber, "do", dodo);
  1349. X
  1350. XVOID doqdo()
  1351. X{
  1352. X    spush(&parenqdo, CODE_ENTRY);
  1353. X    dothread();
  1354. X    doforwardmark();
  1355. X    dobackwardmark();
  1356. X    spush(LOOP+PLUSLOOP, INT32);
  1357. X}
  1358. X
  1359. XCOMPILATION_IMMEDIATE_CODE(qdo_entry, do_entry, "?do", doqdo);
  1360. X
  1361. XVOID doloop()
  1362. X{
  1363. X    if (docheck(LOOP)) {
  1364. X    spush(&parenloop, CODE_ENTRY);
  1365. X    dothread();
  1366. X    dobackwardresolve();
  1367. X    doforwardresolve();
  1368. X    }
  1369. X}
  1370. X
  1371. XCOMPILATION_IMMEDIATE_CODE(loop, qdo_entry, "loop", doloop);
  1372. X
  1373. XVOID doplusloop()
  1374. X{
  1375. X    if (docheck(PLUSLOOP)) {
  1376. X    spush(&parenplusloop, CODE_ENTRY);
  1377. X    dothread();
  1378. X    dobackwardresolve();
  1379. X    doforwardresolve();
  1380. X    }
  1381. X}
  1382. X
  1383. XCOMPILATION_IMMEDIATE_CODE(plusloop, loop, "+loop", doplusloop);
  1384. X
  1385. XVOID doleave()
  1386. X{
  1387. X    rndrop(2);
  1388. X    fjump(rpop());
  1389. X    fbranch(*ip);
  1390. X}
  1391. X
  1392. XCOMPILATION_CODE(leave, plusloop, "leave", doleave);
  1393. X
  1394. XVOID doi()
  1395. X{
  1396. X    spush(rnth(1), INT32);
  1397. X}
  1398. X
  1399. XCOMPILATION_CODE(i_entry, leave,"i", doi);
  1400. X
  1401. XVOID doj()
  1402. X{
  1403. X    spush(rnth(4), INT32);
  1404. X}
  1405. X
  1406. XCOMPILATION_CODE(j_entry, i_entry, "j", doj);
  1407. X
  1408. XVOID doif()
  1409. X{
  1410. X    spush(&parenqbranch, CODE_ENTRY);
  1411. X    dothread();
  1412. X    doforwardmark();
  1413. X    spush(ELSE+THEN, INT32);
  1414. X}
  1415. X
  1416. XCOMPILATION_IMMEDIATE_CODE(if_entry, j_entry, "if", doif);
  1417. X
  1418. XVOID doelse()
  1419. X{
  1420. X    if (docheck(ELSE)) {
  1421. X    spush(&parenbranch, CODE_ENTRY);
  1422. X    dothread();
  1423. X    doforwardmark();
  1424. X    doswap();
  1425. X    doforwardresolve();
  1426. X    spush(THEN, INT32);
  1427. X    }
  1428. X}
  1429. X
  1430. XCOMPILATION_IMMEDIATE_CODE(else_entry, if_entry, "else", doelse);
  1431. X
  1432. XVOID dothen()
  1433. X{
  1434. X    if (docheck(THEN)) {
  1435. X    doforwardresolve();
  1436. X    }
  1437. X}
  1438. X
  1439. XCOMPILATION_IMMEDIATE_CODE(then_entry, else_entry, "then", dothen);
  1440. X
  1441. XVOID docase()
  1442. X{
  1443. X    spush(0, INT32);
  1444. X    spush(OF+ENDCASE, INT32);
  1445. X}
  1446. X
  1447. XCOMPILATION_IMMEDIATE_CODE(case_entry, then_entry, "case", docase);
  1448. X
  1449. XVOID doof()
  1450. X{
  1451. X    if (docheck(OF)) {
  1452. X    spush(&over, CODE_ENTRY);
  1453. X    dothread();
  1454. X    spush(&equals, CODE_ENTRY);
  1455. X    dothread();
  1456. X    spush(&parenqbranch, CODE_ENTRY);
  1457. X    dothread();
  1458. X    doforwardmark();
  1459. X    spush(&drop, CODE_ENTRY);
  1460. X    dothread();
  1461. X    spush(ENDOF, INT32);
  1462. X    }
  1463. X}
  1464. X
  1465. XCOMPILATION_IMMEDIATE_CODE(of_entry, case_entry, "of", doof);
  1466. X
  1467. XVOID doendof()
  1468. X{
  1469. X    if (docheck(ENDOF)) {
  1470. X    spush(&parenbranch, CODE_ENTRY);
  1471. X    dothread();
  1472. X    doforwardmark();
  1473. X    doswap();
  1474. X    doforwardresolve();
  1475. X    spush(OF+ENDCASE, INT32);
  1476. X    }
  1477. X}
  1478. X
  1479. XCOMPILATION_IMMEDIATE_CODE(endof, of_entry, "endof", doendof);
  1480. X
  1481. XVOID doendcase()
  1482. X{
  1483. X    if (docheck(ENDCASE)) {
  1484. X    spush(&drop, CODE_ENTRY);
  1485. X    dothread();
  1486. X    while (tos.INT32) doforwardresolve();
  1487. X    dodrop();
  1488. X    }
  1489. X}
  1490. X
  1491. XCOMPILATION_IMMEDIATE_CODE(endcase, endof, "endcase", doendcase);
  1492. X
  1493. XVOID dobegin()
  1494. X{
  1495. X    dobackwardmark();
  1496. X    spush(AGAIN+UNTIL+WHILE, INT32);
  1497. X}
  1498. X
  1499. XCOMPILATION_IMMEDIATE_CODE(begin, endcase, "begin", dobegin);
  1500. X
  1501. XVOID dountil()
  1502. X{
  1503. X    if (docheck(UNTIL)) {
  1504. X    spush(&parenqbranch, CODE_ENTRY);
  1505. X    dothread();
  1506. X    dobackwardresolve();
  1507. X    }
  1508. X}
  1509. X
  1510. XCOMPILATION_IMMEDIATE_CODE(until, begin, "until", dountil);
  1511. X
  1512. XVOID dowhile()
  1513. X{
  1514. X    if (docheck(WHILE)) {
  1515. X    spush(&parenqbranch, CODE_ENTRY);
  1516. X    dothread();
  1517. X    doforwardmark();
  1518. X    spush(REPEAT, INT32);
  1519. X    }
  1520. X}
  1521. X
  1522. XCOMPILATION_IMMEDIATE_CODE(while_entry, until, "while", dowhile);
  1523. X
  1524. XVOID dorepeat()
  1525. X{
  1526. X    if (docheck(REPEAT)) {
  1527. X    spush(&parenbranch, CODE_ENTRY);
  1528. X    dothread();
  1529. X    doswap();
  1530. X    dobackwardresolve();
  1531. X    doforwardresolve();
  1532. X    }
  1533. X}
  1534. X
  1535. XCOMPILATION_IMMEDIATE_CODE(repeat, while_entry, "repeat", dorepeat);
  1536. X
  1537. XVOID doagain()
  1538. X{
  1539. X    if (docheck(AGAIN)) { 
  1540. X    spush(&parenbranch, CODE_ENTRY);
  1541. X    dothread();
  1542. X    dobackwardresolve();
  1543. X    }
  1544. X}
  1545. X
  1546. XCOMPILATION_IMMEDIATE_CODE(again, repeat, "again", doagain);
  1547. X
  1548. XVOID dorecurse()
  1549. X{
  1550. X    dolast();
  1551. X    dothread();
  1552. X}
  1553. X
  1554. XCOMPILATION_IMMEDIATE_CODE(recurse, again, "recurse", dorecurse);
  1555. X
  1556. XVOID dotailrecurse()
  1557. X{
  1558. X    if (theframed) {
  1559. X     spush(&parenunlink, CODE_ENTRY);
  1560. X    dothread();
  1561. X    }
  1562. X    dolast();
  1563. X    dotobody();
  1564. X    spush(&parenbranch, CODE_ENTRY);
  1565. X    dothread();
  1566. X    dobackwardresolve();
  1567. X}
  1568. X
  1569. XCOMPILATION_IMMEDIATE_CODE(tailrecurse, recurse, "tail-recurse", dotailrecurse);
  1570. X
  1571. XVOID doexit()
  1572. X{
  1573. X    fsemicolon();
  1574. X}
  1575. X
  1576. XCOMPILATION_CODE(exit_entry, tailrecurse, "exit", doexit);
  1577. X
  1578. XVOID doexecute()
  1579. X{
  1580. X    ENTRY t;
  1581. X
  1582. X    t = spop(ENTRY);
  1583. X    docall(t);
  1584. X}
  1585. X
  1586. XNORMAL_CODE(execute, exit_entry, "execute", doexecute);
  1587. X
  1588. XVOID dobye()
  1589. X{
  1590. X    quited = FALSE;
  1591. X}
  1592. X
  1593. XNORMAL_CODE(bye, execute, "bye", dobye);
  1594. X
  1595. X
  1596. X/* TERMINAL INPUT-OUTPUT */
  1597. X
  1598. XVOID dodot()
  1599. X{
  1600. X    if (tos.INT32 < 0) {
  1601. X    (VOID) fputc('-', io_outf);
  1602. X    unary(-, INT32);
  1603. X    }
  1604. X    doudot();
  1605. X}
  1606. X
  1607. XNORMAL_CODE(dot, bye, ".", dodot);
  1608. X
  1609. XVOID dodotr()
  1610. X{
  1611. X    INT32 s, t;
  1612. X
  1613. X    t = spop(INT32);
  1614. X    s = tos.INT32;
  1615. X    doabs();
  1616. X    dolesssharp();
  1617. X    dosharps();
  1618. X    spush(s, INT32);
  1619. X    dosign();
  1620. X    dosharpgreater();
  1621. X    spush(t, INT32);
  1622. X    sover();
  1623. X    dominus();
  1624. X    dospaces();
  1625. X    dotype();
  1626. X}
  1627. X
  1628. XNORMAL_CODE(dotr, dot, ".r", dodotr);
  1629. X
  1630. XVOID doudot()
  1631. X{
  1632. X    dolesssharp();
  1633. X    dosharps();
  1634. X    dosharpgreater();
  1635. X    dotype();
  1636. X    dospace();
  1637. X}
  1638. X
  1639. XNORMAL_CODE(udot, dotr, "u.", doudot);
  1640. X
  1641. XVOID doudotr()
  1642. X{
  1643. X    INT32 t;
  1644. X
  1645. X    t = spop(INT32);
  1646. X    dolesssharp();
  1647. X    dosharps();
  1648. X    dosharpgreater();
  1649. X    spush(t, INT32);
  1650. X    sover();
  1651. X    dominus();
  1652. X    dospaces();
  1653. X    dotype();
  1654. X}
  1655. X
  1656. XNORMAL_CODE(udotr, udot, "u.r", doudotr);
  1657. X
  1658. XVOID doascii()
  1659. X{
  1660. X    spush(' ', INT32);
  1661. X    doword();
  1662. X    docfetch();
  1663. X    doliteral();
  1664. X}
  1665. X
  1666. XIMMEDIATE_CODE(ascii, udotr, "ascii", doascii);
  1667. X
  1668. XVOID dodotquote()
  1669. X{
  1670. X    (VOID) io_scan(thetib, '"');
  1671. X    spush(thetib, CSTR);
  1672. X    dosdup();
  1673. X    spush(&parendotquote, CODE_ENTRY);
  1674. X    dothread();
  1675. X    docomma();
  1676. X}
  1677. X
  1678. XCOMPILATION_IMMEDIATE_CODE(dotquote, ascii, ".\"", dodotquote);
  1679. X
  1680. XVOID dodotparen()
  1681. X{
  1682. X    (VOID) io_scan(thetib, ')'); 
  1683. X    spush(thetib, CSTR);
  1684. X    dosprint();
  1685. X}
  1686. X
  1687. XIMMEDIATE_CODE(dotparen, dotquote, ".(", dodotparen);
  1688. X
  1689. XVOID dodots()
  1690. X{
  1691. X    PTR s;
  1692. X
  1693. X    /* Print the stack depth */
  1694. X    (VOID) fprintf(io_outf, "[%d] ", s0 - sp);
  1695. X
  1696. X    /* Check if there are any elements on the stack */
  1697. X    if (s0 - sp > 0) {
  1698. X
  1699. X    /* Print them and don't forget top of stack */
  1700. X    for (s = s0 - 2; s >= sp; s--) {
  1701. X        (VOID) fprintf(io_outf, "\\");
  1702. X        spush(s -> INT32, INT32);
  1703. X        if (tos.INT32 < 0) {
  1704. X        (VOID) fputc('-', io_outf);
  1705. X        unary(-, INT32);
  1706. X        }
  1707. X        dolesssharp();
  1708. X        dosharps();
  1709. X        dosharpgreater();
  1710. X        dotype();
  1711. X    }
  1712. X    (VOID) fprintf(io_outf, "\\");
  1713. X    dodup();
  1714. X    dodot();
  1715. X    }
  1716. X}
  1717. X
  1718. XNORMAL_CODE(dots, dotparen, ".s", dodots);
  1719. X
  1720. XVOID docr()
  1721. X{
  1722. X    (VOID) fputc('\n', io_outf);
  1723. X}
  1724. X
  1725. XNORMAL_CODE(cr, dots, "cr", docr);
  1726. X
  1727. XVOID doemit()
  1728. X{
  1729. X    CHAR c;
  1730. X
  1731. X    c = (CHAR) spop(INT32);
  1732. X    (VOID) fputc(c, io_outf);
  1733. X}
  1734. X
  1735. XNORMAL_CODE(emit, cr, "emit", doemit);
  1736. X
  1737. XVOID dotype()
  1738. X{
  1739. X    INT32 n;
  1740. X    CSTR s;
  1741. X
  1742. X    n = spop(INT32);
  1743. X    s = spop(CSTR);
  1744. X    while (n--) (VOID) fputc(*s++, io_outf);
  1745. X}
  1746. X
  1747. XNORMAL_CODE(type, emit, "type", dotype);
  1748. X
  1749. XVOID dospace()
  1750. X{
  1751. X    (VOID) fputc(' ', io_outf);
  1752. X}
  1753. X
  1754. XNORMAL_CODE(space, type, "space", dospace);
  1755. X
  1756. XVOID dospaces()
  1757. X{
  1758. X    INT32 n;
  1759. X
  1760. X    n = spop(INT32);
  1761. X    while (n-- > 0) (VOID) fputc(' ', io_outf);
  1762. X}
  1763. X
  1764. XNORMAL_CODE(spaces, space, "spaces", dospaces);
  1765. X
  1766. XVOID dokey()
  1767. X{
  1768. X    spush(io_getchar(), INT32);
  1769. X}
  1770. X
  1771. XNORMAL_CODE(key, spaces, "key", dokey);
  1772. X
  1773. XVOID doexpect()
  1774. X{
  1775. X    CHAR  c;
  1776. X    CSTR s0;
  1777. X    CSTR s1;
  1778. X    INT32  n;
  1779. X    
  1780. X    /* Pop buffer pointer and size */
  1781. X    n = spop(INT32);
  1782. X    s0 = s1 = spop(CSTR);
  1783. X    
  1784. X    /* Fill buffer until end of line or buffer */
  1785. X    while (io_not_eof() && (n-- > 0) && ((c = io_getchar()) != '\n')) *s1++ = c;
  1786. X
  1787. X    io_newline();
  1788. X
  1789. X    /* Set span to number of characters received */
  1790. X    span.parameter = (INT32) (s1 - s0);
  1791. X}
  1792. X
  1793. XNORMAL_CODE(expect, key, "expect", doexpect);
  1794. X
  1795. XNORMAL_VARIABLE(span, expect, "span", 0);
  1796. X
  1797. XVOID doline()
  1798. X{
  1799. X    spush(io_line(), INT32);
  1800. X}
  1801. X
  1802. XNORMAL_CODE(line, span, "line", doline);
  1803. X
  1804. XVOID dosource()
  1805. X{
  1806. X    spush(io_source(), CSTR);
  1807. X}
  1808. X
  1809. XNORMAL_CODE(source, line, "source", dosource);
  1810. X
  1811. X
  1812. X/* PROGRAM BEGINNING AND TERMINATION */
  1813. X
  1814. XVOID doforth83()
  1815. X{
  1816. X
  1817. X}
  1818. X
  1819. XNORMAL_CODE(forth83, source, "forth-83", doforth83);
  1820. X    
  1821. XVOID dointerpret()
  1822. X{
  1823. X    INT32 flag;            /* Flag value returned by for words */
  1824. X
  1825. X#ifdef CASTING
  1826. X    INT32 cast;            /* Casting operation flag */
  1827. X#endif
  1828. X    
  1829. X    quited = TRUE;        /* Iterate until bye or end of input */
  1830. X
  1831. X    while (quited) {
  1832. X
  1833. X    /* Check stack underflow */
  1834. X    if (s0 < sp) {
  1835. X        if (io_source())
  1836. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  1837. X        (VOID) fprintf(io_errf, "interpret: stack underflow\n");
  1838. X        doabort();
  1839. X    }
  1840. X
  1841. X    /* Scan for the next symbol */
  1842. X    spush(' ', INT32);
  1843. X    doword();
  1844. X
  1845. X    /* Exit top loop if end of input stream */
  1846. X    if (io_eof()) {
  1847. X        sdrop();
  1848. X        return;
  1849. X    }
  1850. X
  1851. X    /* Search for the symbol in the current vocabulary search set*/
  1852. X    dofind();
  1853. X    flag = spop(INT32);
  1854. X
  1855. X#ifdef CASTING
  1856. X    /* Check for vocabulary casting prefix */
  1857. X    for (cast = flag; !cast;) {
  1858. X        CSTR s = tos.CSTR;
  1859. X        INT32 l = strlen(s) - 1;
  1860. X
  1861. X        /* Assume casting prefix */
  1862. X        cast = TRUE;
  1863. X
  1864. X        /* Check casting syntax, vocabulary name within parethesis */ 
  1865. X        if ((s[0] == '(') && (s[l] == ')')) {
  1866. X
  1867. X        /* Remove the parenthesis from the input string */
  1868. X        s[l] = 0;
  1869. X        unary(++, INT32);
  1870. X
  1871. X        /* Search for the symbol again */
  1872. X        dofind();
  1873. X        flag = spop(INT32);
  1874. X        
  1875. X        /* If found check that its a vocabulary */
  1876. X        if (flag) {
  1877. X            ENTRY v = spop(ENTRY);
  1878. X
  1879. X            /* Check that the symbol is really a vocabulary */
  1880. X            if (v -> code == VOCABULARY) {
  1881. X
  1882. X            /* Scan for a new symbol */
  1883. X            spush(' ', INT32);
  1884. X            doword();
  1885. X
  1886. X            /* Exit top loop if end of input stream */
  1887. X            if (io_eof()) {
  1888. X                sdrop();
  1889. X                return;
  1890. X            }
  1891. X
  1892. X            /* And look for it in the given vocabulary */
  1893. X            spush(v, ENTRY);
  1894. X            dolookup();
  1895. X            flag = spop(INT32);
  1896. X            cast = flag;
  1897. X            }
  1898. X        }
  1899. X        else {
  1900. X            /* Restore string after vocabulary name test */
  1901. X            s[l] = ')';
  1902. X            unary(--, INT32);
  1903. X        }
  1904. X        }
  1905. X    }
  1906. X#endif
  1907. X    
  1908. X    /* If found then execute or thread the symbol */
  1909. X    if (flag) {
  1910. X        if (state.parameter == flag)
  1911. X        dothread();
  1912. X        else
  1913. X        docommand();
  1914. X    }
  1915. X    else {
  1916. X        /* Else check if it is a literal */
  1917. X        dorecognize();
  1918. X        flag = spop(INT32);
  1919. X        if (flag) {
  1920. X        doliteral();
  1921. X        }
  1922. X        else {
  1923. X        /* Print source file and line number */
  1924. X        if (io_source())
  1925. X            (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  1926. X
  1927. X        /* If not print error message and abort */
  1928. X        (VOID) fprintf(io_errf, "%s ??\n", tos.CSTR);
  1929. X        doabort();
  1930. X        }
  1931. X    }
  1932. X    }
  1933. X    quited = TRUE;
  1934. X}
  1935. X
  1936. XNORMAL_CODE(interpret, forth83, "interpret", dointerpret);
  1937. X
  1938. XVOID doquit()
  1939. X{
  1940. X    rinit();
  1941. X    doleftbracket();
  1942. X    dointerpret();
  1943. X}
  1944. X
  1945. XNORMAL_CODE(quit, interpret, "quit", doquit);
  1946. X
  1947. XVOID doabort()
  1948. X{
  1949. X    /* Check if it is the foreground task */
  1950. X    if (tp == foreground) {
  1951. X    sinit(); 
  1952. X    doleftbracket();
  1953. X    io_flush();
  1954. X    }
  1955. X
  1956. X    /* Terminate aborted tasks */
  1957. X    doterminate();
  1958. X}
  1959. X
  1960. XNORMAL_CODE(abort_entry, quit, "abort", doabort);
  1961. X
  1962. XVOID doabortquote()
  1963. X{
  1964. X    spush('"', INT32);
  1965. X    doword();
  1966. X    dosdup();
  1967. X    spush(&parenabortquote, CODE_ENTRY);
  1968. X    dothread();
  1969. X    docomma();
  1970. X}
  1971. X
  1972. XCOMPILATION_IMMEDIATE_CODE(abortquote, abort_entry, "abort\"", doabortquote);
  1973. X    
  1974. X
  1975. X/* DICTIONARY ADDRESSES */
  1976. X
  1977. XVOID dohere()
  1978. X{
  1979. X    spush(dp, PTR32);
  1980. X}
  1981. X
  1982. XNORMAL_CODE(here, abortquote, "here", dohere);
  1983. X
  1984. XNORMAL_CONSTANT(pad, here, "pad", (INT32) thepad);
  1985. X
  1986. XNORMAL_CONSTANT(tib, pad, "tib", (INT32) thetib);
  1987. X
  1988. XVOID dotobody()
  1989. X{
  1990. X    tos.INT32 = tos.ENTRY -> parameter;
  1991. X}
  1992. X
  1993. XNORMAL_CODE(tobody, tib, ">body", dotobody);
  1994. X
  1995. XVOID dodotname()
  1996. X{
  1997. X    ENTRY e = spop(ENTRY);
  1998. X    
  1999. X    (VOID) fprintf(io_outf, "%s", e -> name);
  2000. X}
  2001. X
  2002. XNORMAL_CODE(dotname, tobody, ".name", dodotname);
  2003. X
  2004. XNORMAL_CONSTANT(cell, dotname, "cell", 4);
  2005. X
  2006. XVOID docells()
  2007. X{
  2008. X    tos.INT32 <<= 2;
  2009. X}
  2010. X
  2011. XNORMAL_CODE(cells, cell, "cells", docells);
  2012. X
  2013. XVOID docellplus()
  2014. X{
  2015. X    tos.INT32 += 4;
  2016. X}
  2017. X
  2018. XNORMAL_CODE(cellplus, cells, "cell+", docellplus);
  2019. X
  2020. X
  2021. X/* COMPILER AND INTERPRETER WORDS */
  2022. X
  2023. XVOID dosharpif()
  2024. X{
  2025. X    INT32 symbol;
  2026. X    BOOL flag;
  2027. X
  2028. X    flag = spop(BOOL);
  2029. X
  2030. X    if (!flag) {
  2031. X    do {
  2032. X        spush(' ', INT32);
  2033. X        doword();
  2034. X        symbol = spop(INT32);
  2035. X        if (STREQ(symbol, "#if")) {
  2036. X        dosharpelse();
  2037. X        spush(' ', INT32);
  2038. X        doword();
  2039. X        symbol = spop(INT32);
  2040. X        }
  2041. X    } while (!((STREQ(symbol, "#else") || STREQ(symbol, "#then"))));
  2042. X    }
  2043. X}
  2044. X
  2045. XIMMEDIATE_CODE(sharpif, cellplus, "#if", dosharpif);
  2046. X
  2047. XVOID dosharpelse()
  2048. X{
  2049. X    INT32 symbol;
  2050. X    
  2051. X    do {
  2052. X    spush(' ', INT32);
  2053. X    doword();
  2054. X    symbol = spop(INT32);
  2055. X    if (STREQ(symbol, "#if")) {
  2056. X        dosharpelse();
  2057. X        spush(' ', INT32);
  2058. X        doword();
  2059. X        symbol = spop(INT32);
  2060. X    }
  2061. X    } while (!STREQ(symbol, "#then"));
  2062. X}
  2063. X
  2064. XIMMEDIATE_CODE(sharpelse, sharpif, "#else", dosharpelse);
  2065. X
  2066. XVOID dosharpthen()
  2067. X{
  2068. X
  2069. X}
  2070. X
  2071. XIMMEDIATE_CODE(sharpthen, sharpelse, "#then", dosharpthen);
  2072. X
  2073. XVOID dosharpifdef()
  2074. X{
  2075. X    spush(' ', INT32);
  2076. X    doword();
  2077. X    dofind();
  2078. X    doswap();
  2079. X    dodrop();
  2080. X    dosharpif();
  2081. X}
  2082. X
  2083. XIMMEDIATE_CODE(sharpifdef, sharpthen, "#ifdef", dosharpifdef);
  2084. X
  2085. XVOID dosharpifundef()
  2086. X{
  2087. X    spush(' ', INT32);
  2088. X    doword();
  2089. X    dofind();
  2090. X    doswap();
  2091. X    dodrop();
  2092. X    dozeroequals();
  2093. X    dosharpif();
  2094. X}
  2095. X
  2096. XIMMEDIATE_CODE(sharpifundef, sharpifdef, "#ifundef", dosharpifundef);
  2097. X
  2098. XVOID dosharpinclude()
  2099. X{
  2100. X    INT32 flag;
  2101. X    CSTR  fname;
  2102. X    
  2103. X    spush(' ', INT32);
  2104. X    doword();
  2105. X    fname = spop(CSTR);
  2106. X    if (flag = io_infile(fname) == IO_UNKNOWN_FILE) {
  2107. X    if (io_source())
  2108. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  2109. X    (VOID) fprintf(io_errf, "%s: file not found\n", fname);
  2110. X    }
  2111. X    else {
  2112. X    if (flag == IO_TOO_MANY_FILES) {
  2113. X        if (io_source())
  2114. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  2115. X        (VOID) fprintf(io_errf, "%s: too many files open\n", fname);
  2116. X    }
  2117. X    }
  2118. X}
  2119. X
  2120. XNORMAL_CODE(sharpinclude, sharpifundef, "#include", dosharpinclude);
  2121. X
  2122. XVOID dosharppath()
  2123. X{
  2124. X    INT32 flag;
  2125. X    
  2126. X    spush(' ', INT32);
  2127. X    doword();
  2128. X    if (flag = io_path(tos.CSTR, IO_PATH_FIRST) == IO_UNKNOWN_PATH) {
  2129. X    if (io_source())
  2130. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  2131. X    (VOID) fprintf(io_errf, "%s: unknown environment variable\n", tos.CSTR);
  2132. X    }
  2133. X    else {
  2134. X    if (flag == IO_TOO_MANY_PATHS) {
  2135. X        if (io_source())
  2136. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  2137. X        (VOID) fprintf(io_errf, "%s: too many paths defined\n", tos.CSTR);
  2138. X    }
  2139. X    }
  2140. X    dodrop();
  2141. X}
  2142. X
  2143. XNORMAL_CODE(sharppath, sharpinclude, "#path", dosharppath);
  2144. X
  2145. XVOID doparen()
  2146. X{
  2147. X    CHAR c;
  2148. X    
  2149. X    while (c = io_getchar())
  2150. X    if (io_eof()) {
  2151. X        if (io_source())
  2152. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  2153. X        (VOID) fprintf(io_errf, "kernel: end of file during comment\n");
  2154. X        return;
  2155. X    }
  2156. X    else
  2157. X        if (c == ')') return;
  2158. X        else
  2159. X        if (c == '(') doparen();
  2160. X}
  2161. X
  2162. XIMMEDIATE_CODE(paren, sharppath, "(", doparen);
  2163. X
  2164. XVOID dobackslash()
  2165. X{
  2166. X    io_skip('\n');
  2167. X}
  2168. X
  2169. XIMMEDIATE_CODE(backslash, paren, "\\", dobackslash);
  2170. X
  2171. XVOID docomma()
  2172. X{
  2173. X    *dp++ = spop(INT32);
  2174. X}
  2175. X
  2176. XNORMAL_CODE(comma, backslash, ",", docomma);
  2177. X
  2178. XVOID doallot()
  2179. X{
  2180. X    INT32 n;
  2181. X
  2182. X    n = spop(INT32);
  2183. X    dp = (PTR32) ((PTR8) dp + n);
  2184. X}
  2185. X
  2186. XNORMAL_CODE(allot, comma, "allot", doallot);
  2187. X
  2188. XVOID doalign()
  2189. X{
  2190. X    align(dp);
  2191. X}
  2192. X
  2193. XNORMAL_CODE(align_entry, allot, "align", doalign);
  2194. X
  2195. XVOID dodoes()
  2196. X{
  2197. X    if (theframed != NIL) {
  2198. X    spush(&parenunlinkdoes, CODE_ENTRY);
  2199. X    }
  2200. X    else {
  2201. X    spush(&parendoes, CODE_ENTRY);
  2202. X    }
  2203. X    dothread();
  2204. X    doremovelocals();
  2205. X}
  2206. X
  2207. XCOMPILATION_IMMEDIATE_CODE(does, align_entry, "does>", dodoes);
  2208. X
  2209. XVOID doimmediate()
  2210. X{
  2211. X    current -> last -> mode |= IMMEDIATE;
  2212. X}
  2213. X
  2214. XNORMAL_CODE(immediate, does, "immediate", doimmediate);
  2215. X
  2216. XVOID doexecution()
  2217. X{
  2218. X    current -> last -> mode |= EXECUTION;
  2219. X}
  2220. X
  2221. XNORMAL_CODE(execution, immediate, "execution", doexecution);
  2222. X
  2223. XVOID docompilation()
  2224. X{
  2225. X    current -> last -> mode |= COMPILATION;
  2226. X}
  2227. X
  2228. XNORMAL_CODE(compilation, execution, "compilation", docompilation);
  2229. X
  2230. XVOID doprivate()
  2231. X{
  2232. X    current -> last -> mode |= PRIVATE;
  2233. X}
  2234. X
  2235. XNORMAL_CODE(private_entry, compilation, "private", doprivate);
  2236. X
  2237. XVOID dorecognizer()
  2238. X{
  2239. X    current -> recognizer = current -> last;
  2240. X}
  2241. X
  2242. XNORMAL_CODE(recognizer, private_entry, "recognizer", dorecognizer);
  2243. X
  2244. XVOID dobracketcompile()
  2245. X{
  2246. X    dotick();
  2247. X    dothread();
  2248. X}
  2249. X
  2250. XCOMPILATION_IMMEDIATE_CODE(bracketcompile, recognizer, "[compile]", dobracketcompile);
  2251. X
  2252. XVOID docompile()
  2253. X{
  2254. X    spush(*ip++, INT32);
  2255. X    dothread();
  2256. X}
  2257. X
  2258. XCOMPILATION_CODE(compile, bracketcompile, "compile", docompile);
  2259. X
  2260. XVOID doqcompile()
  2261. X{
  2262. X    if (state.parameter) docompile();
  2263. X}
  2264. X
  2265. XCOMPILATION_CODE(qcompile, compile, "?compile", doqcompile);
  2266. X
  2267. XNORMAL_VARIABLE(state, qcompile, "state", FALSE);
  2268. X
  2269. XVOID docompiling()
  2270. X{
  2271. X    spush(state.parameter, INT32);
  2272. X}
  2273. X
  2274. XNORMAL_CODE(compiling, state, "compiling", docompiling);
  2275. X
  2276. XVOID doliteral()
  2277. X{
  2278. X    if (state.parameter) {
  2279. X    spush(&parenliteral, CODE_ENTRY);
  2280. X    dothread();
  2281. X    docomma();
  2282. X    }
  2283. X}
  2284. X
  2285. XCOMPILATION_IMMEDIATE_CODE(literal, compiling, "literal", doliteral);
  2286. X
  2287. XVOID doleftbracket()
  2288. X{
  2289. X    state.parameter = FALSE;
  2290. X}
  2291. X
  2292. XIMMEDIATE_CODE(leftbracket, literal, "[", doleftbracket);
  2293. X
  2294. XVOID dorightbracket()
  2295. X{
  2296. X    state.parameter = TRUE;
  2297. X}
  2298. X
  2299. XNORMAL_CODE(rightbracket, leftbracket, "]", dorightbracket);
  2300. X
  2301. XVOID doword()
  2302. X{
  2303. X    CHAR brkchr;
  2304. X
  2305. X    brkchr = (CHAR) spop(INT32);
  2306. X    (VOID) io_skipspace();
  2307. X    (VOID) io_scan(thetib, brkchr);
  2308. X    spush(thetib, CSTR);
  2309. X}
  2310. X
  2311. XNORMAL_CODE(word_entry, rightbracket, "word", doword);
  2312. X
  2313. X
  2314. X/* VOCABULARIES */
  2315. X
  2316. XNORMAL_CONSTANT(context_entry, word_entry, "context", (INT32) context);
  2317. X
  2318. XNORMAL_CONSTANT(current_entry, context_entry, "current", (INT32) ¤t);
  2319. X
  2320. XVOID dolast()
  2321. X{
  2322. X    spush((theframed ? theframed : current -> last), ENTRY);
  2323. X}
  2324. X
  2325. XNORMAL_CODE(last, current_entry, "last", dolast);
  2326. X
  2327. XVOID dodefinitions()
  2328. X{
  2329. X    current = context[0];}
  2330. X
  2331. X
  2332. XNORMAL_CODE(definitions, last, "definitions", dodefinitions);
  2333. X
  2334. XVOID doonly()
  2335. X{
  2336. X    INT32 v;
  2337. X
  2338. X    /* Flush the entry cache */
  2339. X    spush(FALSE, BOOL);
  2340. X    dorestore();
  2341. X
  2342. X    /* Remove all vocabularies except the first */
  2343. X    for (v = 1; v < CONTEXTSIZE; v++) context[v] = NIL;
  2344. X
  2345. X    /* And make it definition vocabulary */
  2346. X    current = context[0];
  2347. X}
  2348. X
  2349. XNORMAL_CODE(only, definitions, "only", doonly);
  2350. X
  2351. XVOID dorestore()
  2352. X{
  2353. X    register INT32 i;        /* Iteration variable */
  2354. X    register ENTRY e;        /* Pointer to parameter entry */
  2355. X    register ENTRY p;        /* Pointer to current entry */
  2356. X
  2357. X    /* Access parameter and check if an entry */
  2358. X    e = spop(ENTRY);
  2359. X    if (e) {
  2360. X
  2361. X    /* Flush all enties until the parameter symbol */
  2362. X    for (p = current -> last; p && (p != e); p = p -> link)
  2363. X        cache[hash(p -> name)] = NIL;
  2364. X
  2365. X    /* If the entry was found remove all symbols until this entry */
  2366. X    if (p == e) current -> last = e;
  2367. X    }
  2368. X    else {
  2369. X    
  2370. X    /* Flush the entry cache */
  2371. X    for (i = 0; i < CACHESIZE; i++) cache[i] = NIL;
  2372. X    }
  2373. X}
  2374. X
  2375. XNORMAL_CODE(restore, only, "restore", dorestore);
  2376. X
  2377. XVOID dotick()
  2378. X{
  2379. X    BOOL flag;
  2380. X
  2381. X    spush(' ', INT32);
  2382. X    doword();
  2383. X    dofind();
  2384. X    flag = spop(BOOL);
  2385. X    if (!flag) {
  2386. X    /* Print source file and line number */
  2387. X    if (io_source())
  2388. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  2389. X
  2390. X    /* If not print error message and abort */
  2391. X    (VOID) fprintf(io_errf, "%s ??\n", tos.CSTR);
  2392. X    doabort();
  2393. X    }
  2394. X}
  2395. X
  2396. XNORMAL_CODE(tick, restore, "'", dotick);
  2397. X
  2398. XVOID dobrackettick()
  2399. X{
  2400. X    dotick();
  2401. X    doliteral();
  2402. X}
  2403. X
  2404. XCOMPILATION_IMMEDIATE_CODE(brackettick, tick, "[']", dobrackettick);
  2405. X
  2406. XVOID dolookup() 
  2407. X{
  2408. X    VOCABULARY_ENTRY v;        /* Search vocabulary */
  2409. X    register ENTRY e;        /* Search entry */
  2410. X    register CSTR s;        /* And string */
  2411. X    
  2412. X    /* Fetch parameters and initate entry pointer */
  2413. X    v = (VOCABULARY_ENTRY) spop(PTR32);
  2414. X    s = tos.CSTR;
  2415. X    
  2416. X    /* Iterate over the linked list of entries */
  2417. X    for (e = v -> last; e; e = e -> link)
  2418. X
  2419. X    /* Compare the symbol and entry string */
  2420. X    if (STREQ(s, e -> name)) {
  2421. X
  2422. X        /* Check if the entry is currently visible */
  2423. X        if (visible(e, v)) {
  2424. X        /* Return the entry and compilation mode */
  2425. X        tos.ENTRY = e;
  2426. X        spush((e -> mode & IMMEDIATE ? 1 : -1), INT32);
  2427. X        return;
  2428. X        }
  2429. X    }
  2430. X    spush(FALSE, BOOL);
  2431. X}
  2432. X
  2433. XNORMAL_CODE(lookup, brackettick, "lookup", dolookup);
  2434. X
  2435. X#ifdef PROFILE
  2436. XVOID docollision()
  2437. X{
  2438. X    /* Add collision statistics to profile information */
  2439. X}
  2440. X#endif
  2441. X
  2442. XVOID dofind()
  2443. X{
  2444. X    ENTRY e;            /* Entry in the entry cache */
  2445. X    CSTR  n;            /* Name string of entry to be found */
  2446. X    INT32 v;            /* Index into vocabulary set */
  2447. X    
  2448. X    /* Access the string to be found */
  2449. X    n = tos.CSTR;
  2450. X
  2451. X    /* Check for cached entry */
  2452. X    if (e = cache[hash(n)]) {
  2453. X
  2454. X    /* Compare the string and the entry name */
  2455. X    if (STREQ(tos.CSTR, e -> name)) {
  2456. X
  2457. X        /* Check if the entry is currently visible */
  2458. X        if (!(((e -> mode & COMPILATION) && (!state.parameter)) ||
  2459. X          ((e -> mode & EXECUTION) && (state.parameter)))) {
  2460. X        tos.ENTRY = e;
  2461. X        spush((e -> mode & IMMEDIATE ? 1 : -1), INT32);
  2462. X        return;
  2463. X        }
  2464. X    }
  2465. X#ifdef PROFILE
  2466. X    else {
  2467. X        docollision();
  2468. X    }
  2469. X#endif    
  2470. X    }
  2471. X    
  2472. X    /* For each vocabulary in the current search chain */
  2473. X    for (v = 0; context[v] && v < CONTEXTSIZE; v++) {
  2474. X    spush(context[v], VOCABULARY_ENTRY);
  2475. X    dolookup();
  2476. X    if (tos.INT32) {
  2477. X        cache[hash(n)] = snth(0).ENTRY;
  2478. X        return;
  2479. X    }
  2480. X    else {
  2481. X        sdrop();
  2482. X    }
  2483. X    }
  2484. X    spush(FALSE, BOOL);
  2485. X}
  2486. X
  2487. XNORMAL_CODE(find, lookup, "find", dofind);
  2488. X
  2489. XVOID dorecognize()
  2490. X{
  2491. X    INT32 v;            /* Vocabulary index */
  2492. X    ENTRY r;            /* Recognizer function */
  2493. X
  2494. X    for (v = 0; context[v] && v < CONTEXTSIZE; v++) { 
  2495. X    
  2496. X    /* Check if a recognizer function is available */
  2497. X    if (r = context[v] -> recognizer) {
  2498. X        spush(r, ENTRY);
  2499. X        docommand();
  2500. X        if (tos.INT32) {
  2501. X        return;
  2502. X        }
  2503. X        else {
  2504. X        sdrop();
  2505. X        }
  2506. X    }
  2507. X    }
  2508. X
  2509. X    /* The string was not a literal symbol */
  2510. X    spush(FALSE, BOOL);
  2511. X}
  2512. X
  2513. XNORMAL_CODE(recognize, find, "recognize", dorecognize);
  2514. X
  2515. XVOID doforget()
  2516. X{
  2517. X    dotick();
  2518. X    tos.ENTRY = tos.ENTRY -> link; 
  2519. X    dorestore();
  2520. X}
  2521. X
  2522. XNORMAL_CODE(forget, recognize, "forget", doforget);
  2523. X
  2524. XVOID dowords()
  2525. X{
  2526. X    ENTRY e;            /* Pointer to entries */
  2527. X    INT32 v;            /* Index into vocabulary set */
  2528. X    INT32 l;            /* String length */
  2529. X    INT32 s;            /* Spaces between words */
  2530. X    INT32 c;            /* Column counter */
  2531. X    INT32 i;            /* Loop index */
  2532. X    
  2533. X    /* Iterate over all vocabularies in the search set */
  2534. X    for (v = 0; v < CONTEXTSIZE && context[v]; v++) {
  2535. X
  2536. X    /* Print vocabulary name */
  2537. X    (VOID) fprintf(io_outf, "VOCABULARY %s", context[v] -> name);
  2538. X    if (context[v] == current) (VOID) fprintf(io_outf, " DEFINITIONS");
  2539. X    (VOID) fputc('\n', io_outf);
  2540. X
  2541. X    /* Access linked list of enties and initiate column counter */
  2542. X    c = 0;
  2543. X
  2544. X    /* Iterate over all entries in the vocabulary */
  2545. X    for (e = context[v] -> last; e; e = e -> link) {
  2546. X
  2547. X        /* Check if the entry is current visible */
  2548. X        if (visible(e, context[v])) {
  2549. X        
  2550. X        /* Print the entry string. Check that space is available */
  2551. X        l = strlen(e -> name);
  2552. X        s = (c ? (COLUMNWIDTH - (c % COLUMNWIDTH)) : 0);
  2553. X        c = c + s + l;
  2554. X        if (c < LINEWIDTH) {
  2555. X            for (i = 0; i < s; i++) (VOID) fputc(' ', io_outf); 
  2556. X        }
  2557. X        else {
  2558. X            (VOID) fputc('\n', io_outf);
  2559. X            c = l;
  2560. X        }
  2561. X        (VOID) fprintf(io_outf, "%s", e -> name);
  2562. X        }
  2563. X    }
  2564. X
  2565. X    /* End the list of words and separate the vocabularies */
  2566. X    (VOID) fputc('\n', io_outf);
  2567. X    (VOID) fputc('\n', io_outf);
  2568. X    }
  2569. X}
  2570. X
  2571. XIMMEDIATE_CODE(words, forget, "words", dowords);
  2572. X
  2573. X
  2574. X/* DEFINING NEW VOCABULARY ENTRIES */
  2575. X
  2576. XENTRY make_entry(name, code, mode, parameter)
  2577. X    CSTR name;            /* String for the new entry */
  2578. X    INT32 code, mode, parameter; /* Entry parameters */
  2579. X{
  2580. X    /* Allocate space for the entry */
  2581. X    ENTRY e;
  2582. X
  2583. X    /* Check type of entry to allocate */
  2584. X    if (code == VOCABULARY)
  2585. X    e = (ENTRY) malloc(sizeof(vocabulary_entry));
  2586. X    else
  2587. X    e = (ENTRY) malloc(sizeof(entry));
  2588. X
  2589. X    /* Insert into the current vocabulary and set parameters */
  2590. X    e -> link = current -> last;
  2591. X    current -> last = e;
  2592. X
  2593. X    /* Set entry parameters */
  2594. X    e -> name = (CSTR) strcpy(malloc((unsigned) strlen(name) + 1), name);
  2595. X    e -> code = code;
  2596. X    e -> mode = mode;
  2597. X    e -> parameter = parameter;
  2598. X    if (code == VOCABULARY)
  2599. X    ((VOCABULARY_ENTRY) e) -> recognizer = NIL;
  2600. X    
  2601. X    /* Check for entry caching */
  2602. X    if (current == context[0])
  2603. X    cache[hash(name)] = e;
  2604. X    else
  2605. X    cache[hash(name)] = NIL;
  2606. X    
  2607. X    /* Return pointer to the new entry */
  2608. X    return e;
  2609. X}
  2610. X
  2611. XVOID doentry()
  2612. X{
  2613. X    INT32 flag;
  2614. X    CSTR  name;
  2615. X    INT32 code, mode, parameter;
  2616. X    ENTRY forward;
  2617. X    
  2618. X    /* Try to find entry to check for forward declarations */
  2619. X    forward = NIL;
  2620. X    dodup();
  2621. X    dofind();
  2622. X    flag = spop(INT32);
  2623. X    if (flag) {
  2624. X    forward = spop(ENTRY);
  2625. X    }
  2626. X    else {
  2627. X    sdrop();
  2628. X    }
  2629. X    
  2630. X    /* Access name, code, mode and parameter field parameters */
  2631. X    name = spop(CSTR);
  2632. X    code = spop(INT32);
  2633. X    mode = spop(INT32);
  2634. X    parameter = spop(INT32);
  2635. X
  2636. X    /* Create the new entry */
  2637. X    (VOID) make_entry(name, code, mode, parameter);
  2638. X
  2639. X    /* If found and forward the redirect parameter field of initial entry */
  2640. X    if (forward && forward -> code == FORWARD) {
  2641. X    forward -> parameter = (INT32) current -> last;
  2642. X    if (verbose) {
  2643. X        if (io_source())
  2644. X        (VOID) fprintf(io_errf, "%s:%i:", io_source(), io_line());
  2645. X        (VOID) fprintf(io_errf, "%s: forward definition resolved\n", forward -> name);
  2646. X    }
  2647. X    }
  2648. X}
  2649. X
  2650. XNORMAL_CODE(entry_entry, words, "entry", doentry);
  2651. X
  2652. XVOID doforward()
  2653. X{
  2654. X    spush(0, INT32);
  2655. X    spush(NORMAL, INT32);
  2656. X    spush(FORWARD, INT32);
  2657. X    spush(' ', INT32);
  2658. X    doword();
  2659. X    doentry();
  2660. X}
  2661. X
  2662. XNORMAL_CODE(forward, entry_entry, "forward", doforward);
  2663. X
  2664. XVOID docolon()
  2665. X{
  2666. X    align(dp);
  2667. X    dohere();
  2668. X    spush(HIDDEN, INT32);
  2669. X    spush(COLON, INT32);
  2670. X    spush(' ', INT32);
  2671. X    doword();
  2672. X    doentry();
  2673. X    dorightbracket();
  2674. X    thelast = current -> last;
  2675. X}
  2676. X
  2677. XNORMAL_CODE(colon, forward, ":", docolon);
  2678. X
  2679. XVOID dosemicolon()
  2680. X{
  2681. X    if (theframed != NIL) {
  2682. X    spush(&parenunlinksemicolon, CODE_ENTRY);
  2683. X    }
  2684. X    else {
  2685. X    spush(&parensemicolon, CODE_ENTRY);
  2686. X    }
  2687. X    dothread();
  2688. X    doleftbracket();
  2689. X    doremovelocals();
  2690. X    if (thelast != NIL) {
  2691. X    thelast -> mode = NORMAL;
  2692. X    if (current == context[0]) cache[hash(thelast -> name)] = thelast;
  2693. X    thelast = NIL;
  2694. X    }
  2695. X}
  2696. X
  2697. XCOMPILATION_IMMEDIATE_CODE(semicolon, colon, ";", dosemicolon);
  2698. X
  2699. XVOID docreate()
  2700. X{
  2701. X    align(dp);
  2702. X    dohere();
  2703. X    spush(NORMAL, INT32);
  2704. X    spush(CREATE, INT32);
  2705. X    spush(' ', INT32);
  2706. X    doword();
  2707. X    doentry();
  2708. X}
  2709. X
  2710. XNORMAL_CODE(create, semicolon, "create", docreate);
  2711. X
  2712. XVOID dovariable()
  2713. X{
  2714. X    spush(0, INT32);
  2715. X    spush(NORMAL, INT32);
  2716. X    spush(VARIABLE, INT32);
  2717. X    spush(' ', INT32);
  2718. X    doword();
  2719. X    doentry();
  2720. X}
  2721. X
  2722. XNORMAL_CODE(variable, create, "variable", dovariable);
  2723. X
  2724. XVOID doconstant()
  2725. X{
  2726. X    spush(NORMAL, INT32);
  2727. X    spush(CONSTANT, INT32);
  2728. X    spush(' ', INT32);
  2729. X    doword();
  2730. X    doentry();
  2731. X}
  2732. X
  2733. XNORMAL_CODE(constant, variable, "constant", doconstant);
  2734. X
  2735. XVOID dovocabulary()
  2736. X{
  2737. X    spush(&forth, VOCABULARY_ENTRY);
  2738. X    spush(NORMAL, INT32);
  2739. X    spush(VOCABULARY, INT32);
  2740. X    spush(' ', INT32);
  2741. X    doword();
  2742. X    doentry();
  2743. X}
  2744. X
  2745. XNORMAL_CODE(vocabulary, constant, "vocabulary", dovocabulary);
  2746. X
  2747. XVOID dofield()
  2748. X{
  2749. X    spush(NORMAL, INT32);
  2750. X    spush(FIELD, INT32);
  2751. X    spush(' ', INT32);
  2752. X    doword();
  2753. X    doentry();
  2754. X}
  2755. X
  2756. XNORMAL_CODE(field, vocabulary, "field", dofield);
  2757. X
  2758. X
  2759. X/* INITIALIZATION OF THE KERNEL */
  2760. X
  2761. XVOID kernel_initiate(last, first, users, parameters, returns)
  2762. X    ENTRY first, last;
  2763. X    INT32 users, parameters, returns;
  2764. X{
  2765. X    /* Link user symbols into vocabulary chain if given */
  2766. X    if (first && last) {
  2767. X    forth.last = last;
  2768. X    first -> link = (ENTRY) &field;
  2769. X    }
  2770. X    
  2771. X    /* Create the foreground task object */
  2772. X    foreground = make_task(users, parameters, returns, (INT32) NIL);
  2773. X    
  2774. X    /* Assign task fields */
  2775. X    foreground -> status = RUNNING;
  2776. X    s0 = (PTR) foreground -> s0;
  2777. X    sp = (PTR) foreground -> sp;
  2778. X    r0 = foreground -> r0;
  2779. X    rp = foreground -> rp;
  2780. X    ip = foreground -> ip;
  2781. X    fp = foreground -> fp;
  2782. X    ep = foreground -> ep;
  2783. X
  2784. X    /* Make the foreground task the current task */
  2785. X    tp = foreground;
  2786. X}
  2787. X
  2788. XVOID kernel_finish()
  2789. X{
  2790. X    /* Future clean up function for kernel */
  2791. X}
  2792. END_OF_src/kernel.c
  2793. if test 49941 -ne `wc -c <src/kernel.c`; then
  2794.     echo shar: \"src/kernel.c\" unpacked with wrong size!
  2795. fi
  2796. # end of overwriting check
  2797. fi
  2798. echo shar: End of archive 6 \(of 6\).
  2799. cp /dev/null ark6isdone
  2800. MISSING=""
  2801. for I in 1 2 3 4 5 6 ; do
  2802.     if test ! -f ark${I}isdone ; then
  2803.     MISSING="${MISSING} ${I}"
  2804.     fi
  2805. done
  2806. if test "${MISSING}" = "" ; then
  2807.     echo You have unpacked all 6 archives.
  2808.     rm -f ark[1-9]isdone
  2809. else
  2810.     echo You still need to unpack the following archives:
  2811.     echo "        " ${MISSING}
  2812. fi
  2813. ##  End of shell archive.
  2814. exit 0
  2815.