/* $Id: cc1.c,v 1.12 2012/06/28 13:47:18 vrsieh Exp $ 
 *
 * Copyright (C) 2008-2009 FAUcc Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#if 1


#include <assert.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "declaration.h"
#include "print.h"
#include "simplify.h"
#include "print.h"
#include "arch_i286_gen.h"
#include "arch_i386_gen.h"
#include "cc1.h"

const char *progname;
int opt_O;
const char *opt_O_arg;
enum target opt_b = TARGET_NONE;
int opt_d;
unsigned int opt_f_align_functions = 0;
unsigned int opt_f_sizeof_char = 0;
unsigned int opt_f_sizeof_short_int = 0;
unsigned int opt_f_sizeof_int = 0;
unsigned int opt_f_sizeof_long_int = 0;
unsigned int opt_f_sizeof_long_long_int = 0;
unsigned int opt_f_segment_enable = 0;
const char *infile;
const char *outfile;

extern struct scope *
parse(const char *in);

static __attribute__((noreturn)) void
usage(int retval)
{
	fprintf(stderr, "Usage: %s [-O level] [-d] [-f compile-option] [-m machine-option] -b {i286,i386,...} < infile > outfile\n", progname);
	exit(retval);
}

int
main(int argc, char **argv)
{
	struct scope *s;
	int c;

#if 0
	for (c = 0; c < argc; c++) {
		fprintf(stderr, "%d: '%s'\n", c, argv[c]);
	}
#endif

	/* Get Program Name */
	progname = *argv;

	/* Get Options */
	while ((c = getopt(argc, argv, "O:b:df:m:")) != -1) {
		switch (c) {
		case 'O':
			opt_O = 1;
			opt_O_arg = optarg;
			break;

		case 'b':
			if (strcmp(optarg, "i286") == 0) {
				opt_b = TARGET_I286;
				if (opt_f_sizeof_int == 0) {
					opt_f_sizeof_int = 2;
				}
				if (opt_f_sizeof_long_int == 0) {
					opt_f_sizeof_long_int = 4;
				}
			} else if (strcmp(optarg, "i386") == 0) {
				opt_b = TARGET_I386;
				if (opt_f_sizeof_int == 0) {
					opt_f_sizeof_int = 4;
				}
				if (opt_f_sizeof_long_int == 0) {
					opt_f_sizeof_long_int = 4;
				}
			} else {
				usage(1);
			}
			break;

		case 'd':
			opt_d = 1;
			break;

		case 'f':
			if (strncmp(optarg, "align-functions=", 16) == 0) {
				opt_f_align_functions = atoi(optarg + 16);
			} else if (strcmp(optarg, "no-dse") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-pic") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-PIC") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-pie") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-PIE") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "omit-frame-pointer") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-inline-atomics") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-optimize-strlen") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-shrink-wrap") == 0) {
				/* Ignore for now... */
			} else if (strcmp(optarg, "no-tree-tail-merge") == 0) {
				/* Ignore for now... */
			} else if (strncmp(optarg, "sizeof_char=", 12) == 0) {
				opt_f_sizeof_char = atoi(optarg + 12);
			} else if (strncmp(optarg, "sizeof_short_int=", 17) == 0) {
				opt_f_sizeof_short_int = atoi(optarg + 17);
			} else if (strncmp(optarg, "sizeof_int=", 11) == 0) {
				opt_f_sizeof_int = atoi(optarg + 11);
			} else if (strncmp(optarg, "sizeof_long_int=", 16) == 0) {
				opt_f_sizeof_long_int = atoi(optarg + 16);
			} else if (strncmp(optarg, "sizeof_long_long_int=", 21) == 0) {
				opt_f_sizeof_long_long_int = atoi(optarg + 21);
			} else if (strcmp(optarg, "segment_enable") == 0) {
				opt_f_segment_enable = 1;
			} else if (strcmp(optarg, "strict-aliasing") == 0) {
				/* Ignore for now... */
			} else {
				fprintf(stderr, "%s: WARNING: unknown compile option '-f %s'\n",
						progname, optarg);
			}
			break;

		case 'm':
			/* FIXME */
			break;

		default:
			usage(1);
			/*NOTREACHED*/
		}
	}
	argc -= optind;
	argv += optind;

	/* Fill defaults. */
	if (opt_b == TARGET_NONE) {
		opt_b = TARGET_I386;
		if (opt_f_sizeof_int == 0) {
			opt_f_sizeof_int = 4;
		}
		if (opt_f_sizeof_long_int == 0) {
			opt_f_sizeof_long_int = 4;
		}
	}

	if (opt_f_align_functions == 0) {
		opt_f_align_functions = 1;
	}
	if (opt_f_sizeof_char == 0) {
		opt_f_sizeof_char = sizeof(char);
	}
	if (opt_f_sizeof_short_int == 0) {
		opt_f_sizeof_short_int = sizeof(short int);
	}
	if (opt_f_sizeof_int == 0) {
		opt_f_sizeof_int = sizeof(int);
	}
	if (opt_f_sizeof_long_int == 0) {
		opt_f_sizeof_long_int = sizeof(long int);
	}
	if (opt_f_sizeof_long_long_int == 0) {
		opt_f_sizeof_long_long_int = sizeof(long long int);
	}

	/* Check options. */
	/* FIXME */

	/* Get Parameter */
	if (0 < argc) {
		infile = *argv;
		argv++;
		argc--;
	} else {
		usage(1);
	}
	if (0 < argc) {
		outfile = *argv;
		argv++;
		argc--;
	} else {
		usage(1);
	}

	/* Do Work */
	s = parse(infile);

	simplify(s);

	switch (opt_b) {
	case TARGET_I286:
		arch_i286_gen(outfile, s);
		break;
	case TARGET_I386:
	default:
		arch_i386_gen(outfile, s);
		break;
	}

	return 0;
}


