home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / editors / mutt / me2s_pl7.zoo / mu_edit2 / mc2 / vcomp.c < prev   
Encoding:
C/C++ Source or Header  |  1992-08-26  |  9.9 KB  |  384 lines

  1. /* 
  2.  * vcomp.c : compile vars and the like
  3.  */
  4.  
  5. /* Copyright 1990, 1991, 1992 Craig Durland
  6.  *   Distributed under the terms of the GNU General Public License.
  7.  *   Distributed "as is", without warranties of any kind, but comments,
  8.  *     suggestions and bug reports are welcome.
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <os.h>
  13. #include "mc.h"
  14. #include "opcode.h"
  15. #include "mm.h"
  16.  
  17. extern char ebuf[], token[], temp[], *spoof(), *typename();
  18. extern int btv, xtn, msize, omsize;
  19. extern unsigned int class, vtype(), vctype(), mmtype();
  20. extern int32 atoN();
  21. extern MuttCmd muttcmds[];
  22. extern VBlob *get_blob(), *proto_name();
  23. extern MMDatum *getconst();
  24.  
  25.     /* process a function pointer: foo (foo) (foo args) */
  26. static void fcnptr(eval)
  27. {
  28.   if (eval)    /* (foo) or (foo args) */
  29.     { genop(PUSHRV); vargs(); genop(DOOP); class = UNKNOWN; }
  30.   else class = FCNPTR;
  31. }
  32.  
  33.     /* process a var pointer: (ptr) (ptr val) */
  34. void evalvp(arg,offset,scope,type)
  35. {
  36.   int t = (type & ~POINTER), mt = mmtype(type);
  37.  
  38.   gonumx((int32)0); genop(SHOVERV);
  39.   if (arg) { gonumx((int32)offset); genop(ARG); }
  40.   else
  41.   {
  42.     genop(SHOVERV);
  43.     gonum16((scope == LOCAL ? RVLBASE : RVGBASE),offset);
  44.     gonum8(GETRVAR,BLOB);
  45.   }
  46.   lookahead(); 
  47.   if (class == DELIMITER && *token == ')') gonum8(GETRVAR,t);    /* (ptr) */
  48.   else    /* (ptr val) */
  49.   {
  50.     genop(SHOVERV); compile(); type_check(mt,0);
  51.     gonum8(SETRVAR,t);
  52.   }
  53.   class = mt;
  54. }
  55.  
  56.     /* gen code for getting a local or global var */
  57. void genvar(name,eval) char *name;
  58. {
  59.   int t, scope, offset;
  60.   unsigned int type;
  61.   VBlob *blob;
  62.   MMDatum *rv;
  63.  
  64.   if ((blob = proto_name(name)))        /* its a proto */
  65.   {
  66.     type = blob->type;
  67.     if (eval && (type & POINTER)) evalvp(TRUE,blob->offset,0,type);
  68.     else
  69.     {
  70.       gonumx((int32)blob->offset); genop(ARG);
  71.       if (type == FCNPTR) fcnptr(eval);
  72.       else
  73.     if (blob->dims) class = BLOB; else class = type;
  74.     }
  75.     return;
  76.   }
  77.  
  78.   if ((t = getvar(name)) != -1)        /* its a var */
  79.   {
  80.     type = vtype(t); offset = voffset(t); scope = vscope(t);
  81.     if (eval && (type & POINTER)) evalvp(FALSE,offset,scope,type);
  82.     else
  83.     {
  84.       if (type == ARRAY || type == BLOB)
  85.     gonum16((scope == LOCAL ? RVLBASE : RVGBASE),offset);
  86.       else
  87.     go2num((scope == LOCAL ? GETLVAR : GETGVAR),
  88.         (type & POINTER) ? BLOB : type, offset);
  89.       if (type == FCNPTR) fcnptr(eval);
  90.       else class = type;
  91.     }
  92.     return;
  93.   }
  94.  
  95.   if (!eval && (rv = getconst(name)))    /* (const) is illegal */
  96.   {
  97.     switch (class = rv->type)
  98.     {
  99.       case STRING:  gostr(RVSTR,rv->val.str);    break;
  100.       case NUMBER:  gonumx(rv->val.num);    break;
  101.       case BOOLEAN: gonum8(RVBOOL,rv->val.num); break;
  102.     }
  103.     return;
  104.   }
  105.  
  106.   bitch(spoof(ebuf,"%s is not a var.",name));
  107. }
  108.  
  109. varcompile(eval)    /* handle (var [value]) */
  110. {
  111.   int j,t,m,n,x,z, arg = FALSE, compiled = FALSE, tsize, scope, offset, *dim;
  112.   unsigned int type;
  113.   VBlob *blob;
  114.   MMDatum *rv;
  115.  
  116.   z = UNKNOWN;
  117.   if (blob = proto_name(token))        /* a prototype */
  118.   {
  119.     arg = TRUE; offset = blob->offset;
  120.     type = blob->type; if (blob->dims) z = ARRAY;
  121.   }
  122.   else
  123.     if ((t = getvar(token)) != -1)    /* a local or global var */
  124.     {
  125.       scope = vscope(t); offset = voffset(t); type = z = vtype(t);
  126.       if (type == ARRAY) { blob = get_blob(t); }
  127.     }
  128.     else        /* maybe a const */
  129.       if (!eval && getconst(token)) { genvar(token,eval); return TRUE; }
  130.       else return FALSE;
  131.  
  132.   if (type == FCNPTR) { genvar(token,eval); return TRUE; }
  133.   if (z == ARRAY)
  134.   {
  135.     z = 0; type = blob->type; tsize = typesize(type);
  136.     dim = blob->dim; n = blob->dims; m = n -1; if (type == STRING) n--;
  137.     for (j = 0; j < n; j++)    /* suck up subscripts */
  138.     {
  139.       lookahead();
  140.     /* check to see if next thing is a constant */
  141.       if (class == TOKEN && (rv = getconst(token)) && rv->type == NUMBER &&
  142.       proto_name(token) == NULL && getvar(token) == -1)
  143.     { x = rv->val.num; goto num; }
  144.  
  145.       if (class == DELIMITER || class == TOKEN)
  146.       {
  147.     if (class == DELIMITER && *token == ')')
  148.       if (j == 0)            /* (var) */
  149.       {
  150.         class = BLOB;
  151.         if (arg) { gonumx((int32)offset); genop(ARG); }
  152.         else gonum16((scope == LOCAL ? RVLBASE : RVGBASE),offset);
  153.         return TRUE;
  154.       }
  155.       else { moan(spoof(ebuf,"Need %d subscript(s).",n)); break; }
  156.     if (compiled) genop(SHOVERV);
  157.     compile(); type_check(NUMBER,0);
  158.     if (j < m) { genop(SHOVERV); gonumx((int32)dim[j+1]); genop(MUL); }
  159.     if (compiled) genop(ADD);
  160.     compiled = TRUE;
  161.       }
  162.       else
  163.         if (class == NUMBER)
  164.     {
  165.       x = atoi(token);
  166.     num:
  167.       get_token();
  168.       if (x < 0 || x >= dim[j])
  169.         { x = 0; moan(spoof(ebuf,"Subscript out of bounds.")); }
  170.       if (j < m) x *= dim[j+1];
  171.       z += x;
  172.     }
  173.     else bitch(spoof(ebuf,"%s is not an array subscript.",token));
  174.     }
  175.     z = z*tsize + (arg ? 0 : offset);    /* offset from base address */
  176.  
  177.     /* now check to see if it is assignment or eval */
  178.     lookahead(); 
  179.         /* TRUE => eval */
  180.     x = (class == DELIMITER && *token == ')') ? TRUE : FALSE;
  181.  
  182.     if (arg)
  183.     {
  184.       if (!compiled) gonumx((int32)z);
  185.       else
  186.       {
  187.         genop(SHOVERV); gonumx((int32)tsize); genop(MUL);
  188.     if (z) { genop(SHOVERV); gonumx((int32)z); genop(ADD); }
  189.       }
  190.       genop(SHOVERV);
  191.       gonumx((int32)offset); genop(ARG);
  192.       if (x) gonum8(GETRVAR,type);
  193.       else
  194.       {
  195.         genop(SHOVERV); compile(); type_check(type,0);
  196.     gonum8(SETRVAR,type);
  197.       }
  198.     }
  199.     else
  200.     {
  201.       if (!compiled)
  202.       {
  203.     if (x) go2num((scope == LOCAL ? GETLVAR : GETGVAR),type,z);
  204.     else
  205.     {
  206.       compile(); type_check(type,0);
  207.       go2num((scope == LOCAL ? SETLVAR : SETGVAR), type,z);
  208.     }
  209.       }
  210.       else
  211.       {
  212.     genop(SHOVERV); gonumx((int32)tsize); genop(MUL);
  213.     genop(SHOVERV); gonum16((scope == LOCAL ? RVLBASE : RVGBASE),z);
  214.     if (x) gonum8(GETRVAR,type);
  215.     else
  216.     {
  217.       genop(SHOVERV);
  218.       compile(); type_check(type,0);
  219.       gonum8(SETRVAR,type);
  220.     }
  221.       }
  222.     }
  223.     class = type;
  224.     return TRUE;    /* done with arrays */
  225.   }
  226.     /* its a var */
  227.   strcpy(temp,token); lookahead();
  228.   if (class == DELIMITER && *token == ')') genvar(temp,eval);
  229.   else            /* var assignment */
  230.   {
  231.     if (arg)        /* (foo "hoho") where foo is (arg n) */
  232.       if (type == STRING || type == LIST)
  233.       {
  234. /* !!!??? this may not be right */
  235.         /* get the arg (an object) (I hope) */
  236.     gonumx((int32)offset); genop(ARG); genop(SHOVERV);
  237.     compile(); type_check(type,0);
  238.     gonum8(SETRVAR,type);
  239.       }
  240.       else
  241.       {
  242.     compile();
  243. /* !!! tell what the type is */
  244.     moan(spoof(ebuf,"Can't change stack vars of that type (%s).",temp));
  245.       }
  246.     else
  247.     {
  248.       compile(); type_check(type,0);
  249.       go2num((scope == LOCAL ? SETLVAR : SETGVAR),
  250.     (type & POINTER) ? BLOB : type, offset);
  251.     }
  252.   }
  253.   return TRUE;
  254. }
  255.  
  256. isvarok(clevel,class)
  257. {
  258.   if (!(clevel == 0 || class == VAROK))
  259.     { moan("Can't create vars here."); return FALSE; }
  260.   return TRUE;
  261. }
  262.  
  263. void vdeclare(type,local)
  264. {
  265.   int x, total_bytes;
  266.  
  267.   x = typesize(type);
  268.   total_bytes = 0;
  269.   do
  270.   {
  271.     get_token();
  272.     if (class != TOKEN) bitch(spoof(ebuf,"%s is not a var name.",token));
  273.     addvar(token, type, x, (local ? LOCAL : GLOBAL));
  274.     total_bytes += x;
  275.     lookahead();
  276.   } while (class == TOKEN);
  277.   if (local) gonum16(LALLOC, total_bytes);
  278. }
  279.  
  280. void pointer(local)        /* (pointer type name ...) */
  281. {
  282.   int t = -1;
  283.  
  284.   get_token();
  285.   if (class == TOKEN) t = lookup(token,muttcmds,msize);
  286.   switch (t)
  287.   {
  288.     case 62: vdeclare(POINTER | BOOLEAN,local); break;
  289.     case 61: vdeclare(POINTER | INT16,    local); break;
  290.     case 75: vdeclare(POINTER | INT8,    local); break;
  291.     case 31: vdeclare(POINTER | INT32,    local); break;
  292.     case 60: vdeclare(POINTER | STRING,    local); break;
  293.     default:
  294.       moan(spoof(ebuf,"%s is not a pointer type.",token));
  295.       vdeclare(POINTER | BOOLEAN,local);
  296.   }
  297. }
  298.  
  299. static getnum(n) int *n;
  300. {
  301.   char *errmsg = "Array dimensions are positive numeric constants.";
  302.   int x;
  303.   MMDatum *rv;
  304.  
  305.   lookahead();
  306.   if (class==DELIMITER || (class==TOKEN && (rv = getconst(token))==NULL))
  307.     return FALSE;
  308.   get_token();
  309.   if (class==TOKEN) { if (rv->type!=NUMBER) bitch(errmsg); x = rv->val.num; }
  310.   else { if (class!=NUMBER) bitch(errmsg); x = atoN(token); }
  311.   if (x<=0) { moan(errmsg); x = 1; }
  312.   *n = x;
  313.   return TRUE;
  314. }
  315.  
  316. int ntharg;    /* arg & proto count for defun */
  317.  
  318. void array(scope,arg)            /* (array type name subs) */
  319. {
  320.   int t,size,x, n, dim[MAXDIM],z, tsize;
  321.   unsigned int type;
  322.  
  323.   size = 0;
  324.   get_token();
  325.   if (class == TOKEN) t = lookup(token,muttcmds,msize);
  326.   else bitch(spoof(ebuf,"%s is not an array type.",token));
  327.   switch(t)
  328.   {
  329.     default:
  330.       moan(spoof(ebuf,"%s is not an array type.",token));
  331.       type = BOOLEAN; goto defvar;
  332.     case 62:        /* (array bool name d1 ...) */
  333.       type = BOOLEAN;
  334. defvar:
  335.       tsize = typesize(type);
  336.       do
  337.       {
  338.     z = 1; n = 0;
  339.     get_token(); strcpy(temp,token);    /* get and save name */
  340.     if (class != TOKEN) bitch(spoof(ebuf,"%s is not a var name.",token));
  341.     while (TRUE)
  342.     {
  343.       if (!getnum(&x)) break;
  344.       if (n >= MAXDIM)
  345.         bitch(spoof(ebuf,"Too many dimensions (max is %d).",MAXDIM)); 
  346.       z *= (dim[n++] = x);
  347.     }
  348.     if (n == 0) moan("An array needs dimensions.");
  349.     z *= tsize; size += z;
  350.     if (arg) moreproto(temp,ntharg++,type,n,dim);
  351.     else add_array(temp,type,z,scope,n,dim);
  352.     lookahead();
  353.       } while (class == TOKEN);
  354.       if (!arg && scope == LOCAL) gonum16(LALLOC,size);
  355.       break;
  356.     case 75: type = INT8;  goto defvar;        /* (byte var [var ...]) */
  357.     case 61: type = INT16; goto defvar;        /* (int var [var ...]) */
  358.     case 31: type = INT32; goto defvar;        /* (INT var [var ...]) */
  359.     case 60:        /* (array string n) */
  360.       moan("I don't support string arrays (anymore)!");        /* ??? */
  361. #if 0
  362.       size = 0;
  363.       do
  364.       {
  365.     get_token(); strcpy(temp,token);    /* get and save name */
  366.     if (class != TOKEN) bitch(spoof(ebuf,"%s is not a var name.",token));
  367.  
  368.     t = getnum(&n) && getnum(&x);
  369.     if (!t || x > MAXSTRLEN)
  370.       bitch(spoof(ebuf,
  371.         "String length is a postive numeric constant <= %d.",MAXSTRLEN));
  372.     dim[0] = n; dim[1] = x+1;
  373.     z = dim[0]*dim[1]*sizeof(char);
  374.     size += z;
  375.     if (arg) moreproto(temp,ntharg++,STRING,2,dim);
  376.     else add_array(temp,STRING,z,scope,2,dim);
  377.     lookahead();
  378.       } while (class == TOKEN);
  379. /*      if (!arg && scope == LOCAL) gonum16(LALLOC,size);*/
  380. #endif
  381.       break;
  382.   }
  383. }
  384.