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

  1. /* << ACE >>
  2.  
  3.    -- Amiga BASIC Compiler --
  4.  
  5.    ** Parser: variable assignment 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,22nd December 1992,
  33.        6th January 1993,
  34.        12th,15th February 1993,
  35.        12th,16th April 1993,
  36.        20th,30th June 1993,
  37.        11th October 1993,
  38.        5th,16th-18th December 1993,
  39.        2nd January 1994,
  40.        21st June 1994,
  41.        20th August 1994,
  42.        1st,10th September 1994,
  43.        1st October 1994,
  44.        11th March 1995
  45. */
  46.  
  47. #include "acedef.h"
  48.  
  49. #define QUN_CODE 3
  50.  
  51. /* locals */
  52. static    char     *frame_ptr[] = { "(a4)","(a5)" };
  53.  
  54. /* externals */
  55. extern    int    sym;
  56. extern    int    lastsym;
  57. extern    int    obj;
  58. extern    int    typ;
  59. extern    char       id[MAXIDSIZE]; 
  60. extern    char       ut_id[MAXIDSIZE];
  61. extern    SHORT      shortval;
  62. extern    LONG       longval; 
  63. extern    float      singleval;
  64. extern    char       stringval[MAXSTRLEN];
  65. extern    SYM    *curr_item;
  66. extern    SHORT    dimsize[MAXDIMS];
  67. extern    char       string_const_start[7];
  68. extern    char       string_const_end[4];
  69. extern    int      lev;
  70. extern    int      strstorecount;
  71. extern    int    stringvarcount;
  72. extern    char     strstorename[80],strstorelabel[80];
  73. extern    int    storetype;
  74. extern    int      arraycount;
  75. extern    char     tempstrname[80];
  76. extern    BOOL     readpresent;
  77. extern    BOOL     have_lparen;
  78. extern    BOOL     have_equal;
  79.  
  80. /* functions */
  81.  
  82. int assign_coerce(storetype,exptype)
  83. int storetype,exptype;
  84. {
  85.  /* coerce expression type to store type */
  86.  
  87.  if (((storetype == stringtype) && (exptype != stringtype)) ||
  88.     ((storetype != stringtype) && (exptype == stringtype))) return(notype);
  89.  else
  90.  if (((storetype == shorttype) || (storetype == longtype))
  91.     && (exptype == singletype)) 
  92.  {
  93.   gen_round(storetype);
  94.  } 
  95.  else
  96.  if ((storetype == singletype) &&
  97.      ((exptype == shorttype) || (exptype == longtype))) 
  98.  {
  99.   gen_Flt(exptype);
  100.  }
  101.  else
  102.  if ((storetype == longtype) && (exptype == shorttype))
  103.  {
  104.   gen("move.w","(sp)+","d0");
  105.   gen("ext.l","d0","  ");
  106.   gen("move.l","d0","-(sp)");
  107.  }
  108.  else
  109.  if ((storetype == shorttype) && (exptype == longtype))
  110.  {
  111.   gen("move.l","(sp)+","d0");
  112.   /*gen("andi.l","#$ffff","d0");*/
  113.   gen("move.w","d0","-(sp)");
  114.  }
  115.  
  116.  return(storetype);  /* could be bytetype (for struct member) */
  117. }
  118.  
  119. void make_string_store()
  120. {
  121. char numbuf[40];
  122.  
  123.  itoa(strstorecount++,numbuf,10);
  124.  strcpy(strstorename,"_stringstore");
  125.  strcat(strstorename,numbuf);
  126.  strcpy(strstorelabel,strstorename);
  127.  strcat(strstorelabel,":\0");
  128. }
  129.  
  130. void create_string_variable(string_item,string_size)
  131. SYM *string_item;
  132. int string_size;
  133. {
  134. /* creates a unique BSS object for a string variable 
  135.    and stores its address in the string variable
  136.    pointer in the stack frame. 
  137. */
  138. char stringvarname[40],stringvarlabel[40],bss_size[20];
  139. char numbuf[10],addrbuf[20];
  140.  
  141.  /* keep a record of "stringvar" number which is
  142.     about to be created (for simple string variables
  143.     and string SUBs only) for future reference. 
  144.  */
  145.  string_item->numconst.longnum = stringvarcount;
  146.  
  147.  /* make name of BSS object */
  148.  strcpy(stringvarname,"_stringvar");
  149.  itoa(stringvarcount++,numbuf,10);
  150.  /* name */
  151.  strcat(stringvarname,numbuf);
  152.  /* label */
  153.  strcpy(stringvarlabel,stringvarname);
  154.  strcat(stringvarlabel,":\0");
  155.  
  156.  /* size of BSS object */
  157.  itoa(string_size,numbuf,10);
  158.  strcpy(bss_size,"ds.b ");
  159.  strcat(bss_size,numbuf);
  160.  
  161.  /* enter bss object */
  162.  enter_BSS(stringvarlabel,bss_size);
  163.  
  164.  /* store bss object address in stack frame */
  165.  itoa(-1*string_item->address,addrbuf,10);
  166.  strcat(addrbuf,frame_ptr[lev]);
  167.  
  168.  gen("pea",stringvarname,"  ");
  169.  gen("move.l","(sp)+",addrbuf); 
  170. }
  171.  
  172. void assign_to_string_variable(string_item,string_size)
  173. SYM *string_item;
  174. int string_size;
  175. {
  176. /* assigns a string on the stack 
  177.    to the specified string variable 
  178. */
  179. char addrbuf[20],buf[80];
  180.  
  181.  /* get stack frame address holder */
  182.  itoa(-1*string_item->address,addrbuf,10);
  183.  strcat(addrbuf,frame_ptr[lev]);
  184.  
  185.  if (string_item->new_string_var)
  186.  {
  187.   /* create a BSS object for new string variable */
  188.   create_string_variable(string_item,string_size);
  189.   string_item->new_string_var=FALSE;  
  190.  }
  191.  else
  192.  if (string_item->decl != declared && !string_item->shared)
  193.  {
  194.   /* Make sure there is a valid address in the 
  195.      variable's stack-frame address holder EACH
  196.      time the variable is to be assigned a value.
  197.  
  198.      The reason is that unlike a declared string
  199.      variable or array, an undeclared string variable 
  200.      might not have a valid address at the time of 
  201.      assignment since the first occurrence of said 
  202.      variable may be as part of a case statement which 
  203.      might NEVER be reached.
  204.  
  205.      However, we still need string variable address
  206.      in stack frame for other purposes (eg: passing
  207.      to SUBs, use in factor() etc). 
  208.    */
  209.    sprintf(buf,"#_stringvar%ld",string_item->numconst.longnum);
  210.    gen("move.l",buf,addrbuf);
  211.  }
  212.  
  213.  /* copy string on stack to variable */
  214.  gen("move.l","(sp)+","a1");  /* source */
  215.  gen("move.l",addrbuf,"a0");  /* destination */
  216.  gen("jsr","_strcpy","  ");   /* copy source to destination */
  217.  enter_XREF("_strcpy");  
  218. }
  219.  
  220. void assign_to_string_array(addrbuf)
  221. char *addrbuf;
  222. {
  223. /* - assigns a string on the stack 
  224.      to the specified string array element.
  225.    - assumes absolute index is in d7.
  226. */
  227.  
  228.  gen("move.l","(sp)+","a1"); /* source */
  229.  gen("move.l",addrbuf,"a0");  
  230.  gen("adda.l","d7","a0");    /* destination */
  231.  
  232.  gen("jsr","_strcpy","  ");  /* copy source to destination */
  233.  enter_XREF("_strcpy");  
  234. }
  235.  
  236. void assign_to_struct(item)
  237. SYM *item;
  238. {
  239. /* assign either an address to 
  240.    a structure variable or a
  241.    value to one of its members.
  242. */
  243. SYM    *structype;
  244. char   addrbuf[40],absbuf[40],numbuf[40];
  245. STRUCM *member;
  246. BOOL   found=FALSE;
  247. int    exprtype,storetype;
  248.  
  249.  if (sym == memberpointer)
  250.  {
  251.   /* assign value to a member */
  252.  
  253.   /* get pointer to structure 
  254.      type definition. 
  255.   */
  256.   structype = item->other; 
  257.  
  258.   insymbol();
  259.  
  260.   if (sym != ident) 
  261.      _error(7);
  262.   else
  263.   {
  264.    /* does member exist? */
  265.    member = structype->structmem->next;
  266.    while ((member != NULL) && (!found)) 
  267.    {
  268.     if (strcmp(member->name,id) == 0)
  269.        found=TRUE;
  270.     else
  271.        member = member->next;
  272.    }
  273.    
  274.    /* dereference it? */
  275.    if (!found) 
  276.       { _error(67); insymbol(); }  /* not a member! */
  277.    else
  278.    {
  279.     /* assign value */
  280.     insymbol();
  281.     if (sym != equal)
  282.        _error(5);
  283.     else
  284.     {
  285.      insymbol();
  286.      exprtype=expr();
  287.  
  288.      /* treat byte type as a SHORT when coercing */ 
  289.      if (member->type == bytetype) 
  290.         storetype=shorttype;
  291.      else
  292.         storetype=member->type;  /* short, long, single */
  293.  
  294.      storetype = assign_coerce(storetype,exprtype);
  295.      if (storetype == notype) 
  296.          _error(4);   /* type mismatch */
  297.      else
  298.      {
  299.       /* address of structure */
  300.       ltoa(-1*item->address,addrbuf,10);
  301.       strcat(addrbuf,frame_ptr[lev]);
  302.  
  303.       if (item->shared && lev == ONE)
  304.       {
  305.      gen("movea.l",addrbuf,"a0");  /* structure variable address */    
  306.      gen("movea.l","(a0)","a0");   /* start address of structure */
  307.       }
  308.       else
  309.           gen("movea.l",addrbuf,"a0"); /* start address of structure */
  310.  
  311.       /* offset from struct start */ 
  312.       if (member->type != stringtype)
  313.       {
  314.        ltoa(member->offset,absbuf,10);
  315.        strcat(absbuf,"(a0)");
  316.       }
  317.  
  318.       if (member->type == bytetype)
  319.       {
  320.        gen("move.w","(sp)+","d0");
  321.        gen("move.b","d0",absbuf);  /* byte */
  322.       }
  323.       else
  324.       if (member->type == stringtype)  /* string */
  325.       {
  326.        sprintf(numbuf,"#%ld",member->offset);
  327.        gen("move.l","(sp)+","a1");  /* source */
  328.        gen("adda.l",numbuf,"a0");   /* destination = struct address + offset */
  329.        gen("jsr","_strcpy","  ");   /* copy source to destination */
  330.        enter_XREF("_strcpy");  
  331.       }
  332.       else
  333.       if (member->type == shorttype)
  334.          gen("move.w","(sp)+",absbuf);  /* short */
  335.       else
  336.          gen("move.l","(sp)+",absbuf);  /* long, single */
  337.      }
  338.     } 
  339.    } 
  340.   }
  341.  }
  342.  else
  343.  {
  344.   /* assign address of structure */
  345.   if (sym != equal)
  346.      _error(5); 
  347.   else
  348.   {
  349.    insymbol();
  350.    if (expr() != longtype)
  351.       _error(4);
  352.    else
  353.    { 
  354.     /* address of structure */
  355.     ltoa(-1*item->address,addrbuf,10);
  356.     strcat(addrbuf,frame_ptr[lev]);
  357.     
  358.     if (item->shared && lev == ONE)
  359.     {     
  360.        gen("movea.l",addrbuf,"a0");     /* address of structure variable */
  361.        gen("move.l","(sp)+","(a0)");    /* store new address in variable */
  362.     }
  363.     else
  364.         gen("move.l","(sp)+",addrbuf);  /* store new address in variable */
  365.    }
  366.   }
  367.  }
  368. }
  369.  
  370. void assign()
  371. {
  372. char addrbuf[80],numbuf[80],sub_name[80];
  373. char ext_name[MAXIDSIZE],buf[MAXIDSIZE];
  374. SYM  *storage_item;
  375. int  oldlevel;
  376. int  exprtype;
  377.  
  378.  /* in case it's a subprogram */
  379.  strcpy(sub_name,"_SUB_");
  380.  strcat(sub_name,id);
  381.  
  382.  /* make external variable name 
  383.     by removing qualifier and  
  384.     adding an underscore prefix 
  385.     if one is not present. 
  386.  */
  387.  strcpy(buf,ut_id);
  388.  remove_qualifier(buf);
  389.  if (buf[0] != '_')
  390.  {
  391.   strcpy(ext_name,"_\0");
  392.   strcat(ext_name,buf);
  393.  }
  394.  else 
  395.      strcpy(ext_name,buf);
  396.  
  397.  /* does it exist? */
  398.  if (exist(id,constant)) { _error(53); return; }
  399.  else
  400.  if (exist(id,array)) obj=array;
  401.  else
  402.  if (exist(id,structure)) { assign_to_struct(curr_item); return; }
  403.  else
  404.  if (exist(sub_name,subprogram)) obj=subprogram;
  405.  else
  406.  if (exist(ext_name,extvar)) obj=extvar;
  407.  else
  408.  if (!exist(id,obj)) enter(id,typ,obj,0); /* create a simple variable */
  409.  
  410.  storage_item = curr_item;
  411.  
  412.  if (obj == array) push_indices(storage_item); /* parse indices first! */
  413.   
  414.  /* assign it */
  415.  if (!have_equal) insymbol();
  416.  if (sym == equal) 
  417.  { 
  418.   if (storage_item->object != array)  /* get expression later! */
  419.   {
  420.    insymbol(); 
  421.    exprtype = expr();
  422.    if (exprtype == undefined) _error(0);   /* illegal syms? */
  423.    storetype = assign_coerce(storage_item->type,exprtype);
  424.    if (storetype == notype) 
  425.        _error(4);   /* type mismatch */
  426.   }
  427.  
  428.       if (obj != extvar)
  429.       {
  430.        /* get address of object */
  431.        if (storage_item->object == subprogram) { oldlevel=lev; lev=ZERO; }
  432.   
  433.        itoa(-1*storage_item->address,addrbuf,10);
  434.        strcat(addrbuf,frame_ptr[lev]);
  435.     
  436.        if (storage_item->object == subprogram) lev=oldlevel; 
  437.       }
  438.  
  439.       switch(storage_item->object)
  440.       {
  441.        case variable   : 
  442.     if ((storage_item->shared) && (lev == ONE) 
  443.            && (storage_item->type != stringtype))
  444.         {
  445.          gen("move.l",addrbuf,"a0");  /* absolute address of store */
  446.      if (storage_item->type == shorttype)
  447.             gen("move.w","(sp)+","(a0)");
  448.      else
  449.             gen("move.l","(sp)+","(a0)");
  450.     }
  451.     else
  452.         /* ordinary variable or shared string variable */
  453.         if (storage_item->type == stringtype) 
  454.          assign_to_string_variable(storage_item,MAXSTRLEN);
  455.         else
  456.         if (storage_item->type == shorttype)
  457.            gen("move.w","(sp)+",addrbuf);
  458.         else
  459.           /* longtype or singletype */
  460.           gen("move.l","(sp)+",addrbuf);
  461.         break;
  462.  
  463.        case subprogram :   
  464.     if (storage_item->address != extfunc)
  465.     {
  466.           if (storage_item->type == stringtype)
  467.               {
  468.              oldlevel=lev;
  469.              lev=ZERO; 
  470.                assign_to_string_variable(storage_item,MAXSTRLEN);
  471.                  lev=oldlevel;
  472.               }
  473.               else
  474.               if (storage_item->type == shorttype)
  475.                      gen("move.w","(sp)+",addrbuf);
  476.               else
  477.                      /* longtype or singletype */
  478.                      gen("move.l","(sp)+",addrbuf);
  479.     }
  480.     else
  481.     {
  482.         /* External subprogram being assigned a value */
  483.         if (storage_item->type == shorttype)
  484.             gen("move.w","(sp)+","d0");
  485.         else
  486.             /* longint, single, string */
  487.             gen("move.l","(sp)+","d0");
  488.     }
  489.         break;
  490.  
  491.     case extvar : if (storage_item->type == shorttype)
  492.             /* short integer */
  493.                   gen("move.w","(sp)+",ext_name);
  494.               else
  495.               if (storage_item->type == stringtype)
  496.               {
  497.             /* string */
  498.             gen("move.l","(sp)+","a1");
  499.             gen("lea",ext_name,"a0");    
  500.             gen("jsr","_strcpy","  ");
  501.             enter_XREF("_strcpy");
  502.               }    
  503.               else
  504.              /* long integer, single-precision */
  505.              gen("move.l","(sp)+",ext_name);
  506.               break;
  507.     
  508.     case array :     get_abs_ndx(storage_item);
  509.             
  510.             /* save storage info in case it gets clobbered
  511.                by other arrays in expr()!! */
  512.             gen("move.l","d7","_tmpelement");
  513.             enter_BSS("_tmpelement","ds.l 1");
  514.  
  515.             /*if (storage_item->type == stringtype)
  516.             {
  517.              gen("move.l","_stroffset","_tmpstroffset");
  518.              enter_BSS("_tmpstroffset","ds.l 1");
  519.             }*/
  520.  
  521.             /* get expression */
  522.                insymbol(); 
  523.             have_lparen=FALSE; /* may encounter another array */
  524.                exprtype = expr();
  525.                if (exprtype == undefined) 
  526.                _error(0);  /* illegal syms? */
  527.                storetype = assign_coerce(storage_item->type,exprtype);
  528.                if (storetype == notype) 
  529.                       _error(4);   /* type mismatch */
  530.             
  531.             /* restore storage item info */
  532.             gen("move.l","_tmpelement","d7");
  533.  
  534.                 if (storage_item->type == stringtype) 
  535.                assign_to_string_array(addrbuf);
  536.                 else
  537.             if (storage_item->type == shorttype)
  538.             {
  539.                gen("move.l",addrbuf,"a0");
  540.                gen("move.w","(sp)+","0(a0,d7.L)");
  541.             }
  542.             else
  543.               {
  544.                /* long or single */
  545.                gen("move.l",addrbuf,"a0");
  546.                gen("move.l","(sp)+","0(a0,d7.L)");
  547.               }
  548.             break;
  549.      }
  550.  } else _error(5); /* '=' expected */
  551. }  
  552.  
  553. void make_array_name(name,lab)
  554. char *name;
  555. char *lab;
  556. {
  557. char num[20];
  558.  
  559.  strcpy(name,"_array");
  560.  itoa(arraycount++,num,10);
  561.  strcat(name,num);
  562.  strcpy(lab,name);
  563.  strcat(lab,":\0");
  564.  
  565. void dim()
  566. /* declare an array */
  567. {
  568. BOOL  dimmed=TRUE;
  569. int   index;
  570. int   arraytype;
  571. char  arrayid[50];
  572. SYM   *array_item;
  573. char  buf[80],numbuf[80],addrbuf[80];
  574. char  arrayname[80],arraylabel[80];
  575. LONG  max_element,string_element_size;
  576.  
  577. do
  578. {
  579.  arraytype = undefined;
  580.  
  581.  insymbol();
  582.  
  583.  /* type identifiers */
  584.  if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  585.      sym == singlesym || sym == stringsym)
  586.  {
  587.   switch(sym)
  588.   {
  589.    case shortintsym : arraytype = shorttype;  break;
  590.    case longintsym  : arraytype = longtype;   break;
  591.    case addresssym  : arraytype = longtype;   break;
  592.    case singlesym   : arraytype = singletype; break;
  593.    case stringsym   : arraytype = stringtype; break;
  594.   }
  595.   insymbol();
  596.  }
  597.  
  598.  if (sym == ident) 
  599.  {
  600.   if (!exist(id,array))
  601.   { 
  602.     dimmed=FALSE; 
  603.     strcpy(arrayid,id); 
  604.     if (arraytype == undefined) arraytype=typ; 
  605.   }
  606.   else
  607.      { _error(22); insymbol(); return; }  /* array already declared */
  608.  
  609.   insymbol();
  610.  
  611.   if (sym != lparen)
  612.      _error(14);
  613.   else
  614.   {
  615.    index=0;
  616.    do
  617.    {
  618.     insymbol();
  619.     /* literal constant? */
  620.     if ((sym == shortconst) && (shortval > 0))
  621.        dimsize[index++] = shortval+1;
  622.     else
  623.     /* defined constant? */
  624.     if ((sym == ident) && (exist(id,constant)))
  625.     {
  626.      if ((curr_item->type == shorttype) && (curr_item->numconst.shortnum > 0))
  627.         dimsize[index++] = curr_item->numconst.shortnum+1;
  628.      else
  629.         _error(23);
  630.     }
  631.     else
  632.        _error(23);  /* illegal array index */
  633.     insymbol();
  634.    }
  635.    while ((sym == comma) && (index < MAXDIMS));
  636.  
  637.    if (sym != rparen)
  638.       _error(9);
  639.  
  640.    if (!dimmed) 
  641.    {
  642.     enter(arrayid,arraytype,array,index-1);
  643.     array_item = curr_item;
  644.  
  645.     max_element = max_array_ndx(array_item); /* number of linear elements */
  646.  
  647.     /* frame address to hold array pointer */  
  648.     itoa(-1*array_item->address,addrbuf,10);
  649.     strcat(addrbuf,frame_ptr[lev]);
  650.  
  651.     insymbol();
  652.  
  653.     /* specify size of string array elements with "SIZE"? */
  654.     if (sym == sizesym && array_item->type == stringtype)
  655.     {
  656.      insymbol();
  657.      if (sym == shortconst) 
  658.         string_element_size=(LONG)shortval; 
  659.      else
  660.      if (sym == longconst) 
  661.         string_element_size=longval; 
  662.      else
  663.      if (sym == ident && exist(id,constant))
  664.      {
  665.       if (curr_item->type == shorttype)
  666.          string_element_size=(LONG)curr_item->numconst.shortnum;
  667.       else
  668.       if (curr_item->type == longtype)
  669.          string_element_size=curr_item->numconst.longnum;
  670.       else
  671.           _error(4);
  672.      }
  673.      else
  674.      if (sym == singleconst)
  675.         _error(4);
  676.      else
  677.         _error(27);  /* numeric constant expected */
  678.  
  679.      if (string_element_size <= 0L) _error(41); /* non-positive string size */
  680.  
  681.      insymbol();
  682.     }
  683.     else
  684.         string_element_size=MAXSTRLEN;
  685.  
  686.     /* record size of array in bytes (for SIZEOF) 
  687.        plus string element size */
  688.     if (array_item->type == stringtype)
  689.     {
  690.        array_item->size = max_element * string_element_size;
  691.        /* size of each string array element */
  692.        array_item->numconst.longnum = string_element_size;
  693.     }
  694.     else
  695.     if (array_item->type == shorttype)
  696.        array_item->size = max_element*2;
  697.     else
  698.        /* long or single */
  699.        array_item->size = max_element*4; 
  700.  
  701.     /* specify ADDRESS? */
  702.     if (sym != addresssym)
  703.     {
  704.      /* set up BSS object for array */
  705.  
  706.      if (array_item->type == stringtype)
  707.         strcpy(buf,"ds.b ");
  708.      else
  709.      if (array_item->type == shorttype)
  710.         strcpy(buf,"ds.w ");
  711.      else
  712.         /* long or single */ 
  713.         strcpy(buf,"ds.l "); 
  714.  
  715.      if (array_item->type == stringtype)
  716.         ltoa(max_element*string_element_size,numbuf,10);
  717.      else
  718.         ltoa(max_element,numbuf,10);
  719.  
  720.      strcat(buf,numbuf);
  721.      make_array_name(arrayname,arraylabel);
  722.  
  723.      /* create the BSS object */
  724.      enter_BSS(arraylabel,buf);
  725.  
  726.      /* store address of array in stack frame */
  727.      gen("pea",arrayname,"  ");
  728.      gen("move.l","(sp)+",addrbuf);        
  729.     }
  730.     else
  731.     {
  732.      /* push specified array start address */
  733.      insymbol();
  734.      if (expr() != longtype)
  735.         _error(4);
  736.      else
  737.          /* store address of array in stack frame */
  738.          gen("move.l","(sp)+",addrbuf);        
  739.     }
  740.    }
  741.   }
  742.  }
  743.  else _error(7);
  744.  }
  745.  while (sym == comma);
  746. }
  747.  
  748. /* --------------- */
  749. /* INPUT functions */
  750. /* --------------- */
  751.  
  752. void input()
  753. {
  754. int  inptype;
  755. char addrbuf[80];
  756. SYM  *storage;
  757.  
  758.  if ((sym != comma) && (sym != semicolon) && (sym != ident)) 
  759.  {
  760.   /* print a string constant? */
  761.   inptype=expr();
  762.   if ((inptype == stringtype) && (lastsym == stringconst))
  763.   {
  764.    gen("jsr","_Ustringprint","  ");
  765.    gen("addq","#4","sp");
  766.    enter_XREF("_Ustringprint");
  767.   }
  768.   else _error(18); 
  769.  }
  770.  
  771.  do
  772.  { 
  773.   /* ";" or "," -> "?" */
  774.   if ((sym == comma) || (sym == semicolon))
  775.   {
  776.    if (sym == semicolon) 
  777.       { gen_printcode(QUN_CODE); gen_printcode(SPACE_CODE); }
  778.    insymbol();
  779.   }
  780.   else { gen_printcode(QUN_CODE); gen_printcode(SPACE_CODE); }
  781.  
  782.   /* allocate variable storage, call _input* and store value in variable */
  783.   if ((sym == ident) && (obj == variable))
  784.   {
  785.    if ((!exist(id,obj)) && (!exist(id,array)))
  786.       enter(id,typ,obj,0);  /* allocate storage for a simple variable */
  787.  
  788.    storage = curr_item;
  789.  
  790.    itoa(-1*storage->address,addrbuf,10);
  791.    strcat(addrbuf,frame_ptr[lev]); 
  792.   
  793.    /* ALL data types need a temporary string */
  794.    make_temp_string();
  795.    if (storage->type != stringtype)
  796.        gen("lea",tempstrname,"a1");
  797.    else
  798.     gen("pea",tempstrname,"  ");
  799.  
  800.    /* When storing an input value into an array element, must save
  801.       value (d0) first, since array index calculation may be corrupted
  802.       if index has to be coerced from ffp to short.
  803.    */
  804.  
  805.    switch(storage->type)
  806.    {
  807.     case shorttype  : gen("jsr","_inputshort","  ");
  808.  
  809.               if (storage->object == variable)
  810.               {
  811.                if ((storage->shared) && (lev == ONE))
  812.                {
  813.                  gen("move.l",addrbuf,"a0");  /* abs address of store */
  814.                     gen("move.w","d0","(a0)");
  815.                }
  816.                else
  817.                /* ordinary variable */
  818.                     gen("move.w","d0",addrbuf);
  819.               }
  820.               else 
  821.               if (storage->object == array)
  822.              {
  823.               gen("move.w","d0","_short_input_temp");
  824.               point_to_array(storage,addrbuf);
  825.               gen("move.w","_short_input_temp","0(a2,d7.L)");
  826.               enter_BSS("_short_input_temp:","ds.w 1");
  827.              }
  828.  
  829.                enter_XREF("_inputshort");
  830.               break;
  831.  
  832.     case longtype   : gen("jsr","_inputlong","  ");
  833.  
  834.               if (storage->object == variable)
  835.               {
  836.                if ((storage->shared) && (lev == ONE))
  837.                {
  838.                  gen("move.l",addrbuf,"a0");  /* abs address of store */
  839.                     gen("move.l","d0","(a0)");
  840.                }
  841.                else
  842.                /* ordinary variable */
  843.                     gen("move.l","d0",addrbuf);
  844.               }
  845.               else 
  846.               if (storage->object == array)
  847.              {
  848.               gen("move.l","d0","_long_input_temp");
  849.               point_to_array(storage,addrbuf);
  850.               gen("move.l","_long_input_temp","0(a2,d7.L)");
  851.               enter_BSS("_long_input_temp:","ds.l 1");
  852.              }
  853.  
  854.               enter_XREF("_inputlong");
  855.               break;
  856.  
  857.     case singletype : gen("jsr","_inputsingle","  ");
  858.  
  859.               if (storage->object == variable)
  860.               {
  861.                if ((storage->shared) && (lev == ONE))
  862.                {
  863.                  gen("move.l",addrbuf,"a0");  /* abs address of store */
  864.                     gen("move.l","d0","(a0)");
  865.                }
  866.                else
  867.                /* ordinary variable */
  868.                     gen("move.l","d0",addrbuf);
  869.               }
  870.               else 
  871.               if (storage->object == array)
  872.              {
  873.               gen("move.l","d0","_long_input_temp");
  874.               point_to_array(storage,addrbuf);
  875.               gen("move.l","_long_input_temp","0(a2,d7.L)");
  876.               enter_BSS("_long_input_temp:","ds.l 1");
  877.              }
  878.  
  879.               enter_XREF("_inputsingle");
  880.               enter_XREF("_MathBase"); /* need math libs */
  881.               enter_XREF("_MathTransBase");
  882.               break;
  883.  
  884.     case stringtype : gen("jsr","_Ustringinput","  ");
  885.  
  886.               if (storage->object == variable)
  887.                   assign_to_string_variable(storage,MAXSTRLEN);
  888.               else 
  889.               if (storage->object == array)
  890.              {
  891.               point_to_array(storage,addrbuf);
  892.               assign_to_string_array(addrbuf);
  893.              }
  894.  
  895.                  enter_XREF("_Ustringinput");
  896.               break;
  897.    }
  898.   } else _error(19);
  899.  
  900.  insymbol();
  901.  if (sym == lparen && storage->object != array) 
  902.     _error(71);  /* undeclared array */
  903.  }
  904.  while ((sym==comma) || (sym==semicolon) || (sym==ident));
  905. }
  906.  
  907. void point_to_array(storage,addrbuf)
  908. SYM  *storage;
  909. char *addrbuf;
  910. {
  911.  
  912.     /* get absolute index of array element */
  913.     have_lparen=FALSE;
  914.     push_indices(storage);
  915.     get_abs_ndx(storage);
  916.  
  917.     if (storage->type != stringtype)
  918.        gen("move.l",addrbuf,"a2");  /* --> pointer to start of array <-- */
  919. }
  920.  
  921. /* -------------- */
  922. /* DATA functions */
  923. /* -------------- */
  924.  
  925. void make_data_const(string)
  926. char *string;
  927. {
  928. char *strbuf,buf[MAXSTRLEN];
  929.  
  930.  /* actual string constant */
  931.  strbuf=(char *)alloc(strlen(string)+10,MEMF_ANY); 
  932.                              /* +10 is for string_const_start/end (9) & '\0' */ 
  933.  strcpy(strbuf,string_const_start);
  934.  strcat(strbuf,string);
  935.  strcat(strbuf,string_const_end);
  936.  enter_BASDATA(strbuf);
  937.  /*FreeMem(strbuf,strlen(string)+10);*/
  938. }
  939.  
  940. void get_data()
  941. {
  942. /* parse a line of BASIC DATA */
  943. char  fnumbuf[40];
  944. float fnum,sign;
  945.  
  946.  do
  947.  {
  948.   sign=1.0;
  949.  
  950.   insymbol();
  951.  
  952.   /* arithmetic sign? */
  953.   if ((sym == minus) || (sym == plus)) 
  954.   { 
  955.    if (sym == minus) sign=-1.0; 
  956.    insymbol();
  957.    if ((sym == ident) || (sym == stringconst)) _error(27);
  958.   }
  959.  
  960.   if (sym == ident) make_data_const(ut_id);
  961.   else
  962.    if (sym == stringconst) make_data_const(stringval);
  963.    else
  964.     if (sym == singleconst)
  965.     {
  966.      sprintf(fnumbuf,"%lx",SPMul(singleval,sign));
  967.      make_data_const(fnumbuf);
  968.     }
  969.     else
  970.      if (sym == longconst)
  971.      {
  972.       fnum=SPMul(SPFlt(longval),sign);
  973.       sprintf(fnumbuf,"%lx",fnum);
  974.       make_data_const(fnumbuf);
  975.      }        
  976.      else
  977.      if (sym == shortconst)
  978.      {
  979.       fnum=SPMul(SPFlt((long)shortval),sign);
  980.       sprintf(fnumbuf,"%lx",fnum);
  981.       make_data_const(fnumbuf);
  982.      }       
  983.      else _error(26);  /* constant expected */
  984.  
  985.    insymbol(); 
  986.   }
  987.   while (sym == comma);  
  988. }
  989.  
  990. void read_data()
  991. char addrbuf[80];
  992. SYM  *storage;
  993.  
  994. /* read a value from the DATA list into a variable or array element */
  995.  
  996.  readpresent=TRUE;
  997.  
  998.  do
  999.  {
  1000.   insymbol();
  1001.   
  1002.   if ((sym == ident) && (obj == variable))
  1003.   {
  1004.    if ((!exist(id,obj)) && (!exist(id,array)))
  1005.       enter(id,typ,obj,0);  /* allocate storage */
  1006.  
  1007.    storage=curr_item;  /* save storage item information */
  1008.  
  1009.    itoa(-1*storage->address,addrbuf,10);
  1010.    strcat(addrbuf,frame_ptr[lev]); 
  1011.   
  1012.    /* is it an array? (this must already have been dimensioned!) */
  1013.    if (storage->object == array)
  1014.    {
  1015.     /* get absolute index of array element */
  1016.     have_lparen=FALSE;
  1017.     push_indices(storage);
  1018.     get_abs_ndx(storage);
  1019.  
  1020.     /* --> get pointer to start of array <-- */
  1021.     if (storage->type != stringtype)
  1022.        gen("move.l",addrbuf,"a2");  
  1023.    }
  1024.  
  1025.    /* get next item from DATA list */
  1026.    if (typ != stringtype) 
  1027.       gen("move.l","_dataptr","a1");   /* for _htol */
  1028.  
  1029.    switch(storage->type)
  1030.    {
  1031.     case stringtype :    gen("move.l","_dataptr","-(sp)"); /* addr of source */
  1032.  
  1033.             if (storage->object == variable)
  1034.                     assign_to_string_variable(storage,MAXSTRLEN);
  1035.             else
  1036.                if (storage->object == array)
  1037.                   assign_to_string_array(addrbuf);
  1038.             break;
  1039.  
  1040.     case singletype :   gen("jsr","_htol","  "); /* return LONG from (a1) */
  1041.             if (storage->object == variable)
  1042.             {
  1043.                  if ((storage->shared) && (lev == ONE))
  1044.                  {
  1045.                   gen("move.l",addrbuf,"a0");  /* abs addr of store */
  1046.                       gen("move.l","d0","(a0)");
  1047.              }
  1048.              else
  1049.                   gen("move.l","d0",addrbuf);
  1050.             }
  1051.              else 
  1052.                 if (storage->object == array)
  1053.                    gen("move.l","d0","0(a2,d7.L)");
  1054.             enter_XREF("_htol");
  1055.             break;
  1056.  
  1057.     case longtype   :    gen("jsr","_htol","  ");
  1058.             gen("move.l","d0","-(sp)");
  1059.             make_integer(singletype);
  1060.             if (storage->object == variable)
  1061.             {
  1062.                  if ((storage->shared) && (lev == ONE))
  1063.                  {
  1064.                    gen("move.l",addrbuf,"a0");  /* abs addr of store */
  1065.                       gen("move.l","(sp)+","(a0)");
  1066.              }
  1067.              else
  1068.                   gen("move.l","(sp)+",addrbuf);
  1069.             }
  1070.              else 
  1071.                 if (storage->object == array)
  1072.                    gen("move.l","(sp)+","0(a2,d7.L)");
  1073.             enter_XREF("_htol");         
  1074.             break;
  1075.  
  1076.     case shorttype   :    gen("jsr","_htol","  ");
  1077.             gen("move.l","d0","-(sp)");
  1078.             make_sure_short(singletype);
  1079.             if (storage->object == variable)
  1080.             {
  1081.                  if ((storage->shared) && (lev == ONE))
  1082.                  {
  1083.                    gen("move.l",addrbuf,"a0");  /* abs addr of store */
  1084.                       gen("move.w","(sp)+","(a0)");
  1085.              }
  1086.              else
  1087.                   gen("move.w","(sp)+",addrbuf);
  1088.             }
  1089.              else 
  1090.                 if (storage->object == array)
  1091.                    gen("move.w","(sp)+","0(a2,d7.L)");
  1092.             enter_XREF("_htol");             
  1093.             break;
  1094.    }
  1095.   } 
  1096.   else _error(19);  /* variable expected */             
  1097.             
  1098.   /* advance to next DATA item */
  1099.   gen("move.l","_dataptr","a2");
  1100.   gen("jsr","_strlen","  ");
  1101.   enter_XREF("_strlen");
  1102.   gen("addq","#1","d0");  /* include EOS in length */
  1103.   gen("move.l","_dataptr","d1");
  1104.   gen("add.l","d0","d1");
  1105.   gen("move.l","d1","_dataptr");
  1106.  
  1107.   insymbol();
  1108.   if (sym == lparen && storage->object != array) 
  1109.      _error(71);  /* undeclared array */  
  1110.  }
  1111.  while (sym == comma);
  1112. }
  1113.