home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src_ansi / ace / c / control.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-05  |  19.4 KB  |  832 lines

  1. /* << ACE >>
  2.  
  3.    -- Amiga BASIC Compiler --
  4.  
  5.    ** Parser: control constructs **
  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.    11th,12th,14th,15th,28th February 1993,
  34.    1st,3rd March 1993,
  35.    2nd,5th January 1994,
  36.    20th August 1994,
  37.    4th,9th September 1996
  38.  */
  39.  
  40. #include "acedef.h"
  41. #include <string.h>
  42.  
  43. /* locals */
  44. static char *frame_ptr[] = {"(a4)", "(a5)"};
  45. static CODE *option[255];
  46.  
  47. /* externals */
  48. extern int sym;
  49. extern int lastsym;
  50. extern int obj;
  51. extern int typ;
  52. extern int lev;
  53. extern int storetype;
  54. extern char id[MAXIDSIZE];
  55. extern SYM *curr_item;
  56. extern CODE *curr_code;
  57. extern CODE *exit_for_cx;
  58. extern BOOL end_of_source;
  59. extern BOOL have_equal;
  60. extern BOOL have_lparen;
  61.  
  62. /* functions */
  63. void block_if (CODE * cx1)
  64. {
  65.   char labname1[80], lablabel1[80];
  66.   char labname2[80], lablabel2[80];
  67.   char labname3[80], lablabel3[80];
  68.   CODE *cx2;
  69.  
  70.   /* statement block after THEN */
  71.   insymbol ();
  72.   do
  73.     {
  74.       statement ();
  75.     }
  76.   while ((sym != elsesym) && (sym != endsym) && (!end_of_source));
  77.   /* ELSE or END IF */
  78.  
  79.   /* ELSE? */
  80.   if (sym == elsesym)
  81.     {
  82.       gen ("nop", "  ", "  ");    /* jump after THEN statement block */
  83.       cx2 = curr_code;
  84.  
  85.       /* execute ELSE code section if expression false */
  86.       make_label (labname1, lablabel1);
  87.       gen (lablabel1, "  ", "  ");
  88.       change (cx1, "jmp", labname1, "  ");
  89.  
  90.       insymbol ();
  91.       do
  92.     {
  93.       statement ();
  94.     }
  95.       while ((sym != endsym) && (!end_of_source));
  96.  
  97.       insymbol ();
  98.       if (sym == ifsym)
  99.     {
  100.       /* branch after THEN */
  101.       make_label (labname2, lablabel2);
  102.       gen (lablabel2, "  ", "  ");
  103.       change (cx2, "jmp", labname2, "  ");
  104.       insymbol ();
  105.     }
  106.       else
  107.     _error (15);        /* END IF expected */
  108.     }
  109.   else
  110.     /* no ELSE */
  111.     {
  112.       insymbol ();
  113.       if (sym == ifsym)
  114.     {
  115.       make_label (labname3, lablabel3);
  116.       gen (lablabel3, "  ", "  ");
  117.       change (cx1, "jmp", labname3, "  ");
  118.       insymbol ();
  119.     }
  120.       else
  121.     _error (15);        /* END IF expected */
  122.     }
  123. }
  124.  
  125. void if_statement (void)
  126. {
  127. /* IF..THEN..ELSE..
  128.    IF..GOTO..ELSE..
  129.    IF..THEN..ELSE..END IF  [block IF]
  130.  */
  131.   CODE *cx1, *cx2, *cx[3];
  132.   char labname1[80], lablabel1[80];
  133.   char labname2[80], lablabel2[80];
  134.   char labname3[80], lablabel3[80];
  135.   char labname4[80], lablabel4[80];
  136.   char buf[50], destbuf[3], idholder[50];
  137.   int targettype = longtype;
  138.   int i, oldobj, oldtyp;
  139.   int exprtype;
  140.  
  141.   insymbol ();
  142.   exprtype = expr ();
  143.  
  144.   /* make sure it's a LONG! */
  145.   exprtype = make_integer (exprtype);
  146.   for (i = 0; i <= 2; i++)
  147.     {
  148.       gen ("nop", "  ", "  ");
  149.       cx[i] = curr_code;
  150.     }
  151.   coerce (&exprtype, &targettype, cx);
  152.  
  153.   if (exprtype == longtype)
  154.     {
  155.       if ((sym == thensym) || (sym == gotosym))
  156.     {
  157.       gen ("move.l", "(sp)+", "d0");
  158.       gen ("cmpi.l", "#0", "d0");
  159.       make_label (labname1, lablabel1);
  160.       gen ("bne.s", labname1, "  ");
  161.       gen ("nop", "  ", "  ");    /* jump past THEN code section */
  162.       cx1 = curr_code;
  163.       gen (lablabel1, "  ", "  ");    /* execute THEN code */
  164.  
  165.       if (sym == gotosym)
  166.         statement ();    /* IF..GOTO */
  167.       else
  168.         /* IF..THEN */
  169.         {
  170.           /* block-if, implied GOTO or assignment statement? */
  171.           insymbol ();
  172.           if (sym == endofline)
  173.         {
  174.           block_if (cx1);
  175.           return;
  176.         }        /* block IF statement */
  177.  
  178.           if (sym == ident || sym == shortconst || sym == longconst)    /* label? */
  179.         {
  180.           /* assume implied GOTO at first */
  181.           if (sym != ident)
  182.             make_label_from_linenum (sym, id);
  183.           strcpy (buf, id);
  184.           strcat (buf, ":\0");
  185.  
  186.           if (!exist (buf, label))
  187.             strcpy (destbuf, "* ");    /* mark for later label check (see sym.c) */
  188.           else
  189.             strcpy (destbuf, "  ");    /* it's a declared label */
  190.  
  191.           strcpy (idholder, id);    /* save info for possible "jmp" or assign */
  192.           oldobj = obj;
  193.           oldtyp = typ;
  194.  
  195.           insymbol ();
  196.  
  197.           /* variable or array element or implicit branch? */
  198.           if (lastsym != ident ||
  199.               (lastsym == ident &&
  200.              sym != equal && sym != lparen && sym != memberpointer))
  201.             {
  202.               /* NOT an assignment statement */
  203.               strcpy (id, idholder);    /* restore id */
  204.               gen ("jmp", id, destbuf);
  205.             }
  206.           else if (lastsym == ident)
  207.             {
  208.               /* assignment */
  209.               strcpy (id, idholder);    /* restore info for assign() */
  210.               obj = oldobj;
  211.               typ = oldtyp;
  212.               if (sym == equal)
  213.             have_equal = TRUE;
  214.               if (sym == lparen)
  215.             if (!exist (id, array))
  216.               {
  217.                 _error (71);
  218.                 insymbol ();
  219.                 return;
  220.               }
  221.             else
  222.               have_lparen = TRUE;
  223.               assign ();
  224.               have_lparen = FALSE;
  225.               have_equal = FALSE;
  226.               if (sym == colon)
  227.             statement ();    /* multi-statement */
  228.             }
  229.         }
  230.           else
  231.         /* not an ident or line number */
  232.         {
  233.           statement ();
  234.           if (sym == colon)
  235.             statement ();    /* multi-statement */
  236.         }
  237.         }            /* END THEN code */
  238.  
  239.       if (sym == elsesym)
  240.         {
  241.           gen ("nop", "  ", "  ");    /* jump past ELSE code section */
  242.           cx2 = curr_code;
  243.  
  244.           /* execute ELSE code section if expression false */
  245.           make_label (labname2, lablabel2);
  246.           gen (lablabel2, "  ", "  ");
  247.           change (cx1, "jmp", labname2, "  ");
  248.  
  249.           insymbol ();
  250.           statement ();
  251.           if (sym == colon)
  252.         statement ();    /* multi-statement */
  253.  
  254.           /* unconditional branch after THEN */
  255.           make_label (labname3, lablabel3);
  256.           gen (lablabel3, "  ", "  ");
  257.           change (cx2, "jmp", labname3, "  ");
  258.         }
  259.       else
  260.         {
  261.           make_label (labname4, lablabel4);
  262.           gen (lablabel4, "  ", "  ");
  263.           change (cx1, "jmp", labname4, "  ");
  264.         }
  265.     }
  266.       else
  267.     _error (11);
  268.     }
  269.   else
  270.     _error (4);
  271. }
  272.  
  273. void while_statement (void)
  274. {
  275. /* WHILE...WEND */
  276.   CODE *cx2, *cx[3];
  277.   char labname1[80], lablabel1[80];
  278.   char labname2[80], lablabel2[80];
  279.   char labname3[80], lablabel3[80];
  280.   int targettype = longtype;
  281.   int i;
  282.   int exprtype;
  283.  
  284.   make_label (labname1, lablabel1);
  285.   gen (lablabel1, "  ", "  ");
  286.  
  287.   insymbol ();
  288.   exprtype = expr ();
  289.  
  290.   /* make sure it's a LONG! */
  291.   exprtype = make_integer (exprtype);
  292.   for (i = 0; i <= 2; i++)
  293.     {
  294.       gen ("nop", "  ", "  ");
  295.       cx[i] = curr_code;
  296.     }
  297.   coerce (&exprtype, &targettype, cx);    /* cx necessary if change from SHORT */
  298.  
  299.   if (exprtype == longtype)
  300.     {
  301.       gen ("move.l", "(sp)+", "d0");
  302.       gen ("cmpi.l", "#0", "d0");
  303.       make_label (labname2, lablabel2);
  304.       gen ("bne.s", labname2, "  ");
  305.       gen ("nop", "  ", "  ");    /* jump out of loop when condition is FALSE */
  306.       cx2 = curr_code;
  307.       gen (lablabel2, "  ", "  ");
  308.  
  309.       while ((sym != wendsym) && (!end_of_source))
  310.     statement ();
  311.  
  312.       if (sym != wendsym)
  313.     _error (12);
  314.  
  315.       check_for_event ();
  316.  
  317.       gen ("jmp", labname1, "  ");
  318.  
  319.       make_label (labname3, lablabel3);
  320.       gen (lablabel3, "  ", "  ");
  321.       change (cx2, "jmp", labname3, "  ");
  322.     }
  323.   else
  324.     _error (4);
  325.  
  326.   insymbol ();
  327. }
  328.  
  329. void repeat_statement (void)
  330. {
  331. /* REPEAT...UNTIL */
  332.   char labname1[80], lablabel1[80];
  333.   char labname2[80], lablabel2[80];
  334.   int exprtype;
  335.  
  336.   make_label (labname1, lablabel1);
  337.   gen (lablabel1, "  ", "  ");
  338.  
  339.   insymbol ();
  340.   while ((sym != untilsym) && (!end_of_source))
  341.     statement ();
  342.  
  343.   /* UNTIL condition */
  344.   if (sym == untilsym)
  345.     {
  346.       check_for_event ();
  347.       insymbol ();
  348.       exprtype = make_integer (expr ());
  349.       if (exprtype == shorttype)
  350.     {
  351.       make_long ();
  352.       exprtype = longtype;
  353.     }
  354.  
  355.       if (exprtype == longtype)
  356.     {
  357.       gen ("move.l", "(sp)+", "d0");
  358.       gen ("cmpi.l", "#0", "d0");
  359.       make_label (labname2, lablabel2);
  360.       gen ("bne.s", labname2, "  ");
  361.       gen ("jmp", labname1, "  ");    /* loop until condition is TRUE */
  362.       gen (lablabel2, "  ", "  ");
  363.     }
  364.       else
  365.     _error (4);
  366.     }
  367.   else
  368.     _error (51);
  369. }
  370.  
  371. void case_statement (void)
  372. {
  373. /* CASE...END CASE */
  374.   CODE *cx;
  375.   CODE *case_ptr[MAXCASES];
  376.   char labname1[80], lablabel1[80];
  377.   char labname2[80], lablabel2[80];
  378.   char case_end_labname[80], case_end_lablabel[80];
  379.   SHORT casecount = 0;
  380.   int exprtype = undefined;
  381.   SHORT i;
  382.  
  383.   insymbol ();
  384.   while (sym == endofline)
  385.     insymbol ();        /* skip blank line(s) */
  386.  
  387.   do
  388.     {
  389.       exprtype = make_integer (expr ());
  390.       if (exprtype == shorttype)
  391.     {
  392.       make_long ();
  393.       exprtype = longtype;
  394.     }
  395.  
  396.       if (sym == colon)
  397.     {
  398.       insymbol ();
  399.  
  400.       if (exprtype == longtype)
  401.         {
  402.           gen ("move.l", "(sp)+", "d0");
  403.           gen ("cmpi.l", "#0", "d0");
  404.           make_label (labname1, lablabel1);
  405.           gen ("bne.s", labname1, "  ");
  406.           gen ("nop", "  ", "  ");    /* try next case */
  407.           cx = curr_code;
  408.           gen (lablabel1, "  ", "  ");    /* execute code for THIS case */
  409.  
  410.           statement ();
  411.           if (sym == colon)
  412.         statement ();    /* multi-statement */
  413.  
  414.           gen ("jmp", "  ", "  ");
  415.           case_ptr[casecount++] = curr_code;    /* branch to end of CASE */
  416.  
  417.           /* label for next case */
  418.           make_label (labname2, lablabel2);
  419.           gen (lablabel2, "  ", "  ");
  420.           change (cx, "jmp", labname2, "  ");
  421.         }
  422.       else
  423.         _error (4);        /* type mismatch */
  424.     }
  425.       else
  426.     _error (24);        /* colon expected */
  427.  
  428.       while (sym == endofline)
  429.     insymbol ();        /* skip empty line(s) */
  430.     }
  431.   while ((exprtype == longtype) && (sym != endsym) &&
  432.      (casecount < MAXCASES) && (!end_of_source));
  433.  
  434.   /* END CASE */
  435.   if (sym != endsym)
  436.     _error (52);
  437.   else
  438.     {
  439.       insymbol ();
  440.       if (sym != casesym)
  441.     _error (52);
  442.       else
  443.     {
  444.       make_label (case_end_labname, case_end_lablabel);
  445.       gen (case_end_lablabel, "  ", "  ");
  446.       for (i = 0; i < casecount; i++)
  447.         change (case_ptr[i], "jmp", case_end_labname, "  ");
  448.       insymbol ();
  449.     }
  450.     }
  451. }
  452.  
  453. int for_assign (char *addr)
  454. {
  455.   SYM *storage_item;
  456.   int exprtype;
  457.  
  458.   /* does it exist? */
  459.   if (!exist (id, obj))
  460.     enter (id, typ, obj, 0);
  461.  
  462.   storage_item = curr_item;
  463.  
  464.   /* don't allow a shared variable to be the index */
  465.   if (storage_item->shared)
  466.     {
  467.       _error (70);
  468.       insymbol ();
  469.       return (undefined);
  470.     }
  471.  
  472.   /* assign it */
  473.   insymbol ();
  474.   if (sym == equal)
  475.     {
  476.       insymbol ();
  477.       exprtype = expr ();
  478.  
  479.       /* can't use a stringtype! */
  480.       if (exprtype == stringtype)
  481.     {
  482.       _error (4);
  483.       return (undefined);
  484.     }
  485.       /* expression not successfully parsed */
  486.       if (exprtype == undefined)
  487.     {
  488.       _error (0);
  489.       return (undefined);
  490.     }
  491.  
  492.       storetype = assign_coerce (storage_item->type, exprtype);
  493.       if (storetype == notype)
  494.     _error (4);        /* type mismatch */
  495.       else
  496.     {
  497.       /* get address of object */
  498.       itoa (-1 * storage_item->address, addr, 10);
  499.       strcat (addr, frame_ptr[lev]);
  500.  
  501.       if (storage_item->type == shorttype)
  502.         gen ("move.w", "(sp)+", addr);
  503.       else
  504.         /* longtype or singletype */
  505.         gen ("move.l", "(sp)+", addr);
  506.     }
  507.     }
  508.   else
  509.     _error (5);            /* '=' expected */
  510.   return (storage_item->type);    /* -> type for WHOLE for..next statement */
  511. }
  512.  
  513. void for_statement (void)
  514. {
  515. /* FOR variable=x to y [STEP [+|-]z]
  516.    Statement Block
  517.    NEXT [variable]
  518.  */
  519.   CODE *cx1, *cx2;
  520.   char labname1[80], lablabel1[80], labname2[80], lablabel2[80];
  521.   char labname3[80], lablabel3[80];
  522.   char counteraddr[10], limitaddr[10], stepaddr[10];
  523.   char for_id[50], cntbuf[10], limbuf[10], stpbuf[10];
  524.   int countertype, limittype, steptype;
  525.  
  526.   /* counter */
  527.   insymbol ();
  528.   if (sym != ident)
  529.     {
  530.       _error (7);
  531.       return;
  532.     }
  533.   strcpy (for_id, id);
  534.   countertype = for_assign (counteraddr);
  535.  
  536.   if (countertype == undefined)
  537.     return;
  538.   else
  539.     {
  540.       if (sym == tosym)
  541.     {
  542.       /* limit */
  543.       insymbol ();
  544.       limittype = expr ();
  545.       limittype = assign_coerce (countertype, limittype);
  546.       if (limittype == notype)
  547.         {
  548.           _error (4);
  549.           return;
  550.         }
  551.       if (limittype == shorttype)
  552.         strcpy (limitaddr, "2(sp)");
  553.       else
  554.         strcpy (limitaddr, "4(sp)");
  555.       if (sym == stepsym)
  556.         {
  557.           /* step */
  558.           insymbol ();
  559.           steptype = expr ();
  560.           steptype = assign_coerce (countertype, steptype);
  561.           if (steptype == notype)
  562.         {
  563.           _error (4);
  564.           return;
  565.         }
  566.         }
  567.       else
  568.         {
  569.           switch (countertype)    /* default step = 1 */
  570.         {
  571.         case shorttype:
  572.           gen ("move.w", "#1", "-(sp)");
  573.           break;
  574.         case longtype:
  575.           gen ("move.l", "#1", "-(sp)");
  576.           break;
  577.         case singletype:
  578.           gen ("move.l", "#$80000041", "-(sp)");
  579.           break;
  580.         }
  581.           steptype = countertype;
  582.         }
  583.       strcpy (stepaddr, "(sp)");    /* step is on stack top */
  584.  
  585.       /* top of for..next loop */
  586.       make_label (labname1, lablabel1);
  587.       gen (lablabel1, "  ", "  ");
  588.  
  589.       /* compare start & limit values */
  590.       strcpy (cntbuf, counteraddr);
  591.       strcpy (limbuf, limitaddr);
  592.       strcpy (stpbuf, stepaddr);
  593.  
  594.       if (countertype == shorttype)
  595.         {
  596.           gen ("move.w", cntbuf, "d0");    /* counter */
  597.           gen ("move.w", limbuf, "d1");    /* limit */
  598.           gen ("cmpi.w", "#0", stepaddr);
  599.           make_label (labname2, lablabel2);
  600.           gen ("blt", labname2, "  ");
  601.           gen ("cmp.w", "d1", "d0");
  602.           gen ("bgt", "  ", "  ");    /* if STEP +ve -> counter>limit? */
  603.           cx1 = curr_code;
  604.           make_label (labname3, lablabel3);        /* don't want to do -ve step test too! */
  605.           gen ("jmp", labname3, "  ");
  606.           gen (lablabel2, "  ", "  ");
  607.           gen ("cmp.w", "d1", "d0");
  608.           gen ("blt", "  ", "  ");    /* if STEP -ve -> counter<limit? */
  609.           cx2 = curr_code;
  610.           gen (lablabel3, "  ", "  ");    /* label for bypassing -ve step test */
  611.         }
  612.       else if (countertype == longtype)
  613.         {
  614.           gen ("move.l", cntbuf, "d0");    /* counter */
  615.           gen ("move.l", limbuf, "d1");    /* limit */
  616.           gen ("cmpi.l", "#0", stepaddr);
  617.           make_label (labname2, lablabel2);
  618.           gen ("blt", labname2, "  ");
  619.           gen ("cmp.l", "d1", "d0");
  620.           gen ("bgt", "  ", "  ");    /* if STEP +ve -> counter>limit? */
  621.           cx1 = curr_code;
  622.           make_label (labname3, lablabel3);        /* don't want to do -ve step test too! */
  623.           gen ("jmp", labname3, "  ");
  624.           gen (lablabel2, "  ", "  ");
  625.           gen ("cmp.l", "d1", "d0");
  626.           gen ("blt", "  ", "  ");    /* if STEP -ve -> counter<limit? */
  627.           cx2 = curr_code;
  628.           gen (lablabel3, "  ", "  ");    /* label for bypassing -ve step test */
  629.         }
  630.       else if (countertype == singletype)
  631.         {
  632.           gen ("moveq", "#0", "d1");
  633.           gen ("move.l", stpbuf, "d0");    /* d0 < d1? (where d1=0) */
  634.           gen ("move.l", "_MathBase", "a6");
  635.           gen ("jsr", "_LVOSPCmp(a6)", "  ");
  636.           enter_XREF ("_MathBase");
  637.           enter_XREF ("_LVOSPCmp");
  638.           make_label (labname2, lablabel2);
  639.           gen ("blt", labname2, "  ");    /* test result of ffp Cmp above */
  640.           gen ("move.l", cntbuf, "d0");    /* counter */
  641.           gen ("move.l", limbuf, "d1");    /* limit */
  642.           gen ("move.l", "_MathBase", "a6");
  643.           gen ("jsr", "_LVOSPCmp(a6)", "  ");
  644.           gen ("bgt", "  ", "  ");    /* if STEP +ve -> counter>limit? */
  645.           cx1 = curr_code;
  646.           make_label (labname3, lablabel3);        /* don't want to do -ve step test too! */
  647.           gen ("jmp", labname3, "  ");
  648.           gen (lablabel2, "  ", "  ");
  649.           gen ("move.l", cntbuf, "d0");    /* counter */
  650.           gen ("move.l", limbuf, "d1");    /* limit */
  651.           gen ("move.l", "_MathBase", "a6");
  652.           gen ("jsr", "_LVOSPCmp(a6)", "  ");
  653.           gen ("blt", "  ", "  ");    /* if STEP -ve -> counter<limit? */
  654.           cx2 = curr_code;
  655.           gen (lablabel3, "  ", "  ");    /* label for bypassing -ve step test */
  656.         }
  657.  
  658.       /* statement block */
  659.       while ((sym != nextsym) && (!end_of_source))
  660.         statement ();
  661.  
  662.       if (sym != nextsym)
  663.         {
  664.           _error (17);
  665.           return;
  666.         }
  667.  
  668.       /* NEXT -- legally followed by ident, colon or eoln! */
  669.       insymbol ();
  670.       if (sym == ident)
  671.         {
  672.           if (strcmp (id, for_id) != 0)
  673.         {
  674.           _error (17);
  675.           insymbol ();
  676.           return;
  677.         }
  678.         }
  679.       else if ((sym != endofline) && (sym != colon))
  680.         {
  681.           _error (17);
  682.           insymbol ();
  683.           return;
  684.         }
  685.  
  686.       if (sym != colon)
  687.         insymbol ();    /* return this sym to statement */
  688.  
  689.       /* counter=counter+step */
  690.       switch (steptype)
  691.         {
  692.         case shorttype:
  693.           gen ("move.w", stpbuf, "d0");
  694.           gen ("add.w", "d0", counteraddr);
  695.           break;
  696.         case longtype:
  697.           gen ("move.l", stpbuf, "d0");
  698.           gen ("add.l", "d0", counteraddr);
  699.           break;
  700.         case singletype:
  701.           gen ("move.l", stpbuf, "d0");
  702.           gen ("move.l", cntbuf, "d1");
  703.           gen ("move.l", "_MathBase", "a6");
  704.           gen ("jsr", "_LVOSPAdd(a6)", "  ");
  705.           gen ("move.l", "d0", counteraddr);
  706.           enter_XREF ("_MathBase");
  707.           enter_XREF ("_LVOSPAdd");
  708.           break;
  709.         }
  710.  
  711.       check_for_event ();
  712.  
  713.       gen ("jmp", labname1, "  ");    /* back to top of loop */
  714.  
  715.       make_label (labname3, lablabel3);
  716.       gen (lablabel3, "  ", "  ");
  717.  
  718.       /* POP the step & limit from stack */
  719.       if (countertype == shorttype)
  720.         gen ("addq", "#4", "sp");
  721.       else
  722.         gen ("addq", "#8", "sp");
  723.  
  724.       change (cx1, "bgt", labname3, "  ");
  725.       change (cx2, "blt", labname3, "  ");
  726.  
  727.       /* EXIT FOR branch code pointer non-NULL? */
  728.       if (exit_for_cx)
  729.         {
  730.           change (exit_for_cx, "jmp", labname3, "  ");
  731.           exit_for_cx = NULL;
  732.         }
  733.     }
  734.     }
  735. }
  736.  
  737. void on_branch (void)
  738. {
  739.   char numbuf[40];
  740.   char lab[80], lablabel[80];
  741.   int branch;
  742.   int btype;
  743.   long i, opt = 0;
  744.  
  745. /* ON <integer-expression> GOTO | GOSUB <label> | <line> */
  746.  
  747.   btype = expr ();
  748.   if (btype == stringtype)
  749.     _error (4);
  750.   else
  751.     {
  752.       if (make_integer (btype) == shorttype)
  753.     make_long ();        /* on stack */
  754.  
  755.       if (sym != gotosym && sym != gosubsym)
  756.     _error (56);
  757.       else
  758.     {
  759.       branch = sym;        /* GOTO or GOSUB */
  760.  
  761.       do
  762.         {
  763.           insymbol ();
  764.           /* label or line-number? */
  765.           if (sym != ident && sym != shortconst && sym != longconst)
  766.         _error (57);
  767.           else
  768.         {
  769.           if (sym != ident)
  770.             make_label_from_linenum (sym, id);
  771.  
  772.           opt++;
  773.  
  774.           sprintf (numbuf, "#%ld", opt);
  775.           gen ("cmpi.l", numbuf, "(sp)");
  776.           make_label (lab, lablabel);
  777.           gen ("bne.s", lab, "  ");    /* is opt equal to value on stack? */
  778.  
  779.           gen ("addq", "#4", "sp");    /* remove value from stack before branch */
  780.  
  781.           switch (branch)
  782.             {
  783.             case gotosym:
  784.               gen_branch ("jmp", id);
  785.               break;
  786.  
  787.             case gosubsym:
  788.               gen_branch ("jsr", id);
  789.               gen ("nop", "  ", "  ");    /* jump to end of choices */
  790.               option[opt - 1] = curr_code;
  791.               break;
  792.             }
  793.  
  794.           gen (lablabel, "  ", "  ");
  795.         }
  796.  
  797.           insymbol ();
  798.         }
  799.       while (sym == comma);
  800.     }
  801.  
  802.       /* if ON..GOSUB -> branch to end of all choices after GOSUB */
  803.       if (branch == gosubsym && opt > 0)
  804.     for (i = 0; i < opt; i++)
  805.       change (option[i], "jmp", lab, "  ");
  806.     }
  807. }
  808.  
  809. void block_statement (void)
  810. {
  811. /*
  812.    ** BLOCK..END BLOCK
  813.  */
  814.   insymbol ();
  815.   while (sym == endofline)
  816.     insymbol ();        /* skip blank line(s) */
  817.  
  818.   while ((sym != endsym) && (!end_of_source))
  819.     statement ();
  820.  
  821.   if (sym != endsym)
  822.     _error (80);
  823.   else
  824.     {
  825.       insymbol ();
  826.       if (sym != blocksym)
  827.     _error (80);
  828.       else
  829.     insymbol ();
  830.     }
  831. }
  832.