/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
*  4-Dec-85 | [1.124] Created change log
*  4-Dec-85 | [1.124] Added full command line scanner; added -pr64 switch
*  5-Dec-85 | [1.136] Moved file opening to after processing so all switches
*           | seen and processed first.  Make provision for piping, but
*           | don't handle it for now.
*  6-Dec-85 | [1.145] Open list device in binary mode
*  6-Dec-85 | [1.146] Added -dump switch, suppress memory dump unless
*           | specified 
*  6-Dec-85 | [1.146] Added -test64
* 24-Nov-91 | [1.177] <jmn> converted to C 6.0
* 24-Nov-91 | [1.177] <jmn> memory.h => automem.h
*  4-Dec-91 | [1.233] <jmn> added -wsym switch, speed up cases where we are
*           | not debugging and making two passes
*  7-Dec-91 | [1.255] <jmn> use _splitpath/_makepath to handle filenames
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <boolean.h>
#include <automem.h>
#include <string.h>

#include <err.h>
#include <ste.h>
#include <sym.h>
#include <pass1.h>
#include <pass2.h>
#include <error.h>
#include <operand.h>
#include <list.h>
#include <pr.h>
#include <printers.h>

FILE * reader;
int line_number;		/* Line number of input */
char line[81];
FILE * punch;

FILE * listing;

char filename[_MAX_PATH];
char listname[_MAX_PATH];
char punchname[_MAX_PATH];

int dot;
int star;
int sdot;
unsigned maxdot;	/* largest value 'dot' ever had */
unsigned litoffset;
unsigned litpool;	/* Start of literal pool */
boolean pr64 = false;
boolean dump = false;
boolean debug = false;
boolean debug_sym = false;
boolean test_pr64 = false;
boolean checksym = false;
unsigned start;
boolean saw_end;
extern int punched;

/****************************************************************************
*                                cmdline_help
* Effect: 
*       Prints out command line help
****************************************************************************/

cmdline_help()
    {
     fprintf(stderr,"autocoder [options] filename\n");
     fprintf(stderr,"     Options are:\n");
     fprintf(stderr,"       -debug (-d)  enable verbose debug mode\n");
     fprintf(stderr,"       -dump        dump memory on console at end\n");
     fprintf(stderr,"       -pr64        enable full character set mode to printer\n");
     fprintf(stderr,"       -dsym        debug symbol table stuff\n");
     fprintf(stderr,"       -test64      enables .ts directives in .cfg file\n");
    }

/****************************************************************************
*                                  openfiles
* Inputs:
*       char * name: Base file name
* Result: boolean
*       true if open succeeded
*	false if open failed
* Effect: 
*       Opens the input, output and listing files
****************************************************************************/

boolean openfiles(char * name)
    {
     char * p;
     char basename[80];
     char drive[_MAX_DRIVE];
     char dir[_MAX_DIR];
     char fname[_MAX_FNAME];
     char ext[_MAX_EXT];
     char fullname[_MAX_PATH];

     check_sym("openfiles: entry");

     _splitpath(name,drive,dir,fname,ext);
     
     check_sym("openfiles: prior to open reader");
     _makepath(filename,drive,dir,fname,ext);

     reader = fopen(filename,"r");
     if(reader == NULL && strlen(ext) == 0)
        { /* try default */
	 _makepath(fullname,drive,dir,fname,"aut");
	 reader = fopen(fullname,"r");
	} /* try default */

     if(reader==NULL) 
        { /* no file */
	 fprintf(stderr,"Couldn't open input file %s\n",filename);
	 return false;
	} /* no file */
     line_number = 0;

     /* Now open the listing file */

     check_sym("openfiles: prior to open listing");

     _makepath(listname,"","",fname,"lst");
     listing = fopen(listname,"wb");

     if(listing==NULL)
        { /* failed */
	 fprintf(stderr,"Couldn't re-open listing file %s\n",listname);
	 return false;
	} /* failed */

     check_sym("openfiles: prior to dev_init");

     if(!dev_init(listing,test_pr64))
        { /* list init failed */
	 fprintf(stderr,"Couldn't initialize listing file %s\n",fname);
	 return false;
	} /* list init failed */

     check_sym("openfiles: prior to init_listing");

     init_listing();

     /* Now open the punch file */

     check_sym("openfiles: prior to open punch");

     _makepath(punchname,"","",fname,"cdr");
     punch = fopen(punchname,"w");
     if(punch==NULL)
        { /* failed */
	 fprintf(stderr,"Couldn't open punch file %s\n",fname);
	 return false;
	} /* failed */

     check_sym("openfiles: completed");
     return true;
    }

