home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / ace / c / sub.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-04  |  11.8 KB  |  465 lines

  1. /* << ACE >>
  2.  
  3.    -- Amiga BASIC Compiler --
  4.  
  5.    ** Parser: subprogram code **
  6.    ** Copyright (C) 1998 David Benn
  7.    ** 
  8.    ** This program is free software; you can redistribute it and/or
  9.    ** modify it under the terms of the GNU General Public License
  10.    ** as published by the Free Software Foundation; either version 2
  11.    ** of the License, or (at your option) any later version.
  12.    **
  13.    ** This program is distributed in the hope that it will be useful,
  14.    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    ** GNU General Public License for more details.
  17.    **
  18.    ** You should have received a copy of the GNU General Public License
  19.    ** along with this program; if not, write to the Free Software
  20.    ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22.    Author: David J Benn
  23.      Date: 26th October-30th November, 1st-13th December 1991,
  24.        14th,20th-27th January 1992, 
  25.            2nd-17th, 21st-29th February 1992, 
  26.        1st,13th,14th,22nd,23rd March 1992,
  27.        21st,22nd April 1992,
  28.        2nd,3rd,11th,15th,16th May 1992,
  29.        7th,8th,9th,11th,13th,14th,28th,29th,30th June 1992,
  30.        2nd-8th,14th-19th,26th-29th July 1992,
  31.        1st-3rd,7th,8th,9th August 1992,
  32.        6th,7th December 1992,
  33.        24th March 1993,
  34.        14th,20th,30th June 1993,
  35.        18th December 1993,
  36.        12th,21st June 1994
  37. */
  38.  
  39. #include "acedef.h"
  40.  
  41. /* locals */
  42. static    char     *frame_ptr[] = { "(a4)","(a5)" };
  43.  
  44. /* externals */
  45. extern    int    sym;
  46. extern    int    typ;
  47. extern    int    lev;
  48. extern    char       id[MAXIDSIZE]; 
  49. extern    SYM    *curr_item;
  50. extern    CODE    *curr_code;
  51. extern    int      addr[2]; 
  52.  
  53. /* functions */
  54. void forward_ref()
  55. {
  56. char  sub_name[80];
  57. SYM   *sub_ptr;
  58. short param_count=0;
  59. int   param_type;
  60. int   sub_type=undefined;
  61. /* declare a forward reference to a SUB -- see declare() 
  62.    NO checking against symbol table is carried out */
  63.  
  64.  insymbol();
  65.  
  66.  /* type identifiers */
  67.  if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  68.      sym == singlesym || sym == stringsym)
  69.  {
  70.   switch(sym)
  71.   {
  72.    case shortintsym : sub_type = shorttype;  break;
  73.    case longintsym  : sub_type = longtype;   break;
  74.    case addresssym  : sub_type = longtype;   break;
  75.    case singlesym   : sub_type = singletype; break;
  76.    case stringsym   : sub_type = stringtype; break;
  77.   }
  78.   insymbol();
  79.  }
  80.  
  81.  if (sym != ident) _error(7);
  82.  else
  83.  {
  84.   /* get the name */ 
  85.   strcpy(sub_name,"_SUB_");
  86.   strcat(sub_name,id);
  87.   
  88.   /* enter it into symbol table & mark as forward ref. */
  89.   if (!exist(sub_name,subprogram))
  90.   {
  91.    if (sub_type == undefined) sub_type = typ;
  92.    enter(sub_name,sub_type,subprogram,0);
  93.    curr_item->decl=fwdref;
  94.   }
  95.   else _error(33); /* subprogram already declared */
  96.  
  97.   sub_ptr=curr_item;
  98.  
  99.   /* get parameters -- if any */  
  100.   insymbol();
  101.   if (sym != lparen) 
  102.   {
  103.    /* Is this an external subprogram? */
  104.    if (sym == externalsym) 
  105.    {
  106.     insymbol();
  107.     enter_XREF(sub_name);
  108.     sub_ptr->address = extfunc;
  109.    }
  110.  
  111.    sub_ptr->no_of_params=0;
  112.    return; /* no parameters -> return sym */
  113.   }
  114.   else
  115.   {
  116.    /* parameters expected */
  117.    do
  118.    {
  119.     param_type = undefined;
  120.  
  121.     insymbol();
  122.  
  123.     /* type identifiers */
  124.     if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  125.         sym == singlesym || sym == stringsym)
  126.     {
  127.      switch(sym)
  128.      {
  129.       case shortintsym : param_type = shorttype;  break;
  130.       case longintsym  : param_type = longtype;   break;
  131.       case addresssym  : param_type = longtype;   break;
  132.       case singlesym   : param_type = singletype; break;
  133.       case stringsym   : param_type = stringtype; break;
  134.      }
  135.      insymbol();
  136.     }
  137.  
  138.     if (sym != ident) _error(7);  /* ident expected */
  139.     else
  140.     {
  141.      /* store parameter type */
  142.      if (param_type == undefined) param_type=typ;
  143.      sub_ptr->p_type[param_count]=param_type;
  144.      param_count++;
  145.     }
  146.     insymbol();
  147.    }
  148.    while ((sym == comma) && (param_count < MAXPARAMS));
  149.   
  150.    sub_ptr->no_of_params=param_count;
  151.  
  152.    if (param_count == MAXPARAMS) _error(42);  /* too many */
  153.  
  154.    if (sym != rparen) _error(9);
  155.    insymbol();
  156.  
  157.    /* Is this an external subprogram? */
  158.    if (sym == externalsym) 
  159.    {
  160.     insymbol();
  161.     enter_XREF(sub_name);
  162.     sub_ptr->address = extfunc;
  163.    }
  164.   }
  165.  }
  166. }
  167.  
  168. void load_params(sub_ptr)
  169. SYM *sub_ptr;
  170. {
  171. SHORT par_addr=-8; /* one word above stack frame 
  172.                   (allows for R.A. & address reg store) */
  173. SHORT i,n;
  174. int   formal_type;
  175. char  addrbuf[40];
  176. char  formaltemp[MAXPARAMS][80],formaladdr[MAXPARAMS][80];
  177. int   formaltype[MAXPARAMS];
  178.  
  179.  /* store actual parameters in stack frame of subprogram to be CALLed */
  180.  
  181.  if (sym != lparen) { _error(14); return; }
  182.  else
  183.  {
  184.   i=0;
  185.   do
  186.   {
  187.    insymbol();
  188.    formal_type=expr();
  189.  
  190.    /* check parameter types */
  191.    if (formal_type != sub_ptr->p_type[i]) 
  192.    {
  193.     /* coerce actual parameter type to formal parameter type */
  194.     switch(sub_ptr->p_type[i])
  195.     {
  196.      case shorttype: make_sure_short(formal_type);
  197.              break;
  198.  
  199.      case longtype: if ((formal_type = make_integer(formal_type)) == shorttype) 
  200.                make_long();
  201.             else 
  202.                        if (formal_type == notype) _error(4); /* string */ 
  203.             break;
  204.  
  205.      case singletype : gen_Flt(formal_type);
  206.                break;
  207.  
  208.      case stringtype : _error(4);  /* can't coerce this at all! */
  209.                break;
  210.     }
  211.    }
  212.  
  213.    /* store parameter information temporarily since further stack operations  
  214.       may corrupt data in next frame if stored immediately */
  215.    if (sub_ptr->p_type[i] == shorttype)
  216.    {
  217.     par_addr -= 2; 
  218.     /* save parameter type */
  219.     formaltype[i]=shorttype; /* not data TYPE but STORE type (2 or 4 bytes) */
  220.  
  221.     /* save address of formal */
  222.     itoa(par_addr,addrbuf,10);
  223.     strcat(addrbuf,"(sp)");
  224.     strcpy(formaladdr[i],addrbuf);
  225.  
  226.     /* create temporary store in current stack frame -> don't use a global
  227.        data object as it could be clobbered during recursion! */
  228.     addr[lev] += 2;
  229.     itoa(-1*addr[lev],formaltemp[i],10);
  230.     strcat(formaltemp[i],frame_ptr[lev]); 
  231.     
  232.     /* store it */
  233.     gen("move.w","(sp)+",formaltemp[i]);
  234.    }
  235.    else
  236.    /* long, single, string, array */   
  237.    {
  238.     par_addr -= 4; 
  239.     /* save parameter type */
  240.     formaltype[i]=longtype;  /* storage requirement is 4 bytes */
  241.  
  242.     /* save address of formal */
  243.     itoa(par_addr,addrbuf,10);
  244.     strcat(addrbuf,"(sp)");
  245.     strcpy(formaladdr[i],addrbuf);
  246.  
  247.     /* create temporary store in current stack frame -> don't use a global
  248.        data object as it could be clobbered during recursion! */
  249.     addr[lev] += 4;
  250.     itoa(-1*addr[lev],formaltemp[i],10);
  251.     strcat(formaltemp[i],frame_ptr[lev]); 
  252.     
  253.     /* store it */
  254.     gen("move.l","(sp)+",formaltemp[i]);
  255.    }
  256.    
  257.    i++;
  258.   }
  259.   while ((i < sub_ptr->no_of_params) && (sym == comma));
  260.  
  261.   if ((i < sub_ptr->no_of_params) || (sym == comma)) 
  262.      _error(39); /* parameter count mismatch - too few or too many resp. */
  263.   else
  264.   {
  265.    /* disable multi-tasking 
  266.       before passing parameters */
  267.    gen("movea.l","_AbsExecBase","a6");
  268.    gen("jsr","_LVOForbid(a6)","  ");
  269.    enter_XREF("_AbsExecBase");
  270.    enter_XREF("_LVOForbid");
  271.  
  272.    /* load parameters into next frame */
  273.    for (n=0;n<sub_ptr->no_of_params;n++)
  274.    {
  275.     if (formaltype[n] == shorttype) 
  276.        gen("move.w",formaltemp[n],formaladdr[n]); /* short */
  277.     else
  278.        gen("move.l",formaltemp[n],formaladdr[n]); /* long,string,single,array */
  279.    }
  280.   }
  281.  
  282.   if (sym != rparen) _error(9);
  283.  }
  284. }
  285.  
  286. void sub_params(sub_ptr)
  287. SYM  *sub_ptr;
  288. {
  289. SHORT param_count=0;
  290. int   param_type;
  291. char  addrbuf[40];
  292.  
  293.  /* parse current SUB's formal parameter list */
  294.  
  295.  insymbol();
  296.  if (sym != lparen) 
  297.  {
  298.   sub_ptr->no_of_params=0;
  299.   return; /* no parameters -> return sym */
  300.  }
  301.  else
  302.  {
  303.   /* if actual parameters passed, Forbid() called -> Permit() */
  304.   gen("movea.l","_AbsExecBase","a6");
  305.   gen("jsr","_LVOPermit(a6)","  ");
  306.   enter_XREF("_AbsExecBase");
  307.   enter_XREF("_LVOPermit");
  308.  
  309.   /* formal parameters expected */
  310.   do
  311.   {
  312.    param_type=undefined;
  313.  
  314.    insymbol();
  315.  
  316.    /* type identifiers */
  317.    if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  318.        sym == singlesym || sym == stringsym)
  319.    {
  320.     switch(sym)
  321.     {
  322.      case shortintsym : param_type = shorttype;  break;
  323.      case longintsym  : param_type = longtype;   break;
  324.      case addresssym  : param_type = longtype;   break;
  325.      case singlesym   : param_type = singletype; break;
  326.      case stringsym   : param_type = stringtype; break;
  327.     }
  328.     insymbol();
  329.    }
  330.  
  331.    if (sym != ident) _error(7);  /* ident expected */
  332.    else
  333.    {
  334.     if (!exist(id,variable)) /* treat param's as local variables */
  335.     {
  336.        /* if type not already specified, take type indicated by ident */ 
  337.        if (param_type == undefined) param_type = typ;
  338.  
  339.        /* enter parameter as a variable into symbol table */
  340.        enter(id,param_type,variable,0);
  341.  
  342.        /* string parameter? -> associate with BSS object */
  343.        if (curr_item->type == stringtype)  
  344.        {
  345.           itoa(-1*curr_item->address,addrbuf,10);
  346.       strcat(addrbuf,frame_ptr[ONE]);
  347.       gen("move.l",addrbuf,"-(sp)");  /* push value parameter */
  348.           assign_to_string_variable(curr_item,MAXSTRLEN);
  349.        }
  350.     }
  351.     else
  352.        _error(38); /* duplicate parameter */
  353.    }
  354.  
  355.    /* store parameter type */
  356.    sub_ptr->p_type[param_count]=param_type;
  357.    param_count++;
  358.  
  359.    insymbol();
  360.   }
  361.   while ((sym == comma) && (param_count < MAXPARAMS));
  362.   
  363.   sub_ptr->no_of_params=param_count;
  364.  
  365.   if (param_count == MAXPARAMS) _error(42);  /* too many */
  366.  
  367.   if (sym != rparen) _error(9);
  368.   insymbol();
  369.  }
  370. }
  371.  
  372. void parse_shared_vars()
  373. {
  374. SYM  *zero_ptr,*one_ptr;
  375. int  i;
  376. char buf0[40],buf1[40],num[40];
  377. BOOL share_it;
  378.  
  379.  /* get the SHARED list for current SUB and store details */
  380.  
  381.  do
  382.  {
  383.   share_it=FALSE;
  384.   insymbol();
  385.   if (sym != ident) _error(7);  /* identifier expected */
  386.   else
  387.   {
  388.    lev=ZERO;
  389.    if (exist(id,variable) || exist(id,structure)) 
  390.    {
  391.     share_it=TRUE;
  392.     zero_ptr=curr_item;
  393.     lev=ONE;
  394.     enter(id,zero_ptr->type,zero_ptr->object,0);  /* variable or structure */    
  395.     one_ptr=curr_item;
  396.     /* add another 2 bytes to address if short */
  397.     if (one_ptr->type == shorttype) 
  398.     {
  399.      addr[lev] += 2;
  400.      one_ptr->address=addr[lev];
  401.     }
  402.     zero_ptr->shared=TRUE;
  403.     one_ptr->shared=TRUE;
  404.     if (one_ptr->type == stringtype)
  405.     one_ptr->new_string_var=FALSE; /* don't want a new BSS object! */
  406.     if (one_ptr->object == structure)
  407.     one_ptr->other = zero_ptr->other; /* pointer to structdef SYM node */
  408.    }
  409.    else
  410.    if (exist(id,array))
  411.    {
  412.     share_it=TRUE;
  413.     zero_ptr=curr_item;
  414.     lev=ONE;
  415.     enter(id,zero_ptr->type,array,zero_ptr->dims);    
  416.     one_ptr=curr_item;
  417.     zero_ptr->shared=TRUE;
  418.     one_ptr->shared=TRUE;
  419.     /* copy array index values from level ZERO to ONE */
  420.     for (i=0;i<=zero_ptr->dims;i++) one_ptr->index[i] = zero_ptr->index[i];
  421.     /* get string array element size? */
  422.     if (one_ptr->type == stringtype) 
  423.        one_ptr->numconst.longnum = zero_ptr->numconst.longnum;
  424.    }
  425.    else { _error(40); lev=ONE; }
  426.  
  427.    if (share_it)
  428.    {
  429.     /* copy size information for SIZEOF? */
  430.     if (one_ptr->type == stringtype || 
  431.         one_ptr->object == array ||
  432.         one_ptr->object == structure) one_ptr->size = zero_ptr->size;
  433.  
  434.     /* copy address of object from level ZERO to level ONE stack frame */
  435.     
  436.     /* frame location of level ONE object */ 
  437.     itoa(-1*one_ptr->address,buf1,10);
  438.     strcat(buf1,"(a5)");
  439.  
  440.     /* if simple numeric variable (short,long,single) or structure 
  441.        -> get address */
  442.     if ((zero_ptr->type != stringtype) && (zero_ptr->object != array))
  443.     {
  444.      strcpy(num,"#\0");
  445.      itoa(zero_ptr->address,buf0,10);
  446.      strcat(num,buf0);
  447.      gen("move.l","a4","d0");  /* frame pointer */
  448.      gen("sub.l",num,"d0");    /* offset from frame top */
  449.      gen("move.l","d0",buf1);  /* store address in level ONE frame */
  450.     }
  451.     else
  452.     {
  453.      /* array or string -> level ZERO already contains address */
  454.      itoa(-1*zero_ptr->address,buf0,10);
  455.      strcat(buf0,"(a4)");
  456.      gen("move.l",buf0,buf1);
  457.     }
  458.    }
  459.   }
  460.  
  461.   insymbol();
  462.  }
  463.  while (sym == comma);
  464. }
  465.