/* This subroutine provides the interface for the yacc yyparse subroutine.
 * It process the operand and generates the object code.
 *
 * $Log: proper.c,v $
 * Revision 1.2  1997/06/13 08:37:40  david
 * ANSI-fied.
 *
 * Revision 1.1  1997/06/04 02:59:13  david
 * Initial revision
 *
 */

#include <stdio.h>
#include <ctype.h>
#include "xasm.h"

static char *RcsId = "$Id: proper.c,v 1.2 1997/06/13 08:37:40 david Exp $";

char fwdref;
char parse_flag; /* Flag determines if 'parse' entered iteratively */

char *ptr; /* Pointer used by yacc parser (yyparse) */
char objcode[BUFSIZ]; /* Object code generated */
char *labels, *opcodes, *operands; /* For use in psuedo operations */
char *lptrs;
static int slen; /* Length of string */

char *or();

char *proper( char *label, char *opcode, char *operand, char *lptr )
{
char input_line[80]; /* Combination of opcode & operand */

labels = label;
opcodes = opcode;
operands = operand;
lptrs = lptr;

*objcode = '\0'; /* Reset Object Code generated */
slen = 0; /* Reset string length */
parse_flag = 0; /* Reset iterative parse flag */

upper( opcode );
sprintf( input_line, "%s %s", opcode, operand );
ptr = input_line; /* Initialize parser to first of operand */

yyrestart( NULL );

yyparse(); /* Call the yacc parser for the current operand */
/*
   {
   fprintf( stderr, "Error parsing line. Aborting.\n" );
   exit( 1 );
   }
*/

if ( slen == 0 ) /* If no string length */
   locinc += (strlen( objcode ) >> 1); /* Amount to increment loc */
 else
   locinc += slen; /* String length to increment loc */

#if DEBUG
fprintf( stderr, "Leaving 'proper'.\n\n" );
#endif
return( objcode );
}

/* DATA - Put object code + data together and put into objcode */
void data( int objc, int data )
{
sprintf( objcode, "%02x%02x", objc, data & 0xff );
upper( objcode );
if ( ( data & 0xfffff000 ) != 0 )
   xerror( "Data too big to fit into 8 bits" );
}

/* CALL - Form object code & address for CALL */
void call( int addr )
{
sprintf( objcode, "%02x%02x",
   ((addr & 0x700) >> 3) | 0x14, (addr & 0xff) ); /* Get Page, offset */
upper( objcode );

if ( ( addr & 0xfffff000 ) != 0 )
   xerror( "Address to big to fit into 4k" );
}

/* JMP - Form object code & address for JMP */
void jmp( int addr )
{
sprintf( objcode, "%02x%02x",
   ((addr & 0x700) >> 3) | 0x04, (addr & 0xff) ); /* Get Page, offset */
upper( objcode );

if ( ( addr & 0xfffff000 ) != 0 )
   xerror( "Address to big to fit into 4k" );
}

/* Forms and checks the address part of the object code */
void addr( int opcode, int address )
{
register int temp = address & 0xff;

sprintf( objcode, "%02x%02x", opcode, temp );
upper( objcode );

if ( temp != 0xff )
   {
   if ( page( loc ) != page( address ) )
      xerror( "Jump to Off-Page Address" );
   }
 else /* End of page check */
   if ( page( loc ) != ( page( address ) + 1 ) )
      xerror( "Jump to Off-Page Address" );
}

/* Returns the page of the address */
int page( int addr )
{
return ( (addr & 0x700) >> 8);
}

/* This subroutine takes the two inputs and "OR"s them together, then it
   makes an Upper Case Hex string and returns a pointer to it.
*/
char *or( int opcode, int orcode )
{
static char retcode[10];
	
sprintf( retcode, "%02x", opcode | orcode);
upper( retcode );
return retcode;
}

/* Form string */
void formstr( char *ptr )
{
char temp[3];

while ( *ptr )
   {
   sprintf( temp, "%02x", *ptr++ );
   upper( temp );
   strcat( objcode, temp );
   slen++; /* Increment string length */
   }
}
