/*  This file is part of GNU bc.

    Copyright (C) 1991-1994, 1997, 2006 Free Software Foundation, Inc.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License , or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to:
      The Free Software Foundation, Inc.
      Foundation, Inc.  51 Franklin Street, Fifth Floor,
      Boston, MA 02110-1301  USA

    You may contact the author by:
       e-mail:  philnelson@acm.org
      us-mail:  Philip A. Nelson
                Computer Science Department, 9062
                Western Washington University
                Bellingham, WA 98226-9062
       
*************************************************************************/

/* load.c:  This code "loads" code into the code segments. */

#include "bcdefs.h"
#include "proto.h"

/* Load variables. */

program_counter load_adr;
char load_str;
char load_const;

/* Initialize the load sequence. */
void
init_load ()
{
  clear_func(0);
  load_adr.pc_func = 0;
  load_adr.pc_addr = 0;
  load_str = FALSE;
  load_const = FALSE;
}

/* addbyte adds one BYTE to the current code segment. */
void
addbyte (thebyte)
     int thebyte;
{
  int prog_addr;
  bc_function *f;
  char *new_body;

  /* If there was an error, don't continue. */
  if (had_error) return;

  /* Calculate the segment and offset. */
  prog_addr = load_adr.pc_addr++;
  f = &functions[load_adr.pc_func];

  if (prog_addr >= f->f_body_size)
    {
      f->f_body_size *= 2;
      new_body = (char *) bc_malloc (f->f_body_size);
      memcpy(new_body, f->f_body, f->f_body_size/2);
      free (f->f_body);
      f->f_body = new_body;
    }

  /* Store the thebyte. */
  f->f_body[prog_addr] = (char) (thebyte & 0xff);
  f->f_code_size++;
}


/* Define a label LAB to be the current program counter. */

void
def_label (lab)
     long lab;
{
  bc_label_group *temp;
  int group, offset, func;
    
  /* Get things ready. */
  group = lab >> BC_LABEL_LOG;
  offset = lab % BC_LABEL_GROUP;
  func = load_adr.pc_func;
  
  /* Make sure there is at least one label group. */
  if (functions[func].f_label == NULL)
    {
      functions[func].f_label = 
	(bc_label_group *) bc_malloc (sizeof(bc_label_group));
      functions[func].f_label->l_next = NULL;
    }

  /* Add the label group. */
  temp = functions[func].f_label;
  while (group > 0)
    {
      if (temp->l_next == NULL)
	{
	  temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
	  temp->l_next->l_next = NULL;
	}
      temp = temp->l_next;
      group --;
    }

  /* Define it! */
  temp->l_adrs [offset] = load_adr.pc_addr;
}

/* Several instructions have integers in the code.  They
   are all known to be legal longs.  So, no error code
   is added.  STR is the pointer to the load string and
   must be moved to the last non-digit character. */

long
long_val (str)
     const char **str;
{ int  val = 0;
  char neg = FALSE;

  if (**str == '-')
    {
      neg = TRUE;
      (*str)++;
    }
  while (isdigit((int)(**str))) 
    val = val*10 + *(*str)++ - '0';

  if (neg)
    return -val;
  else
    return val;
}


/* load_code loads the CODE into the machine. */

