home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / tile.lzh / tile.6 < prev   
Text File  |  1990-07-26  |  54KB  |  2,811 lines

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