/* 
   Copyright 1994-2003 Free Software Foundation, Inc.

   This program 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 of the License, or
   (at your option) any later version.

   This program 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., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
#include <stdio.h>
#include				<string.h>
#include        "lists.h"
#include	"expr.h"
#include 	"c.h"
extern int prm_68020, prm_asmfile,prm_compileonly;
extern long lc_maxauto;
extern int packdata[], packlevel ;

char PROGNAME[]="CC386";
char ENVNAME[]="CC386";
char SOURCEXT[]=".ASM";
char GLBDEFINE[]="_i386_";
char OBJEXT[] = ".OBJ" ;

#ifdef BRIEFHELP
char *usage_text = "[+e/+i/f+l+v/w+A/C/D/E/I/O/Q/T/X] file list";
#else
char *usage_text = "[options] files"
#ifdef CPLUSPLUS
//"      [C++ mode is enabled, use .CPP extension]"
#endif
"\n"
"/c     - compile only                 +e     - dump errors to file\n"
"+i     - dump preprocessed file       /fname - specify parameter file\n"
"+l     - dump listing file            +v     - enable debug symbols\n"
"/w-xxx - disable a warning            +A     - disable extensions\n"
"/C     - codegen parameters           /Dxxx  - define something\n"
"/E[+]nn- max number of errors         /Ipath - specify include path\n"
"/O     - optimizer parameters         +Q     - quiet mode\n"
"/S     - make ASM source file         /T     - translate trigraphs\n"
"/Wxx   - set executable type\n"
/*#ifdef CPLUSPLUS
"+X     - enable C++ exception handling"
#endif
"\n" */
"Codegen parameters: (/C[+][-][params])\n"
"  +d   - display diagnostics          -b     - no BSS\n"
"  -l   - no C source in ASM file      -m     - no leading underscores\n"
"  +r   - reverse order of bit ops     +I     - microsoft exports\n"
"  +M   - generate MASM code           +N[X]  - generate NASM code [GENERIC]\n"
"  +S   - add stack checking code      +T     - generate TASM code\n"
"  +Z   - add profiler calls\n"
"Optimizer parameters (/O[+][-][params])\n"
"  +a   - peepopt inline ASM           +i     - inline intrinsics\n"
"  -m   - don't merge constants        -p     - no peephole opts\n"
/*"  -RA  - no address register optimizations\n" */
/*"  -RD  - no data register optimizations\n" */
"Time: "__TIME__"  Date: "__DATE__;

#endif        
int stdmemberptrsize = 4;
int prm_masm = FALSE;
int prm_nodos = FALSE;                            
int prm_flat = TRUE; /* not supporting TASM small model any more */
int prm_nasm = 0;
int prm_microlink = 0;
int prm_browse = 0 ;
int cf_maxaddress =20;
int cf_maxdata=4;
int cf_freeaddress =1;
int cf_freedata=3;
int cf_freefloat=3;
int stackadd = 3;
int stackmod = -4;
int strucadd = 3;
int strucmod = -4;
int stdretblocksize = 8;
int stdinttype = bt_int;
int stdunstype = bt_unsigned;
int stdintsize = 4;
int stdldoublesize = 10;
int stdaddrsize = 4;
int regdsize = 4;
int regasize = 4;
int regfsize = 10;

extern TYP stdchar ;
TYP             stdconst = { bt_int, 1, UF_DEFINED, -1, -1, 4, 0, 0, "stdconst"};
TYP             stdstring = {bt_pointer, 0, 0,-1, -1, 4, 0, &stdchar};
TYP             stdint = { bt_int, 0, UF_DEFINED | UF_USED,-1, -1, 4 };
TYP							stdlongdouble = {bt_longdouble,0,0,-1,-1,10};
TYP             stduns = { bt_unsigned, 0, 0,-1, -1, 4};
KEYWORDS prockeywords[] = {
				{0,"_absolute", kw__abs,4}, { 0, "_pascal", kw__pascal,4 },
				{0,"_cdecl", kw__cdecl,0 }, { 0, "_stdcall", kw__stdcall,4 },
            {0,"_interrupt", kw__interrupt,4},{0,"_genbyte", kw__genword,4 },
        {0,"_intrinsic", kw__intrinsic,4}, {0,"_trap", kw__trap,4},
				{0,"_loadds", kw__loadds,4}, { 0, "_far", kw__far,4 },
				{0,"_indirect",kw__indirect,4}, {0,"_export",kw__export,4 },
				{0,"_import",kw__import,4},
				{0,"_EAX", kw_D0,4}, {0,"_ECX", kw_D1,4},{0,"_EDX", kw_D2,4},
				{0,"_EBX", kw_D3,4},{0,"_ESP", kw_D4,4},{0,"_EBP", kw_D5,4},
				{0,"_ESI", kw_D6,4},{0,"_EDI", kw_D7,4},
        {0, 0, 0} };

char *registers[] = { "EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI",
"","","","","","","","",
"ESP","EBP","ESI","EDI" };

int confcodegen(char s, int bool)
{
	switch (s) {
					case 'I':
						prm_microlink = bool ;
						break ;
					case 'M':
						prm_masm = bool;
                  prm_asmfile = bool;
                  prm_compileonly = bool ;
						break;
					case 'N':
						prm_nasm = bool;
						prm_asmfile = bool ;
                  prm_compileonly = bool ;
                  break;
               case 'T':
                  prm_asmfile = bool ;
                  prm_compileonly = bool ;
						break;
					case 'X':
						prm_nodos = bool;
						break;
					case 'F':
						prm_flat = bool;
						break;
               case '?':
                  prm_browse = bool ;
                  break ;
					default:
						return 0;
	}
	return 1;
}
void confsetup(void)
{
		cf_freeaddress = 2;
}
int     alignment(int type, TYP *tp)
{       switch(tp->type) {
                case bt_char: case bt_unsignedchar:  case bt_bool: return 1;
                case bt_short: case bt_unsignedshort: return 2;
                case bt_long: case bt_unsignedlong: return 4;
								case bt_int: case bt_unsigned: return 4 ;
                case bt_enum:           return 2;
                case bt_pointer:
								case bt_matchall:
                                return 4;
								case bt_memberptr:
                case bt_float:          return 4;
                case bt_double:         return 8;
                        case bt_longdouble:           return 12;
                case bt_fcomplex:      return 8 ;
                case bt_rcomplex:      return 16;
                case bt_lrcomplex:     return 24;
								case bt_class:
                case bt_struct:
                case bt_union:          return tp->alignment;
                default:                return 1;
                }
}
int getalign(int sc, TYP *tp)
{
   int align = alignment(sc,tp);
                                    if (sc != sc_auto) 
                                       if (packdata[packlevel] < align)
                                          align = packdata[packlevel];
	return align;
}

long getautoval(long val)
{
	return val;
}
funcvaluesize(int size)
{
		return 0;
}