void
load_code (code)
     const char *code;
{
  const char *str;
  long  ap_name;	/* auto or parameter name. */
  long  label_no;
  long  vaf_name;	/* variable, array or function number. */
  long  func;
  static program_counter save_adr;

  /* Initialize. */
  str = code;
   
  /* Scan the code. */
  while (*str != 0)
    {
      /* If there was an error, don't continue. */
      if (had_error) return;

      if (load_str)
	{
	  if (*str == '"') load_str = FALSE;
	  addbyte (*str++);
	}
      else
	if (load_const)
	  {
	    if (*str == '\n') 
	      str++;
	    else
	      {
		if (*str == ':')
		  {
		    load_const = FALSE;
		    addbyte (*str++);
		  }
		else
		  if (*str == '.')
		    addbyte (*str++);
		  else
		    if (*str >= 'A')
		      addbyte (*str++ + 10 - 'A');
		    else
		      addbyte (*str++ - '0');
	      }
	  }
	else
	  {
	    switch (*str)
	      {

	      case '"':	/* Starts a string. */
		load_str = TRUE;
		break;

	      case 'N': /* A label */
		str++;
		label_no = long_val (&str);
		def_label (label_no);
		break;

	      case 'B':  /* Branch to label. */
	      case 'J':  /* Jump to label. */
	      case 'Z':  /* Branch Zero to label. */
		addbyte(*str++);
		label_no = long_val (&str);
		if (label_no > 65535L)
		  {  /* Better message? */
		    fprintf (stderr,"Program too big.\n");
		    exit(1);
		  }
		addbyte ( (char) (label_no & 0xFF));
		addbyte ( (char) (label_no >> 8));
		break;

	      case 'F':  /* A function, get the name and initialize it. */
		str++;
		func = long_val (&str);
		clear_func (func);
#if DEBUG > 2
		printf ("Loading function number %d\n", func);
#endif
		/* get the parameters */
		while (*str++ != '.')
		  {
		    if (*str == '.')
		      {
			str++;
			break;
		      }
		    if (*str == '*')
		      {
			str++;
			ap_name = long_val (&str);
#if DEBUG > 2
			printf ("var parameter number %d\n", ap_name);
#endif
			functions[(int)func].f_params = 
			  nextarg (functions[(int)func].f_params, ap_name,
				   TRUE);
		      }
		    else
		      {
			ap_name = long_val (&str);
#if DEBUG > 2
			printf ("parameter number %d\n", ap_name);
#endif
			functions[(int)func].f_params = 
			  nextarg (functions[(int)func].f_params, ap_name,
				   FALSE);
		      }
		  }

		/* get the auto vars */
		while (*str != '[')
		  {
		    if (*str == ',') str++;
		    ap_name = long_val (&str);
#if DEBUG > 2
		    printf ("auto number %d\n", ap_name);
#endif
		    functions[(int)func].f_autos = 
		      nextarg (functions[(int)func].f_autos, ap_name, FALSE);
		  }
		save_adr = load_adr;
		load_adr.pc_func = func;
		load_adr.pc_addr = 0;
		break;
		
	      case ']':  /* A function end */
		functions[load_adr.pc_func].f_defined = TRUE;
		load_adr = save_adr;
		break;

	      case 'C':  /* Call a function. */
		addbyte (*str++);
		func = long_val (&str);
		if (func < 128)
		  addbyte ( (char) func);
		else
		  {
		    addbyte (((func >> 8) & 0xff) | 0x80);
		    addbyte (func & 0xff);
		  }
		if (*str == ',') str++;
		while (*str != ':')
		  addbyte (*str++);
		addbyte (':');
		break;
		
	      case 'c':  /* Call a special function. */
		addbyte (*str++);
		addbyte (*str);
		break;

	      case 'K':  /* A constant.... may have an "F" in it. */
		addbyte (*str);
		load_const = TRUE;
		break;

	      case 'd':  /* Decrement. */
	      case 'i':  /* Increment. */
	      case 'l':  /* Load. */
	      case 's':  /* Store. */
	      case 'A':  /* Array Increment */
	      case 'M':  /* Array Decrement */
	      case 'L':  /* Array Load */
	      case 'S':  /* Array Store */
		addbyte (*str++);
		vaf_name = long_val (&str);
		if (vaf_name < 128)
		  addbyte (vaf_name);
		else
		  {
		    addbyte (((vaf_name >> 8) & 0xff) | 0x80);
		    addbyte (vaf_name & 0xff);
		  }
		break;

	      case '@':  /* A command! */
		switch (*(++str))
		  {
		  case 'i':
		    init_load ();
		    break;
		  case 'r':
		    execute ();
		    break;
		  } 
		break;

	      case '\n':  /* Ignore the newlines */
		break;
		
	      default:   /* Anything else */
		addbyte (*str);	   
	      }
	    str++;
	  }
    }
}