/****************************************************************************
*                                    main
* Inputs:
*       int argc: Count of arguments
*	char * argv[]: Pointers to arguments
* Effect: 
*       Runs autocoder assembler
****************************************************************************/

main(int argc,char * argv[])
    {
     int i;
     int fileindex= -1;

   /* process the keywords */

   i = 0;

   while ((++i)<argc)
      { /* process args */

/* -debug */

	if(stricmp(argv[i],"-d") == 0 || stricmp(argv[i],"-debug") == 0)
	   { /* -debug */
	    debug = true;
	    checksym = true;
	    continue;
	   } /* -debug */

/* -dsym */
	if(stricmp(argv[i],"-dsym") == 0)
	   { /* -dump */
	    debug_sym = true;
	    checksym = true;
	    continue;
	   } /* -dump */
/* -wsym */
	if(stricmp(argv[i],"-wsym") == 0)
	   { /* -wsym */
	    checksym = true;
	    continue;
	   } /* -wsym */

/* -dump */
	if(stricmp(argv[i],"-dump") == 0)
	   { /* -dump */
	    dump = true;
	    continue;
	   } /* -dump */

/* -help */
	if ((stricmp(argv[i],"-help") == 0) || (stricmp(argv[i],"?") == 0))
	   { /* -help */
	    cmdline_help();
	    return 0;
	   } /* -help */

/* -pr64 */

	if(stricmp(argv[i],"-pr64") == 0)
	   { /* -pr64 */
	    pr64 = true;
	    continue;
	   } /* -pr64 */

/* -test64 */
	if(stricmp(argv[i],"-test64") == 0)
	   { /* -test64 */
	    test_pr64 = true;
	    continue;
	   } /* -test64 */

/* - */
	if( stricmp(argv[i],"-") == 0) 
	   continue;

/* filename */

	if(argv[i][0] != '-')
	   { /* not a switch */
	    
	    fileindex = i;
	    continue;
	   } /* not a switch */

/* we don't know what this is */

	fprintf(stderr,"Unknown option \"%s\"\n",argv[i]);
	fprintf(stderr,"Use -help for help\n");
	return 0;

      } /* process args */

   check_sym("main: args checked");

   if(fileindex > 0)
      { /* real filename */
       
       if (!openfiles(argv[fileindex])) 
	  return 1;
      } /* real filename */
   else
      { /* pipe in */
       fprintf(stderr,"No filename specified\n");
       return 1;
      } /* pipe in */

     for(i=0;i<16000;i++) memory[i] = '\0';

     /* Initialize symbol table */

     check_sym("main: prior to init_symbols");

     init_symbols();

     litpool = -1;	/* No literal pool assigned */
     maxdot = 0;	/* maxdot starts at 0 */
     start = -1;	/* Illegal address */
     saw_end = false;

     check_sym("main: prior to pass1");
     pass1();
     check_sym("main: after pass1");

     if(!saw_end)
     	error(err_opcode,"No END statement seen");

     if(debug)
     	printf("End of pass 1: maxdot = %d, dot = %d\n",maxdot, dot);
     litpool = max(maxdot,dot);	/* literal pool assigned */
     resolve_lits(line_number,"End of pass 1");

     /* P A S S   2   P R O C E S S I N G */

     rewind(reader);
     line_number = 0;
     litpool = dot;
     litoffset = 0;	/* unresolved literals computed to new base 0 */
     litpool = -1;	/* reset it */
     maxdot = 0;

     check_sym("main: prior to pass2");
     pass2();
     check_sym("main: after pass2");

     litpool = dot;

     resolve_lits(line_number,"End of pass 2");

     check_sym("main: after resolve_lits");

     dump_lits(line_number,"End of pass 2");	/* Dump any remaining literals not handled by LIT ops */

     list_syms();
     if(dump)
     	dump_memory();

     punch_cards();

     fclose(reader);

     dev_final();

     dev_close();

     fclose(punch);

     fprintf(stderr,"Punched %d card%s\n",punched,(punched == 1 ? "" : "s"));

    }


/****************************************************************************
*                                  readline
* Effect: 
*       Reads a line of input to 'line'
****************************************************************************/

void readline()
    {
     int i;
     fgets(line,81,reader);
     i = strlen(line);
     if(line[i-1] == '\n') 
	i--;
     for(;i<81;i++) 
	line[i] = ' ';
     line_number++;
    }