#else


#include <assert.h>
#include <stdio.h>
#include <string.h>

const char *progname;
const char *input;

int
main(int argc, char **argv)
{
	static struct {
		const char *name;
		const char *value;
	} foption[] = {
		{ "-ftarget", NULL },
		{ "-fsizeof_char", NULL },
		{ "-fsizeof_short", NULL },
		{ "-fsizeof_int", NULL },
		{ "-fsizeof_long", NULL },
		{ "-fsizeof_long_long", NULL },
		{ "-fstack-protector", NULL },
		{ "-mtune", NULL },
		{ NULL, NULL }
	};
	static struct {
		const char *name;
		unsigned int value;
	} option[] = {
		{ "-quiet", 0 },
		{ NULL, 0 }
	};
	static struct {
		const char *name;
		const char *value;
	} poption[] = {
		{ "-auxbase", NULL },
		{ "-dumpbase", NULL },
		{ "-o", NULL },
		{ NULL, NULL }
	};
	unsigned int i;
	unsigned int o;

#if 1
	fprintf(stderr, "%s", argv[0]);
	for (i = 1; i < argc; i++) {
		fprintf(stderr, " %s", argv[i]);
	}
	fprintf(stderr, "\n");
#endif

	progname = *argv;

	for (i = 1; i < argc; i++) {
		for (o = 0; foption[o].name; o++) {
			if (strncmp(argv[i], foption[o].name,
					strlen(foption[o].name)) == 0
			 && argv[i][strlen(foption[o].name)] == '\0') {
				foption[o].value = "1";
				goto found;

			} else if (strncmp(argv[i], foption[o].name,
					strlen(foption[o].name)) == 0
				&& argv[i][strlen(foption[o].name)] == '=') {
				foption[o].value = &argv[i][strlen(foption[o].name) + 1];
				goto found;
			}
		}
		for (o = 0; option[o].name; o++) {
			if (strcmp(argv[i], option[o].name) == 0) {
				option[o].value = 1;
				goto found;
			}
		}
		for (o = 0; poption[o].name; o++) {
			if (strcmp(argv[i], poption[o].name) == 0) {
				poption[o].value = argv[++i];
				goto found;
			}
		}
		if (argv[i][0] == '-') {
			fprintf(stderr, "Option %s unknown.\n", argv[i]);
			assert(0);
		}
		input = argv[i];
	found:	;
	}

	fprintf(stderr, "Compiling %s.\n", input);

	return 0;
}


#endif
