
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
#include "regs.h"
#include "trace.h"
#include "lights.h"
#include "io.h"
#include "chan.h"
#include "console.h"
#include "screen.h"
#include "binloader.h"

extern char errview[5][81];
extern int errno;

#ifdef NEEDSTRTOLL
t_int64
strtoll (char *start, char **end, int base)
{
   t_int64 ret = 0;
   int sign;

   while (isspace (*start)) start++;
   if (*start == '+')
   {
      sign = +1;
      start++;
   }
   else if (*start == '-')
   {
      sign = -1;
      start++;
   }

   while (*start)
   {
      if (base == 8)
      {
	 if (*start >= '0' && *start < '8')
	 {
	    ret = ret << 3 | (*start - '0');
	 }
	 else break;
      }
      else
      {
         if (isdigit (*start))
	 {
	    ret = (ret * 10) + (*start - '0');
	 }
	 else break;
      }
      start++;
   }
   if (end != NULL) *end = start;
   if (sign < 0) ret = -ret;
   return (ret);
}
#endif

int
binloader (char *file, int loadpt)
{
   FILE *fd;
   FILE *lfd;
   int loadaddr = 0200;
   int curraddr = 0200;
   char inbuf[82];

#ifdef DEBUGLOADER
   lfd = fopen ("load.log", "w");
   fprintf (lfd, "binloader: file = '%s', loadpd = %d\n", file, loadpt);
#endif

   if (loadpt > 0)
   {
      loadaddr = loadpt;
      curraddr = loadpt;
   }

   if ((fd = fopen (file, "r")) == NULL)
   {
      sprintf (errview[0], "binloader: open failed: %s",
	       strerror(errno));
      sprintf (errview[1], "filename: %s", file);
      iochk = 1;
      run = 0;
#ifdef DEBUGLOADER
      fprintf (lfd, "error: %s\n", errview[0]);
      fprintf (lfd, "       %s\n", errview[1]);
      fclose (lfd);
#endif
      return (-1);
   }

   while (fgets (inbuf, sizeof(inbuf), fd))
   {
      char *op = inbuf;
      int i;

      for (i = 0; i < 5; i++)
      {
	 char otag;
	 char item[16];
	 union 
	 {
	    uint32 ldata[2];
	    t_int64 lldata;
	 } d;

	 otag = *op++;
	 strncpy (item, op, 12);
	 item[12] = '\0';
	 d.lldata = strtoll (item, NULL, 8);

#ifdef DEBUGLOADER
	 fprintf (lfd, "loadaddr = %5.5o, curraddr = %5.5o\n",
		  loadaddr, curraddr);
	 fprintf (lfd, "otag = %c, item = %s\n", otag, item);
	 fprintf (lfd, "d.ldata = %2.2o %11.11o\n", d.ldata[MSL], d.ldata[LSL]);
	 fprintf (lfd, "d.lldata = %12o\n", d.lldata);
#endif

         switch (otag)
	 {
	 case ORG_TAG:
	    curraddr = loadaddr = d.ldata[LSL] & 077777;
	    break;
	 case BSS_TAG:
	    curraddr += d.ldata[LSL] & 077777;
	    break;
	 case DATA_TAG:
	 case ABSINST_TAG:
	    memh[curraddr] = ((d.ldata[MSL] << 4) & SIGN)
			    | (d.ldata[MSL] & HMSK);
	    meml[curraddr] = d.ldata[LSL];
	    curraddr++;
	    break;
	 case RELINST_TAG:
	    memh[curraddr] = ((d.ldata[MSL] << 4) & SIGN) 
			    | (d.ldata[MSL] & HMSK);
	    meml[curraddr] = d.ldata[LSL] + loadaddr;
	    curraddr++;
	    break;
	 case ABSENTRY_TAG:
	    srh = 00; /* TRA   addr */
	    srl = 002000000000 | d.ldata[LSL];
	    break;
	 case RELENTRY_TAG:
	    srh = 00; /* TRA   addr */
	    srl = 002000000000 | (d.ldata[LSL] + loadaddr);
	    break;
	 default: ;
	 }
	 op += 12;
      }
   }

#ifdef DEBUGLOADER
   fclose (lfd);
#endif
   fclose (fd);
}
