/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 27-Nov-85 | [1.20] Created
* 24-Nov-91 | [1.177] <jmn> converted to C6.0
*****************************************************************************/
#include <stdio.h>
#include <boolean.h>
#include <stdlib.h>

#include <ste.h>
#include <err.h>
#include <operands.h>
#include <sym.h>
#include <expr.h>
#include <pass1.h>
#include <operand.h>
#include <error.h>
#include <list.h>

extern int dot;
extern int sdot;
extern char * valstr();

void equop_1(void);
void equop_2(void);


/****************************************************************************
*                                    equop
* Inputs:
*       int opindex: Op table index (irrelevant)
*	int pass: Pass (1 or 2)
* Effect: 
*       Enters the label in the table with the desired value
****************************************************************************/

void equop(int opindex,int pass)
    {
     ste * sy;

     switch(pass)
        {
         case 1: equop_1();
	 	 break;
         case 2: equop_2();
	 	 break;
	}
    }

/****************************************************************************
*                                   equop_1
* Effect: 
*       Installs the EQUed symbl
****************************************************************************/

static void equop_1()
    {
     getlabelval * v;
     ste * sy = NULL;
     unsigned equval;
     int noperands;

     v = getlabel();

     if(v != NULL)
        { /* enter EQU symbol */

	 noperands = scan_operands();
	 if(noperands == 0)
	    { /* no operand */
	     error(err_operand,"EQU operation requires operand");
	     return;
	    } /* no operand */
	 if(noperands > 1)
	    { /* too many operands */
	     error(err_operand,"EQU operation wants only one operand");
	     return;
	    } /* too many operands */
	     
	 if(!expr(operands[0],&equval,false,expr_lit_illegal,1,false))
	    { /* wait for pass 2 */
	     return;
	    } /* wait for pass 2 */
	 
	 sy = enter(v->name,equval);
	} /* enter EQU symbol */
     else
        { /* lose */
	 error(err_operand,"EQU symbol requires label");
	 return;
	} /* lose */

    }

/****************************************************************************
*                                   equop_2
* Effect: 
*       Checks the EQUed symbol
****************************************************************************/

static void equop_2()
    {
     getlabelval * v;
     ste * sy = NULL;
     unsigned equval;
     int noperands;

     check_sym("entering EQU pass 2");

     v = getlabel();

     check_sym("EQU pass 2 got label");

     if(v != NULL)
        { /* enter EQU symbol */

	 noperands = scan_operands();

	 check_sym("EQU pass 2 scanned operands");

	 if(noperands != 1)
	    { /* reported in pass 1 */
	     free(v->name);		/* release string */
	     goto bad_exit;
	    } /* reported in pass 1 */

	 if(!expr(operands[0],&equval,true,expr_lit_illegal,2,false))
	    { /* failed */
	     free(v->name);		/* release string */
	     goto bad_exit;
	    } /* failed */
	     
	 check_sym("EQU pass 2 parsed expr");

	 sy = lookup(v->name);

	 if(sy==NULL)
	    { /* this is defining instance */
	     sy = enter(v->name,equval);
	     check_sym("EQU pass 2 entered new symbol");
	    } /* this is defining instance */
	 else
	    { /* this is pass 2 */     
	     if(sy->val != equval)
	        { /* redef */
		 char msg[80];
		 sprintf(msg,"Symbol '%s'==%s EQUed to %s in pass 2",
	     		v->name,valstr(sy->val),valstr(equval));
		} /* redef */
	     free(v->name);		/* release string */
	    } /* this is pass 2 */
	} /* enter EQU symbol */
     else
        { /* lose */
	 free(v->name);		/* release string */
	 goto bad_exit;
	} /* lose */

     check_sym("finished EQU pass 2 processing");

bad_exit:
     list_addr(equval);
     list_line();
     emit_listing();

     check_sym("finished EQU pass 2 output");


    }
