/* bob.c - the main routine */
/*
        Copyright (c) 1991, by David Michael Betz
        All rights reserved.

        Alterations and additions, 1994, by G.C.Wraith
*/

#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include "bob.h"

/* Revision history

        1.0     08/15/91        Initial version for DDJ article.
        1.1     08/20/91        Fixed do_for to allow null statements.
        1.2     08/28/91        Fixed problem with newobject().
        1.3     09/27/91        Fixed a bug in compact_vector().
        1.4     10/09/91        Reworked for Windows 3 - part 1.
        1.5     10/12/91        Various bug fixes.  Added gc().
        1.5a    22/01/94        RISC OS version (GCW) -> ArmBob

        
*/
/* Start with clear screen for RISC OS */

#define BANNER  "Bob v1.5 - Copyright (c) 1991, by David Betz" 
#define QSIZE 32000   /* buffer for preprocessed file */
#define SYNTAX "Usage: Bob [-help|-debug|-trace] filename\n"


/* global variables */
jmp_buf error_trap;
char **bobargv;
int bobargc;
int q[QSIZE];
int qgetc(void *p);
int qout, qin;

#ifdef RISCOS
/* throwback */
int errorline;
char errormesg[100];
char errorfile[256];
#endif

/* external variables */
extern int decode,trace;
extern VALUE symbols;
extern VALUE stdin_iostream;
extern VALUE stdout_iostream;
extern VALUE stderr_iostream;

#ifdef RISCOS
extern int w_task;         
extern void w_closedown(void);
extern void w_report(char *);
extern int Taskwin_query(void);
extern void preprocess(FILE *source);
#endif

/* forward declarations */
#ifdef __STDC__
/* static void compile_file(char *); */
int nonblank(char *n);
#ifndef RISCOS
static int loadproj(char *);
#endif
static void add_file(char *,FILE *,VALUE *);
#endif

/* main - the main routine */
int main(int argc,char *argv[])
{
    char fullname[256];
    int i;
#ifndef RISCOS
    int proj;


    /* display the banner - suppressed for RISC OS  */
    osputs(BANNER);
    osputs("\n");
#else  
    w_task = 0;    /* not a wimp task yet */
#endif
#ifndef RISCOS 
    proj = 0;      /* not a project is default */
#endif
    /* initialize */
    initialize(SMAX);
    init_compiler();
    bobargc = argc - 1;
    bobargv = argv + 1;

    /* setup the standard i/o streams */
    add_file("stdin",stdin,&stdin_iostream);
    add_file("stdout",stdout,&stdout_iostream);
    add_file("stderr",stderr,&stderr_iostream);

    /* load and execute some code */
    if (argc < 2)
       { printf(SYNTAX);
         return (1);}
    i = 1;
    while (argv[i][0] == '-')
       {
        switch (argv[i][1])
        {
#ifndef RISCOS
         case 'p':
            proj = 1;
            break;
#endif
         case 'd':
            decode = 1;
            break;
         case 't':
            trace = 1;
            break;
          case 'h':
            printf(SYNTAX);
            return(1);
            break;
         default:
            printf("Unknown flag %s\n",argv[i]);
            return(1);
            break;
         }
        i++;
       }
    if (i>=argc)
        {
          printf(SYNTAX);
          return (1);
        }
    strcpy(fullname,argv[i]);
#ifndef RISCOS
    switch (proj!=0)
    {
     case TRUE:
        if (!loadproj(fullname))
             {printf("Error: Cannot open file %s\n",fullname);
              return(1);}
        break;
     default:
        compile_file(fullname);
        break;
    }
#else
    compile_file(fullname);
#endif
    if (!execute("main"))
         return(1);
    return(0);
}

#ifndef RISCOS
/* load a project file */
static int loadproj(char *projfile)
{
 FILE *ifp;
 char name[256];
 int ok;
 int c,i;
 ok = ((ifp = fopen(projfile,"r"))!=NULL);
 i = 0;
 if (ok)
     {
      while ((c = fgetc(ifp)) != EOF)
       if (c != '\n')
          name[i++] = c;
       else
         {
          name[i] = '\0';
          i = 0;
          if (nonblank(name))
            compile_file(name);
         }
      fclose(ifp);
      }
return(ok);
}

/* comment lines in project files start with | */
int nonblank(char *n)
{
 int i;
 i = 0;
 while (n[i] == ' ') i++;
 return (n[i] != '\0' && n[i] != '|');
}
#endif

int qgetc(void *p)
{
  return ( q[qout++] );
 }

static void initq(void)
{
  int  i;
  for ( i = qout = qin = 0; i < QSIZE; q[i++] = EOF);
}

/* compile_file - compile definitions in a file */
void compile_file(char *name)
{
    FILE *ifp;
    if ((ifp = fopen(name,"r")) != NULL) {
        strcpy(errorfile,name);
        initq();
        preprocess(ifp);
        compile_definitions(&qgetc,ifp);
        fclose(ifp);
    }
    else printf("Cannot open file %s\n",name);
}

/* info - display progress information 
   replaced by more strongly typed versions
   for RISC OS version  */
void info1(char *fmt,char *a1)
{
    char buf1[100],buf2[100];
    sprintf(buf1,fmt,a1);
    sprintf(buf2,"[ %s ]\n",buf1);
    osputs(buf2);
}

void info2(char *fmt,char *a1,char *a2)
{
    char buf1[100],buf2[100];
    sprintf(buf1,fmt,a1,a2);
    sprintf(buf2,"[ %s ]\n",buf1);
    osputs(buf2);
}

void infodss(char *fmt,int a1,int a2,char *a3,char *a4)
{
    char buf1[100],buf2[100];
    sprintf(buf1,fmt,a1,a2,a3,a4);
    sprintf(buf2,"[ %s ]\n",buf1);
    osputs(buf2);
}

/* error - print an error message and exit 
   replaced by more strongly typed version
   for RISC OS */
void error0(char *fmt)
{
    char buf1[100],buf2[100];
    sprintf(buf1,fmt);
    sprintf(buf2,"Error: %s\n",buf1);
    osputs(buf2);
    w_closedown();
    longjmp(error_trap,1);
}

void error1(char *fmt,char *a1)
{
    char buf1[100],buf2[100];
    sprintf(buf1,fmt,a1);
    sprintf(buf2,"Error: %s\n",buf1);
    osputs(buf2);
    w_closedown();
    longjmp(error_trap,1);
}

void error1d(char *fmt,int a1)
{
    char buf1[100],buf2[100];
    sprintf(buf1,fmt,a1);
    sprintf(buf2,"Error: %s\n",buf1);
    osputs(buf2);
    w_closedown();
    longjmp(error_trap,1);
}

void errorsd(char *fmt,char *a1,int a2)
{
    char buf1[100],buf2[100];
    sprintf(buf1,fmt,a1,a2);
    sprintf(buf2,"Error: %s\n",buf1);
    osputs(buf2);
    w_closedown();
    longjmp(error_trap,1);
}

void osputs(char *str)
{
 if (w_task)
   w_report(str);
 else
  fputs(str,stderr); 
}

/* add_file - add a built-in file */
static void add_file(char *name,FILE *fp,VALUE *pval)
{
    extern IODISPATCH fileio;
    DICT_ENTRY *sym;
    sym = addentry(&symbols,name,ST_SDATA);
    set_iostream(&sym->de_value,newiostream(&fileio,fp));
    *pval = sym->de_value;
}
