/*
 * This file belongs to FreeMiNT. It's not in the original MiNT 1.12
 * distribution. See the file CHANGES for a detailed log of changes.
 * 
 * 
 * Copyright 2000 Frank Naumann <fnaumann@freemint.de>
 * All rights reserved.
 * 
 * This file 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, or (at your option)
 * any later version.
 * 
 * This file 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; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 * 
 * begin:	2000-01-01
 * last change:	2000-03-07
 * 
 * Author:	Frank Naumann <fnaumann@freemint.de>
 * 
 * Please send suggestions, patches or bug reports to me or
 * the MiNT mailing list.
 * 
 * 
 * changes since last version:
 * 
 * known bugs:
 * 
 * todo:
 * 
 * optimizations:
 * 
 */

# include "list.h"
# include "generate.h"

# include <stdlib.h>
# include <stdio.h>
# include <time.h>


# ifdef __MINT__
long _stksize = 64 * 1024;
# endif

int errors = 0;

/* from parser */
int yyparse (void);

/* from parser */
extern FILE *yyin, *yyout;


static void
print_head (FILE *out, const char *myname)
{
	time_t t = time (NULL);
	
	fprintf (out, "/*\n * %s, %s *\n", myname, ctime (&t));
	fprintf (out,
		" * DO NOT EDIT - this file is automatically generated\n"
		" */\n"
	);
	fprintf (out, "\n");
	
	fprintf (out,
		"/*                                                                      \n"
		" * This file belongs to FreeMiNT. It's not in the original MiNT 1.12    \n"
		" * distribution. See the file CHANGES for a detailed log of changes.    \n"
		" *                                                                      \n"
		" *                                                                      \n"
		" * Copyright 2000 Frank Naumann <fnaumann@freemint.de>                  \n"
		" * All rights reserved.                                                 \n"
		" *                                                                      \n"
		" * This file is free software; you can redistribute it and/or modify    \n"
		" * it under the terms of the GNU General Public License as published by \n"
		" * the Free Software Foundation; either version 2, or (at your option)  \n"
		" * any later version.                                                   \n"
		" *                                                                      \n"
		" * This file is distributed in the hope that it will be useful,         \n"
		" * but WITHOUT ANY WARRANTY; without even the implied warranty of       \n"
		" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        \n"
		" * GNU General Public License for more details.                         \n"
		" *                                                                      \n"
		" * You should have received a copy of the GNU General Public License    \n"
		" * along with this program; if not, write to the Free Software          \n"
		" * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            \n"
		" *                                                                      \n"
		" */                                                                     \n"
	);
	fprintf (out, "\n");
}

static void
usage (void)
{
	fprintf (stderr, "Usage: \n");
	exit (2);
}

