home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / programm / language / bcpl4ami.lzh / bcpl / src / icint.c next >
Encoding:
C/C++ Source or Header  |  1991-02-03  |  8.4 KB  |  539 lines

  1. /*
  2. //     This program is an ASCII INTCODE assembler and interpreter
  3. // for a 16 bit machine.
  4. */
  5.  
  6. #define    EXT
  7. #include    "icint.h"
  8.  
  9. static int    uglob = 0;
  10. static int    verbose = 0;
  11. static struct hdr
  12. {
  13.     unsigned short    psize, gsize, plen, glen;
  14. } proghdr =
  15. {
  16.     0, 0, 0, 0
  17. };
  18. static FP    symin;
  19. static int    hiwater = 0;
  20.  
  21. int vec(n)
  22.     int    n;
  23. {
  24.     register int    t;
  25.  
  26.     if (hiwater + n + 1 > MAXMEM)
  27.     {
  28.         fprintf(stderr, "Cannot allocate %d words\n", n);
  29.         exit(2);
  30.     }
  31.     t = hiwater;
  32.     hiwater += n + 1;
  33.     return (t);
  34. }
  35.  
  36. unvec(n)
  37.     int        n;
  38. {
  39.     hiwater = n;
  40. }
  41.  
  42. rch()
  43. {
  44.     for (;;)
  45.     {
  46.         ch = getc(symin);
  47.         if (ch != '/')
  48.             return;
  49.         while (ch != '\n')
  50.             ch = getc(symin);
  51.         linecount++;
  52.     }
  53. }
  54.  
  55. assemble()
  56. {
  57.     register int    v, f;
  58.     register int    a, w, i, aa;
  59.  
  60.     linecount = 0;
  61.     /* put startup code in first three words */
  62.     mem[pp++] =  LIG1;
  63.     mem[pp++] = K2;
  64.     /* make all globals initially point to exit instruction */
  65.     for (i = 0; i <= GLOBMAX; ++i)
  66.         mem[gp++] = pp;
  67.     gp = globvec;
  68.     mem[pp++] = X22;
  69.     v = labvec = vec(LABMAX);
  70.     f = 0;
  71. clear:
  72.     for (i = 0; i <= LABMAX; ++i)
  73.         mem[v++] = 0;
  74.     v = labvec;
  75.     cp = 0;
  76.  
  77. next:
  78.     rch();
  79. sw:
  80.     switch (ch)
  81.     {
  82.     default:
  83.         fprintf(stderr, "Bad char '%c' (%02x) at p = %d (line %d)\n",
  84.             ch, ch, pp - progvec, linecount);
  85.         goto next;
  86.  
  87.     case EOF:
  88.         if (!uglob)
  89.         {
  90.             unvec(labvec);    /* return storage */
  91.             return;
  92.         }
  93.         fprintf(stderr, "Possibly uninitialized globals: ");
  94.         for (i = 0; i <= GLOBMAX; ++i)
  95.             if (mem[globvec+i] == 0)
  96.             {
  97.                 mem[globvec+i] = progvec + 2;
  98.                 fprintf(stderr, "%d ", i);
  99.             }
  100.         fprintf(stderr, "\n");
  101.         unvec(labvec);        /* return storage */
  102.         return;
  103.  
  104.     case '0':case '1':case '2':case '3':case '4':
  105.     case '5':case '6':case '7':case '8':case '9':
  106.         setlab(rdn());
  107.         cp = 0;
  108.         goto sw;
  109.  
  110.     case '\n':
  111.         linecount++;
  112.     case '$':
  113.     case ' ':
  114.     case '\r':
  115.         goto next;
  116.  
  117.     case 'L': f = OP_L; break;
  118.     case 'S': f = OP_S; break;
  119.     case 'A': f = OP_A; break;
  120.     case 'J': f = OP_J; break;
  121.     case 'T': f = OP_T; break;
  122.     case 'F': f = OP_F; break;
  123.     case 'K': f = OP_K; break;
  124.     case 'X': f = OP_X; break;
  125.  
  126.     case 'C':
  127.         rch(); stc(rdn()); goto sw;
  128.  
  129.     case 'D':
  130.         rch();
  131.         if (ch == 'L')
  132.         {
  133.             rch();
  134.             stw(0);
  135.             labref(rdn(), pp - 1);
  136.         }
  137.         else
  138.             stw(rdn());
  139.         goto sw;
  140.  
  141.     case 'G':
  142.         rch();
  143.         aa = rdn();
  144.         if (aa > proghdr.glen)
  145.             proghdr.glen = aa;
  146.         a = aa + gp;
  147.         if (ch == 'L')
  148.             rch();
  149.         else
  150.             fprintf(stderr, "Bad code at p = %d (line %d)\n",
  151.                 pp - progvec, linecount);
  152.         mem[a] = 0;
  153.                 labref(rdn(), a);
  154.                 goto sw;
  155.  
  156.     case 'Z':
  157.         for (i = 0; i <= LABMAX; ++i)
  158.             if (mem[labvec+i] > 0)
  159.                 fprintf(stderr, "L%d unset\n", i);
  160.                 goto clear;
  161.     }
  162.  
  163.     w = f << FSHIFT;
  164.     rch();
  165.     if (ch == 'I')
  166.     {
  167.         w |= IBIT;
  168.         rch();
  169.     }
  170.     if (ch == 'P')
  171.     {
  172.         w |= PBIT;
  173.         rch();
  174.     }
  175.     if (ch == 'G')
  176.     {
  177.         w |= GBIT;
  178.         rch();
  179.     }
  180.  
  181.     if (ch == 'L')
  182.     {
  183.         rch();
  184.         stw(w | DBIT);        /* two words so we can backpatch */
  185.         stw(0);
  186.         labref(rdn(), pp - 1);
  187.     }
  188.         else
  189.     {
  190.         aa = rdn();
  191.                 if ((aa & ABITS) == aa)
  192.             stw(w | aa);
  193.         else
  194.         {
  195.             stw(w | DBIT);
  196.             stw(aa);
  197.         }
  198.         if (w & GBIT && mem[globvec+aa] == progvec + 2)
  199.             mem[globvec+aa] = 0;
  200.     }
  201.  
  202.     goto sw;
  203. }
  204.  
  205. stw(w)
  206.     int        w;
  207. {
  208.     mem[pp] = w;
  209.     ++pp;
  210.     cp = 0;
  211. }
  212.  
  213. stc(c)
  214.     int        c;
  215. {
  216.     if (cp == 0)
  217.     {
  218.         stw(0);
  219.         cp = CHARWORDBITS;
  220.     }
  221.     cp -= BYTESIZE;
  222.     mem[pp - 1] |= (c << cp);
  223. }
  224.  
  225. int rdn()
  226. {
  227.     register int    a, b;
  228.  
  229.     a = b = 0;
  230.     if (ch == '-')
  231.     {
  232.         b = 1;
  233.         rch();
  234.     }
  235.     while ('0' <= ch && ch <= '9')
  236.     {
  237.         a = 10 * a + ch - '0';
  238.         rch();
  239.     }
  240.     if (b)
  241.         a = -a;
  242.     return (a);
  243. }
  244.  
  245. setlab(n)
  246.     int        n;
  247. {
  248.     register int    k, nn;
  249.  
  250.     k = mem[labvec+n];
  251.         if (k < 0)
  252.         fprintf(stderr, "L%d already set to %d at p = %d (line %d)\n",
  253.             n, -k - progvec, pp - progvec, linecount);
  254.         while (k > 0)
  255.     {
  256.         nn = mem[k];
  257.         mem[k] = pp;
  258.         k = nn;
  259.     }
  260.         mem[labvec+n] = -pp;
  261. }
  262.  
  263. labref(n, a)
  264.     int        n, a;
  265. {
  266.     register int    k;
  267.  
  268.     k = mem[labvec+n];
  269.     if (k < 0)
  270.         k = -k;
  271.     else
  272.         mem[labvec+n] = a;
  273.     mem[a] += k;
  274. }
  275.  
  276. /*
  277. **    The intcode has the assumption that 2 characters fit in a word
  278. **    hardwired in because of packstring and unpackstring.
  279. **    Hence the next three routines.
  280. */
  281.  
  282. int icgetbyte(s, i)
  283.     int        s, i;
  284. {
  285.     register word    *w;
  286.  
  287.     w = &mem[s] + i / 2;
  288.         return (i & 1 ?  *w & 0xff : (*w >> 8) & 0xff);
  289. }
  290.  
  291. icputbyte(s, i, ch)
  292.     int        s, i, ch;
  293. {
  294.     register word    *w;
  295.  
  296.     w = &mem[s] + i / 2;
  297.     if (i & 1)
  298.         *w = (*w & ~0xff) | (ch & 0xff);
  299.     else
  300.         *w = (*w & ~0xff00) | ((ch & 0xff) << 8);
  301. }
  302.  
  303. /* convert a C string to a BCPL string; storage comes from BCPL memory */
  304. int bcstr(s)
  305.     char        *s;
  306. {
  307.     register int    i, len, t;
  308.  
  309.     len = strlen(s);
  310.     t = vec((len + 2) / 2);
  311.     icputbyte(t, 0, len);
  312.     for (i = 1; i <= len; ++i)
  313.         icputbyte(t, i, *s++);
  314.     return (t);
  315. }
  316.  
  317. /* convert a BCPL string to a C string; caller supplies array */
  318. strbc(i, s)
  319.     int        i;
  320.     char        s[];
  321. {
  322.     register int    n, len;
  323.     register char    *p;
  324.  
  325.     len = icgetbyte(i, 0);
  326.     if (len > MAXFN - 1)
  327.         len = MAXFN - 1;
  328.     p = s;
  329.     for (n = 1; n <= len; ++n)
  330.         *p++ = icgetbyte(i, n);
  331.     *p = '\0';
  332. }
  333.  
  334. makemem()
  335. {
  336.     char        *malloc();
  337.  
  338.     MAXMEM = proghdr.psize + proghdr.gsize + LABMAX + 100;
  339.     if ((mem = (word *)malloc(MAXMEM * sizeof(word))) == NULL)
  340.     {
  341.         fprintf(stderr, "Cannot allocate %d words of memory for interpreter\n", MAXMEM);
  342.         exit(1);
  343.     }
  344. }
  345.  
  346. rchk(a, b, s)
  347.     int        a, b;
  348.     char        *s;
  349. {
  350.     if (a != b)
  351.         fprintf(stderr, "Read error on %s\n", s);
  352. }
  353.  
  354. loadbin(name)
  355.     char        *name;
  356. {
  357.     register FP    f;
  358.  
  359. #ifdef    c80
  360.     if ((f = fopen(name, "rb")) == NULL)
  361. #else
  362.     if ((f = fopen(name, "r")) == NULL)
  363. #endif
  364.     {
  365.         fprintf(stderr, "Cannot open %s for reading\n", name);
  366.         exit(1);
  367.     }
  368.     rchk(fread((char *)&proghdr, sizeof(struct hdr), 1, f), 1, "proghdr");
  369.     makemem();
  370.     progvec = vec((int)proghdr.psize);
  371.     pp = progvec + proghdr.plen;
  372.     gp = globvec = vec((int)proghdr.gsize);
  373.     rchk(fread((char *)&mem[progvec], sizeof(word), (int)proghdr.plen, f),
  374.         (int)proghdr.plen, "prog");
  375.     rchk(fread((char *)&mem[globvec], sizeof(word), (int)proghdr.glen, f),
  376.         (int)proghdr.glen, "glob");
  377.     fclose(f);
  378. }
  379.  
  380. loadsym(name)
  381.     char        *name;
  382. {
  383.     makemem();
  384.     pp = progvec = vec((int)proghdr.psize);
  385.     gp = globvec = vec((int)proghdr.gsize);
  386.     if ((symin = fopen(name, "r")) == NULL)
  387.     {
  388.         fprintf(stderr, "Cannot open %s for reading\n", name);
  389.         exit(1);
  390.     }
  391.     assemble();
  392.     proghdr.plen = pp - progvec;
  393.     fclose(symin);
  394. }
  395.  
  396. wchk(a, b, s)
  397.     int        a, b;
  398.     char        *s;
  399. {
  400.     if (a != b)
  401.         fprintf(stderr, "Write error on %s\n", s);
  402. }
  403.  
  404. storebin(name)
  405.     char        *name;
  406. {
  407.     register FP    f;
  408.  
  409. #ifdef    c80
  410.     if ((f = fopen(name, "wb")) == NULL)
  411. #else
  412.     if ((f = fopen(name, "w")) == NULL)
  413. #endif
  414.     {
  415.         fprintf(stderr, "Cannot open %s for writing\n", name);
  416.         exit(1);
  417.     }
  418.     ++proghdr.glen;
  419.     wchk(fwrite((char *)&proghdr, sizeof(struct hdr), 1, f), 1, "proghdr");
  420.     wchk(fwrite((char *)&mem[progvec], sizeof(word), (int)proghdr.plen, f),
  421.         (int)proghdr.plen, "prog");
  422.     wchk(fwrite((char *)&mem[globvec], sizeof(word), (int)proghdr.glen, f),
  423.         (int)proghdr.glen, "glob");
  424.     fclose(f);
  425. }
  426.  
  427. main(argc, argv)
  428.     int        argc;
  429.     char        *argv[];
  430. {
  431.     register int    i;
  432.     register char    *opstring;
  433.     int        loadflag, storeflag;
  434.     int        atoi();
  435.  
  436.     initio();
  437.     proghdr.psize = PROGMAX;
  438.     proghdr.gsize = GLOBMAX;
  439.     storeflag = loadflag = 0;
  440.     for (--argc, ++argv; argc > 0 && *argv[0] == '-'; --argc, ++argv)
  441.     {
  442.         opstring = *argv;
  443.         switch (opstring[1])
  444.         {
  445.         case 'g':
  446.         case 'G':
  447.             proghdr.gsize = atoi(&opstring[2]);
  448.             break;
  449.         case 'p':
  450.         case 'P':
  451.             proghdr.psize = atoi(&opstring[2]);
  452.             break;
  453.         case 'l':
  454.         case 'L':
  455.             loadflag = 1;
  456.             break;
  457.         case 's':
  458.         case 'S':
  459.             storeflag = 1;
  460.             break;
  461.         case 'u':
  462.         case 'U':
  463.             uglob = 1;
  464.             break;
  465.         case 'v':
  466.         case 'V':
  467.             verbose = 1;
  468.             break;
  469.         }
  470.     }
  471.  
  472.     if (storeflag)
  473.     {
  474.         if (argc <= 1)
  475.         {
  476.             fprintf(stderr, "Usage: icint -s source binary\n");
  477.             exit(1);
  478.         }
  479.     }
  480.     else
  481.     {
  482.         if (argc <= 0)
  483.         {
  484.             fprintf(stderr, "Usage: icint [options] source [input]\n");
  485.             exit(1);
  486.         }
  487.         if (argc > 1 && !setsysin(argv[1]))
  488.         {
  489.             fprintf(stderr, "Cannot open %s for reading\n", argv[1]);
  490.             exit(1);
  491.         }
  492.     }
  493.  
  494.     if (loadflag)
  495.         loadbin(argv[0]);
  496.     else
  497.         loadsym(argv[0]);
  498.  
  499.     if (verbose)
  500.         fprintf(stderr, "Program size = %d\n", proghdr.plen);
  501.  
  502.     if (storeflag)
  503.     {
  504.         storebin(argv[1]);
  505.         exit(0);
  506.     }
  507.  
  508.     slctinput(S_IN);
  509.     slctoutput(S_OUT);
  510.  
  511.     if (verbose)
  512.         fprintf(stderr, "Intcode system entered\n");
  513.  
  514. #ifdef    profiling
  515.     for (i = 0; i < 8; ++i)
  516.         majinstr[i] = 0;
  517.     for (i = 0; i < 38; ++i)
  518.         mininstr[i] = 0;
  519. #endif
  520.  
  521.     i = interpret();
  522.  
  523. #ifdef    profiling
  524.     for (i = 0; i < 8; ++i)
  525.         fprintf(stderr, "Major %d: %d\n", i, majinstr[i]);
  526.     for (i = 0; i < 38; ++i)
  527.         fprintf(stderr, "Minor %d: %d\n", i, mininstr[i]);
  528. #endif    profiling
  529.  
  530.     if (verbose)
  531.         fprintf(stderr, "Execution cycles = %d, code = %d\n", cyclecount, i);
  532.  
  533.     if (i < 0)
  534.         mapstore();
  535.     finio();
  536.     exit(i);
  537.     return (0);
  538. }
  539.