home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / m0 / part05 / interp.c next >
Encoding:
C/C++ Source or Header  |  1994-06-06  |  7.1 KB  |  315 lines

  1. /*
  2.     interp.c
  3. */
  4. /*  Copyright (c) 1994 Christian F. Tschudin. All rights reserved.
  5.  
  6.     Distributed under the terms of the GNU General Public License
  7.     version 2 of june 1991 as published by the Free Software
  8.     Foundation, Inc.
  9.  
  10.              This file is part of M0.
  11.  
  12. M0 is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY.  No author or distributor accepts responsibility to anyone for
  14. the consequences of using it or for whether it serves any particular
  15. purpose or works at all, unless he says so in writing.  Refer to the GNU
  16. General Public License for full details. 
  17.  
  18. Everyone is granted permission to copy, modify and redistribute M0, but
  19. only under the conditions described in the GNU General Public License. 
  20. A copy of this license is supposed to have been given to you along with
  21. M0 so you can know your rights and responsibilities.  It should be in a
  22. file named LICENSE.  Among other things, the copyright notice and this
  23. notice must be preserved on all copies.  */
  24.  
  25. #include "l_proto.h"
  26. #include "o_proto.h"
  27.  
  28.  
  29. static retcode interpret();
  30. static retcode schedule();
  31.  
  32.  
  33. retcode
  34. init_interpreter(char *bin, char *lib)
  35. {
  36.     byteptr startup;
  37.     uint mlen;
  38.     byteptr mstr;
  39.     eindex m;
  40.     retcode rc;
  41.  
  42.     startup = load_m0(bin, lib, "startup.m0");
  43.     if (!startup)
  44.         return ERR_IN_INIT;
  45.     mstr = make_msgr(startup,startup,strlen((char*)startup),0,0,&mlen);
  46.     m = str_import(0, mstr, mlen, mlen);
  47.     rc = new_proc(m, 0);
  48.     if (rc != OK)
  49.         return ERR_IN_INIT;
  50.     decref(0, m);
  51.     rc = run();
  52.     /* this initialisation process must terminate */
  53.     if (rc != OK || current != 0)
  54.         return ERR_IN_INIT;
  55.  
  56.     return OK;
  57. }
  58.  
  59.  
  60. int runable(void)
  61. {
  62.     return schedule() == OK;
  63. }
  64.  
  65.  
  66. retcode
  67. run(void)
  68. {
  69.     eindex err_name, err_handler;
  70.     eindex ei;
  71.     retcode rc;
  72.     char *fn;
  73.  
  74.     if (!current || current->state != S_RUNNING)
  75.         return IDLE;
  76.     for(;;) {
  77.         rc = interpret();
  78.         if (rc==YIELD_CPU || rc==OK) {
  79.             if (current->state == S_TERMINATED)
  80.                 remove_proc(current);
  81.             return rc;
  82.         }
  83.         /* else we have an error condition */
  84.         if (rc == ERR_NOT_IN_HALTED) {
  85. abort:
  86.             current->state = S_TERMINATED;
  87.             current->last_error = rc;
  88. #ifdef DEBUG
  89.             fn = unique_filename("abrt");
  90.             TRACE(0, printf("  ## abort: process %d dumped to file <%s>\n",
  91.                             current->pid, fn))
  92.             TRACE(0, dump_process_to_file(fn, current))
  93. #endif
  94.             remove_proc(current);
  95.             return ABORT;
  96.         }
  97.         if (current->esp >= MAXESTACK)
  98.             goto abort;
  99.         if (dict_load(current, errorhandler_name, &err_handler) != OK)
  100.             goto abort;
  101.         if (rc == ERR_OSTACK_OVERFLOW || current->osp >= (MAXOSTACK-2)) {
  102.             ei = make_array(current, current->os, current->osp);
  103.             current->osp = 1;
  104.             current->os[0] = ei;
  105.             rc = ERR_OSTACK_OVERFLOW;
  106.         }
  107.  
  108.         /*
  109.             at this place we should also deal with
  110.             an ESTACK_OVERFLOW error ...
  111.         */
  112.  
  113.         /* Push the error object and the name on the operand stack */
  114.         current->os[current->osp++] = current->err_element;
  115.         incref(current, current->err_element);
  116.         err_name = eaddr(current,err_name_array)->V.arr.a[rc];
  117.         current->os[current->osp++] = err_name;
  118.         incref(current, err_name);
  119.         /* Push the error handling routine on the exec stack */
  120.         ei = make_sub(current, err_handler, 0);
  121.         eattr(current,ei) |= A_EXECUTABLE;
  122.         current->es[current->esp++] = ei;
  123.     }
  124. }
  125.  
  126.  
  127. static retcode
  128. schedule()
  129. {
  130.     mproc p = current;
  131.     retcode rc;
  132.  
  133.     if (!current)
  134.         return IDLE;
  135.     while ((p = p->next) != current)
  136.         if (p->state == S_RUNNING)
  137.             break;
  138.     if (p->state == S_RUNNING) {
  139.         current = p;
  140.         TRACE(1, printf("  ## current process is now %d\n", current->pid))
  141.         rc = OK;
  142.     } else {
  143.         TRACE(1, printf("  ## currently no active process\n"))
  144.         rc = IDLE;
  145.     }
  146.  
  147.     return rc;
  148. }
  149.  
  150.  
  151. static retcode
  152. interpret()
  153. {
  154.     eindex ei, e;
  155.     eptr ep;
  156.     uint len;
  157.     retcode rc;
  158.  
  159. pop_estack:
  160.     TRACE(5, printf("interpreter loop, pop_estack %d\n", current->esp))
  161.  
  162.     if (current->esp == 0 ) {
  163.         current->state = S_TERMINATED;
  164.         return OK;
  165.     }
  166.     current->esp--;
  167.     ei = current->es[current->esp];
  168.  
  169.     for (;;) {
  170.  
  171.     TRACE(4, printf("top of interpreter loop: "))
  172.     TRACE(4, dump_element(stdout, current, ei))
  173.  
  174.         ep = eaddr(current,ei);
  175.         if (!(epattr(ep)&A_EXECUTABLE)) {
  176.         /* push the element on the o-stack */
  177.         if (current->osp >= MAXOSTACK)
  178.             return ERR_OSTACK_OVERFLOW;
  179.         current->os[current->osp] = ei;
  180.         current->osp++;
  181.         goto pop_estack;
  182.         }
  183.         switch (eptype(ep)) {
  184.         case T_EMPTY:    /* returned on end-of-string */
  185.             decrefp(current, ei, ep);
  186.             goto pop_estack;
  187.         case T_ARRAY:
  188.             TRACE(5, printf("exec array %d: %d\n",
  189.                             ei, (int) eplen(ep)))
  190.  
  191.             if (eplen(ep) == 0) {
  192.                 decrefp(current, ei, ep);
  193.                 goto pop_estack;
  194.             }
  195.             e = array_get(current, ei, 0);
  196.             incref(current, e);
  197.             if (etype(current,e) == T_ARRAY) {
  198.                 /* it must be a user defined procedure */
  199.                 if (current->osp >= MAXOSTACK)
  200.                     return ERR_OSTACK_OVERFLOW;
  201.                 current->os[current->osp++] = e;
  202.                 e = 0;
  203.             }
  204.             if (eplen(ep) == 1) {
  205.                 decrefp(current, ei, ep);
  206.                 if (!e)
  207.                     goto pop_estack;
  208.                 ei = e;
  209.                 continue;
  210.             }
  211.             if ((epattr(ep)&A_SUB) && eprefcnt(ep) == 1) {
  212.                 eplen(ep) -= 1;
  213.                 ep->V.sub.offset += 1;
  214.             } else {
  215.                 eindex i = make_sub(current, ei, 1);
  216.                 if (!i) {
  217.                     current->err_element = ei;
  218.                     return ERR_OUT_OF_LOCALS;
  219.                 }
  220.                 eattr(current,i) |= epattr(ep) & A_EXECUTABLE;
  221.                 decrefp(current, ei, ep);
  222.                 ei = i;
  223.             }
  224.             if (e) {
  225.                 current->es[current->esp++] = ei;
  226.                 ei = e;
  227.             }
  228.             continue;
  229.         case T_STRING:
  230.             if (eplen(ep) == 0) {
  231.                 decrefp(current, ei, ep);
  232.                 goto pop_estack;
  233.             }
  234.             rc = str_gettoken(current, ei, &len, &e);
  235.             if (rc != OK ) {
  236.                 current->err_element = ei;
  237.                 return rc;
  238.             }
  239.             if (etype(current,e) == T_EMPTY) {
  240.                 decref(current, e);
  241.                 e = 0;
  242.             } else if (etype(current,e) == T_ARRAY) {
  243.                 /* it must be a user defined procedure */
  244.                 if (current->osp >= MAXOSTACK)
  245.                     return ERR_OSTACK_OVERFLOW;
  246.                 current->os[current->osp++] = e;
  247.                 e = 0;
  248.             }
  249.  
  250.             if (len == eplen(ep)) {
  251.                 decrefp(current, ei, ep);
  252.                 if (!e)
  253.                     goto pop_estack;
  254.                 ei = e;
  255.                 continue;
  256.             }
  257.             if ((epattr(ep)&A_SUB) && eprefcnt(ep) == 1) {
  258.                 ep->V.sub.offset += len;
  259.                 eplen(ep) -= len;
  260.             } else {
  261.                 eindex i = make_sub(current, ei, len);
  262.                 if (!i) {
  263.                     current->err_element = ei;
  264.                     return ERR_OUT_OF_LOCALS;
  265.                 }
  266.                 decrefp(current, ei, ep);
  267.                 ei = i;
  268.                 eattr(current,ei) |= A_EXECUTABLE;
  269.             }
  270.  
  271.             if (e) {
  272.                 current->es[current->esp++] = ei;
  273.                 ei = e;
  274.             }
  275.             continue;
  276.         case T_NAME:
  277.             TRACE(5, printf("interpreter: name resultion %d\n", ei))
  278.  
  279.             if (dict_load(current, ei, &e) == OK) {
  280.                 decrefp(current, ei, ep);
  281.                 ep = eaddr(current,e);
  282.                 if (eptype(ep)==T_ARRAY && (epattr(ep)&A_EXECUTABLE)) {
  283.                     ei = make_sub(current, e, 0);
  284.                     eattr(current,ei) |= A_EXECUTABLE;
  285.                 } else {
  286.                     ei = e;
  287.                     incref(current,ei);
  288.                 }
  289.                 continue;
  290.             }
  291.             current->err_element = ei;
  292.             return ERR_UNDEFINED;
  293.         case T_PROC:
  294.             rc = (ep->V.pro.fct)();
  295.             TRACE(5,
  296. printf("interpreter proc: %d, rc=%d, e-top=%d\n", ei, rc, current->es[current->esp-1]))
  297.  
  298.             if (rc == OK) {
  299.                 decrefp(current, ei, ep);
  300.                 goto pop_estack;
  301.             }
  302.             if (rc == YIELD_CPU) {
  303.                 decrefp(current, ei, ep);
  304.             } else
  305.                 current->err_element = ei;
  306.             return rc;
  307.         default:
  308.             current->err_element = ei;
  309.             return ERR_NOT_IMPLEMENTED;
  310.         }
  311.     }
  312. }
  313.  
  314.  
  315.