int
main (int argc, char **argv)
{
	const char *myname;
	
	myname = *argv++;
	
# if 0
	while (*argv)
	{
		if (!strcmp (*argv, "-o"))
		{
			argv++;
			if (*argv == 0)
			{
				fprintf(stderr, "missing argument to -o\n");
				usage ();
			}
			
			f = fopen (*argv, "wt");
			if (!f)
				perror (*argv);
			else
				outfile = f;
			
			argv++;
		}
		else
		{
			if (**argv == '-')
			{
				fprintf (stderr, "unknown option: %s\n", *argv);
				usage ();
			}
		}
	}
# endif
	
	
	if (*argv == 0)
	{
# if YYDEBUG != 0
		yydebug = 1;
# endif
		yyparse ();
	}
	else
	{
		while (*argv)
		{
			FILE *f;
			
			f = fopen (*argv, "rt");
			if (f)
			{
				yyin = f;
				yyparse ();
				
				fclose (f);
			}
			else
			{
				perror (*argv);
				exit (1);
			}
			
			argv++;
		}
	}
	
	if (!errors)
	{
		FILE *f;
		
		// check_tab ();
		
		
		f = fopen ("syscalls.h", "w");
		if (!f)
		{
			perror ("syscalls.h");
			exit (1);
		}
		
		print_head (f, myname);
		fprintf (f, "# ifndef _syscalls_h\n# define _syscalls_h\n\n");
		fprintf (f, "# include \"mint/mint.h\"\n");
		fprintf (f, "# include \"mint/mem.h\"\n");
		fprintf (f, "\n");
		fprintf (f, "\n");
		fprintf (f, "typedef struct systab SYSTAB;\n");
		fprintf (f, "struct systab\n");
		fprintf (f, "{\n");
		fprintf (f, "\tlong _cdecl (*call)();\n");
		fprintf (f, "\tushort nr_of_args;\n");
		fprintf (f, "\tushort size_of_args;\n");
		fprintf (f, "};\n");
		fprintf (f, "\n");
		fprintf (f, "\n");
		fprintf (f, "extern SYSTAB dos_tab [];\n");
		fprintf (f, "extern SYSTAB bios_tab [];\n");
		fprintf (f, "extern SYSTAB xbios_tab [];\n");
		fprintf (f, "\n");
		fprintf (f, "extern Func dos_tab_old [];\n");
		fprintf (f, "extern Func bios_tab_old [];\n");
		fprintf (f, "extern Func xbios_tab_old [];\n");
		fprintf (f, "\n");
		fprintf (f, "extern ushort dos_max;\n");
		fprintf (f, "extern ushort bios_max;\n");
		fprintf (f, "extern ushort xbios_max;\n");
		fprintf (f, "\n");
		
		fprintf (f, "\n/*\n * DOS syscalls argument structs\n */\n");
		generate_struct (f, DOS);
		
		fprintf (f, "\n/*\n * BIOS syscalls argument structs\n */\n");
		generate_struct (f, BIOS);
		
		fprintf (f, "\n/*\n * XBIOS syscalls argument structs\n */\n");
		generate_struct (f, XBIOS);
		
		fprintf (f, "\n/*\n * DOS syscalls prototypes\n */\n");
		generate_proto (f, DOS);
		
		fprintf (f, "\n/*\n * BIOS syscalls prototypes\n */\n");
		generate_proto (f, BIOS);
		
		fprintf (f, "\n/*\n * XBIOS syscalls prototypes\n */\n");
		generate_proto (f, XBIOS);
		
		fprintf (f, "\n# endif /* _syscalls_h */\n");
		fclose (f);
		
		
		f = fopen ("syscalls.c", "w");
		if (!f)
		{
			perror ("syscalls.c");
			exit (1);
		}
		
		print_head (f, myname);
		fprintf (f, "# include \"syscalls.h\"\n\n");
		
		fprintf (f, "\n");
		fprintf (f, "static long\n");
		fprintf (f, "sys_enosys (PROC *p, void *v)\n");
		fprintf (f, "{\n");
		fprintf (f, "\treturn ENOSYS;\n");
		fprintf (f, "}\n");
		fprintf (f, "\n");
		
		fprintf (f, "\n/*\n * DOS syscall table\n */\n");
		generate_tab (f, DOS, "dos");
		
		fprintf (f, "\n/*\n * BIOS syscall table\n */\n");
		generate_tab (f, BIOS, "bios");
		
		fprintf (f, "\n/*\n * XBIOS syscall table\n */\n");
		generate_tab (f, XBIOS, "xbios");
		
		fclose (f);
		
		
		f = fopen ("syscalls_old.c", "w");
		if (!f)
		{
			perror ("syscalls_old.c");
			exit (1);
		}
		
		print_head (f, myname);
		fprintf (f, "# include \"syscalls.h\"\n");
		fprintf (f, "\n");
		fprintf (f, "# include \"mint/proc.h\"\n");
		fprintf (f, "\n");
		fprintf (f, "\n");
		fprintf (f, "static long\n");
		fprintf (f, "old_enosys (void)\n");
		fprintf (f, "{\n");
		fprintf (f, "\treturn ENOSYS;\n");
		fprintf (f, "}\n");
		fprintf (f, "\n");
		
		fprintf (f, "\n/*\n * DOS old syscall wrapper & table\n */\n");
		generate_wrapper (f, DOS, "dos");
		
		fprintf (f, "\n/*\n * BIOS old syscall wrapper & table\n */\n");
		generate_wrapper (f, BIOS, "bios");
		
		//not used
		//fprintf (f, "\n/*\n * XBIOS old syscall wrapper & table\n */\n");
		//generate_wrapper (f, XBIOS, "xbios");
		
		fclose (f);
	}
	
	return errors;
}
