/*
 * C compiler
 * ==========
 *
 * Copyright 1989, 1990, 1991 Christoph van Wuellen.
 * Credits to Matthew Brandt.
 * All commercial rights reserved.
 *
 * This compiler may be redistributed as long there is no
 * commercial interest. The compiler must not be redistributed
 * without its full sources. This notice must stay intact.
 *
 * History:
 *
 * 1989   starting an 68000 C compiler, starting with material
 *        originally by M. Brandt
 * 1990   68000 C compiler further bug fixes
 *        started i386 port (December)
 * 1991   i386 port finished (January)
 *        further corrections in the front end and in the 68000
 *        code generator.
 *        The next port will be a SPARC port
 */

#include "chdr.h"
#include "expr.h"
#include "cglbdec.h"
#include "proto.h"

#define MAXKEY	((unsigned) 256)	/* hash table size */

static TYP *	hashtable[MAXKEY];	/* hash table */

/*
**	returns true it tp is an integral type,
**	otherwise retusn false.
*/

BOOL
is_integral_type P1(const TYP *, tp)
{
    switch (tp->type) {
      case bt_char:
      case bt_charu:
      case bt_uchar:
      case bt_schar:
      case bt_short:
      case bt_ushort:
      case bt_int16:
      case bt_uint16:
      case bt_int32:
      case bt_uint32:
      case bt_long:
      case bt_ulong:
	return TRUE;
      default:
	break;
    }
    return FALSE;
}


#ifdef FLOAT_SUPPORT
/*
**	returns true if the type is a floating type,
**	otherwise it returns false.
*/

BOOL
is_floating_type P1(const TYP *, tp)
{
    switch (tp->type) {
      case bt_float:
      case bt_double:
      case bt_longdouble:
	return TRUE;
      default:
	break;
    }
    return FALSE;
}
#endif /* FLOAT_SUPPORT */


/*
**	returns true if the type is an arithmetic type,
**	otherwise it returns false.
*/

BOOL
is_arithmetic_type P1(const TYP *, tp)
{
    return (is_integral_type(tp)
#ifdef FLOAT_SUPPORT
	 || is_floating_type(tp)
#endif /* FLOAT_SUPPORT */
	   ) ;
}


/*
**	returns true if the type is a function, otherwise returns false.
*/

BOOL
is_function_type P1(const TYP *, tp)
{
    if (tp == NIL_TYP)
	return FALSE;
    /* functions are implicitly converted to pointers to functions */
    return (tp->type == bt_func) ||
	   (is_pointer_type(tp) && referenced_type(tp)->type == bt_func) ;
}


/*
**	returns true if the type is a scalar type,
**	otherwise returns false.
*/
BOOL
is_scalar_type P1(const TYP *, tp)
{
    return (is_arithmetic_type(tp) || is_pointer_type(tp));
}


/*
**	returns true is the type is an object type,
**	otherwise returns false.
*/

BOOL
is_object_type P1(const TYP *, tp)
{
    switch (tp->type) {
      case bt_func:
	return FALSE;
      default:
	break;
    }
    return TRUE;
}


/*
**	returns true if the type is a struct or union,
**	otherwise returns false.
*/

BOOL
is_structure P1(const TYP *, tp)
{
    switch (tp->type) {
      case bt_struct:
      case bt_union:
	return TRUE;
      default:
	break;
    }
    return FALSE;
}


/*
**	returns true if the type is a pointer type,
**	otherwise it returns false.
*/

BOOL
is_pointer_type P1(const TYP *, tp)
{
    switch (tp->type) {
      case bt_pointer32:
      case bt_pointer16:
	return TRUE;
      default:
	break;
    }
    return FALSE;
}


/*
**	returns type if the type is an array,
**	otherwise returns false.
*/

BOOL
is_array_type P1(const TYP *, tp)
{
    return (is_pointer_type(tp) && is_derived_type(tp));
}


/*
**	returns true if tp is a signed type,
**	otherwise it returns false.
*/

BOOL
is_signed_type P1(const TYP *, tp)
{
    switch (tp->type) {
      case bt_char:
      case bt_schar:
      case bt_short:
      case bt_int16:
      case bt_int32:
      case bt_long:
      case bt_bitfield:
	return TRUE;
      default:
	break;
    }
    return FALSE;
}

/*
**	returns true if tp is an unsigned type,
**	otherwise it returns false.
*/

BOOL
is_unsigned_type P1(const TYP *, tp)
{
    switch (tp->type) {
      case bt_ulong:
      case bt_uint32:
      case bt_uint16:
      case bt_ushort:
      case bt_uchar:
      case bt_charu:
      case bt_pointer16:
      case bt_pointer32:
      case bt_ubitfield:
	return TRUE;
      default:
	break;
    }
    return FALSE;
}


/*
**	This is used to tell valid from invalid redeclarations
**	return zero for equal types, ERR_ value for non-equal types.
*/

MSGNUM
is_same_type P3(TYP *, tp1, TYP *, tp2,  BOOL, KandR)
{
    MSGNUM ret;
    if (tp1 == NIL_TYP || tp2 == NIL_TYP)
	return ERR_REDECL;

    if (tp1 == tp2)
	return (MSGNUM)0;

    if (tp1->type != tp2->type) {
	if (!KandR || (promote(tp1)->type != tp2->type))
	    return ERR_REDECL;
    }

    if (tp1->qual != tp2->qual)
	return ERR_REDECL;

    switch (tp1->type) {
      case bt_pointer16:
      case bt_pointer32:
	return is_same_type(referenced_type(tp1), referenced_type(tp2), KandR);
      case bt_func:
	ret = is_same_type(returned_type(tp1), returned_type(tp2), KandR);
	if (ret == 0)
	    return check_proto(parameters(tp1)->symbols.head,
			       parameters(tp2)->symbols.head, FALSE);
	return ret;
      case bt_struct:
      case bt_union:
	if (members(tp1) == members(tp2))
	    return (MSGNUM)0;
	return (ERR_REDECL);
      default:
	break;
    }
    return (MSGNUM)0;
}

TYP *
qualify_type P2(TYP*, tp,  QUALIFIER, qualifier)
{
    if (qualifier != tp->qual) {
	TYP *tp1 = tp;
	QUALIFIER q = tp1->qual;
	tp1->qual = qualifier;
	tp = mk_type(tp1, tp1->btp);
	tp1->qual = q;
    }
    return tp;
}

/*
** ANSI 3.1.2.6
**	A composite type can be constructed from two types that are compatible;
**	it is a type that is compatible with both of the two types and
**	satisifies the following conditions:
**
**	    If one type is an array of know size, the composite type is an
**	    array of that size.
**
**	    If only one type is a function type with a parameter list (a
**	    function prototype), the composite type is a function prototype
**	    with the parameter list.
**
**	    If both types are function types with parameter type lists, the
**	    type of each parameter in the composite parameter type list
**	    is the composite type of the corresponding parameters.
**
**	These rules apply recursively to the types from which the two
**	types are derived.
*/
TYP *
composite_type P2(TYP *, tp1, TYP *, tp2)
{
    SYM *sp1, *sp2;
    if (tp1->type != tp2->type)
	return tp1;	/* error path */
    if (tp1 == tp2)
	return tp1;
    switch (tp1->type) {
      case bt_pointer16:
      case bt_pointer32:
	/*
	**	Combine the pointed at types.
	*/
	set_referenced_type(tp1,
		 composite_type(referenced_type(tp1), referenced_type(tp2)));

	if (is_array_type(tp1)) {
	    if (tp1->size == UNKNOWN_SIZE) {
		/*
		**	tp1 is an array with unknown size ... return
		**	tp2 as it might have a known size.
		*/
		return tp2;
	    }
	    if (tp2->size == UNKNOWN_SIZE) {
		/*
		**	tp2 is an array with unknown size ... return
		**	tp1 as it has a known size.
		*/
		return tp1;
	    }
	}
	break;
      case bt_func:
	/*
	**	Combine the function return types.
	*/
	set_returned_type(tp1,
		     composite_type(returned_type(tp1), returned_type(tp2)));
	set_returned_type(tp2, returned_type(tp1));

	sp1 = parameters(tp1)->symbols.head;
	if (sp1 == NULL) {
	    /*
	    **	tp1 has no parameters so return tp2 ... it might have
	    */
	    return tp2;
	}
	sp2 = parameters(tp2)->symbols.head;
	if (sp2 == NULL) {
	    /*
	    **	tp2 has no parameters so return tp1 ... it does
	    */
	    return tp1;
	}
	/*
	**	Now combine the type information for the function parameters
	*/
	while (sp1 != NULL && sp2 != NULL) {
	    sp2->tp = sp1->tp = composite_type(sp1->tp, sp2->tp);
	    sp1 = sp1->next;
	    sp2 = sp2->next;
	}
	break;
      default:
	break;
    }
    return tp1;
}

/*
 * This is used to tell valid if two types are compatible with each other.
 *
 * ANSI 3.1.2.6
 *	Two types have compatible type if their types are the same.
 *	Two structure, union, or enumeration types declared in seperate
 *	translation units are compatible if they have the same number of
 *	memebers, the same memeber names, and compatible memeber types; for
 *	two structures, the memebers shall be in the same order; for two
 *	structures or unions, te bit-fields shall have the same widths;
 *	for two enumerations, the members shall have the same values.
 *
 *	All declarations that refer to the same object or function shall have
 *	compatible type; otherwise the behavious ir undefined.
 *
 * ANSI 3.5.3
 *	for two qualified types to be compatible, both shall have the
 *	identically qualified version of a compatible type;  the order of the
 *	qualifiers within a list of specifiers or qualifiers does not
 *	affect the specified type.
 *
 * ANSI 3.5.4.1
 *	for two pointers to be compatible, both shall be identically qualified
 *	and both shall be pointers to compatible types.
 *
 * ANSI 3.5.4.2
 *	For two arrays to be compatible, both shall have compatible element
 *	types, and if both size specifiers are present they shall have the
 *	same value.
 *
 * ANSI 3.5.4.3
 *	for two function type to be compatible, both shall specify compatible
 *	return types.  Moreover, the parameter type lists, if both are
 *	present, shall agree in the number of parameters and in use of the
 *	ellipsis terminator; corresponding parameters shall have compatible
 *	types.  If one type has a parameter list and the other type is
 *	specified by a function declarator that is not part of a function
 *	definition and that contains an empty identifier list, the
 *	parameter list shall not have an ellipsis terminator and the type
 *	of each parameter shall be compatible with the type that results
 *	from the application of the default argument promotions.  If one type
 *	has a parameter type list and the other type is specified by a function
 *	definition that contains a (possibly empty) identifier list, both
 *	shall agree in the numbr of parameters, and the type of each
 *	prototype argument shall be compatible with the type that results
 *	from the application of the default argument promotions to the type
 *	of the corresponding identifier.
 */
BOOL
is_compatible P2(const TYP *, tp1, const TYP *, tp2)
{
    if (tp1 == NIL_TYP || tp2 == NIL_TYP)
	return FALSE;

    if (tp1 == tp2)
	return TRUE;

    if (tp1->type != tp2->type)
	return FALSE;

    switch (tp1->type) {
      case bt_pointer16:
      case bt_pointer32:
	if (is_void(referenced_type(tp1)) || is_void(referenced_type(tp2)))
	    return TRUE;
	return (is_compatible(referenced_type(tp1), referenced_type(tp2)));
      case bt_func:
	return (!is_same_type(returned_type(tp1), returned_type(tp2), FALSE)) && 
	       (check_proto(parameters(tp1)->symbols.head,
			    parameters(tp2)->symbols.head, FALSE) == (MSGNUM)0);
      case bt_struct:
      case bt_union:
	return (members(tp1) == members(tp2));
      default:
	break;
    }
    return TRUE;
}


/*
**	perform the integral promotions and return the type
*/

TYP *
promote P1(TYP *, tp)
{
    switch(tp->type) {
      case bt_charu:
      case bt_uchar:
      case bt_ushort:
	if (tp->size == tp_int->size)
	    return tp_uint;
	/*FALLTHRU*/
      case bt_char:
      case bt_schar:
      case bt_short:
	return tp_int;
      case bt_float:
	return tp_double;
      case bt_pointer16:
      case bt_pointer32:
	/* always passed by reference, never by value */
	return tp_pointer;
      case bt_func:
	/* always passed by reference, never by value */
	return tp_func;
      default:
	break;
    }
    return tp;
}

/*
**	perform the unary convertions and return the type
*/

TYP *
unary_conversion P1(TYP *, tp)
{
    switch(tp->type) {
      case bt_charu:
      case bt_uchar:
      case bt_ushort:
	if (tp->size == tp_int->size)
	    return tp_uint;
	/*FALLTHRU*/
      case bt_char:
      case bt_schar:
      case bt_short:
	return tp_int;
      case bt_pointer16:
      case bt_pointer32:
	/* always passed by reference, never by value */
	return tp_pointer;
      case bt_func:
	/* always passed by reference, never by value */
	return tp_func;
      default:
	break;
    }
    return tp;
}

/*
**	returns type if the size of the type is not known.
**	There is a complication that "copied" types (i.e. ones
**	with qualifiers) might have been copied before the size
**	was known so we need to calculate it now!.
*/

BOOL
is_incomplete_type P1(TYP *, tp)
{
    if (tp->size == UNKNOWN_SIZE) {
	if (is_structure(tp) && (members(tp)->symbols.head != NIL_SYM)) {
	    /* the tag must be in the tag table */
	     SYM *	sp = tag_search(tp->sname);
	    tp->size = sp->tp->size;
	    return is_incomplete_type(tp);
	}
	return TRUE;
    }
    return FALSE;
}


/*
** ensure that the size of ep is known.
*/

void
check_complete P1(TYP *, tp)
{
    if (is_incomplete_type(tp))
	message (ERR_SIZE);
}


/*
**	Check that tp1 has all the qualifiers of tp2
*/
void
check_qualifiers P2(TYP*, tp1, TYP*, tp2)
{
    if (!is_pointer_type(tp1) || !is_pointer_type(tp2))
	return;
    if (tp1->btp->qual < tp2->btp->qual)
	message(ERR_QUAL);
}


TYP     *
copy_type P1(const TYP *, tp)
{
    TYP		*ret_tp;
    if (tp == NIL_TYP)
	return NIL_TYP;
    ret_tp = (TYP *) galloc((size_t) sizeof(TYP));
    *ret_tp = *tp;
    ret_tp->next = NULL;

    switch (tp->type) {
      case bt_pointer16:
      case bt_pointer32:
	set_referenced_type(ret_tp, copy_type(referenced_type(tp)));
	break;
      case bt_func:
	set_returned_type(ret_tp, copy_type(returned_type(tp)));
	set_parameters(ret_tp, mk_block());
	break;
      default:
	break;
    }
    return ret_tp;
}

static unsigned
hash P1(const TYP *, tp)
{
    return ((unsigned)tp>>(unsigned)2 & (MAXKEY-(unsigned)1));
}

TYP *
mk_type P2(const TYP *, tp1, TYP *, btp)
{
    static  TYP	    init_tp = { bt_void, 0, 0, 0, 0, 0, 0, {0}};
    TYP		*tp;
    unsigned keyno = hash(tp1);
    /*
    **	Look to see if this type has already been defined
    */
    switch (tp1->type) {
      case bt_void:
      case bt_char:
      case bt_schar:
      case bt_uchar:
      case bt_charu:
      case bt_short:
      case bt_ushort:
      case bt_long:
      case bt_ulong:
      case bt_int32:
      case bt_int16:
      case bt_pointer16:
      case bt_pointer32:
	for (tp = hashtable[keyno]; tp ; tp = tp->next){
	    if (btp && btp->type == bt_func)
		continue;
	    if ((tp->type == tp1->type) &&
		(tp->qual == tp1->qual) &&
		(tp->size == tp1->size) &&
		(tp->btp  == btp) &&
		(is_enum(tp) == is_enum(tp1)) &&
		(is_derived_type(tp) == is_derived_type(tp1))) {
		return tp;
	    }
	}
	break;
      default:
	break;
    }

    tp = (TYP *) galloc((size_t) sizeof(TYP));
    *tp = init_tp;
    tp->size = tp1->size;
    tp->type = tp1->type;
    tp->qual = tp1->qual;
    tp->btp = btp;
    if(is_derived_type(tp1))
	set_derived(tp);
    if(is_enum(tp1))
	set_enum(tp);
    switch (tp->type) {
      case bt_func:
	if (parameters(tp1))
	    set_parameters(tp, parameters(tp1));
	else
	    set_parameters(tp, mk_block());
	break;
      case bt_struct:
      case bt_union:
	if (members(tp1))
	    set_members(tp, members(tp1));
	else
	    set_members(tp, mk_block());
	break;
      default:
	break;
    }

    tp->next = hashtable[keyno];
    hashtable[keyno] = tp;
    return tp;
}

void
size_type P1(TYP *, tp)
{
    TYP *rtp;
    if (tp == NIL_TYP)
	return ;
    if (is_array_type(tp)) {
	rtp = referenced_type(tp);
	size_type (rtp);
	if (rtp &&
	    (array_index(tp) != UNKNOWN_SIZE) && (rtp->size != UNKNOWN_SIZE)) {
	    tp->size = rtp->size * array_index(tp);
	}
    }
}

/*
**	Calculate the alignment requirements of the specified type
*/
SIZE
alignment P1(const TYP*, tp)
{
    SYM		*sp;
    SIZE	 algn, al;

    switch (tp->type) {
      case bt_struct:
      case bt_union:
	if (align_option) {
	    /* align structures to the alignment of the worst aligned member */
	    algn = g_alignments[bt_char];;
	    for (sp = members(tp)->symbols.head; sp != NIL_SYM; sp = sp->next) {
		al = alignment (sp->tp);
		if (al > algn)
		    algn = al;
	    }
	    return algn;
	}
	/* FALLTHRU */
      case bt_void:
      case bt_char:
      case bt_charu:
      case bt_uchar:
      case bt_schar:
      case bt_short:
      case bt_ushort:
      case bt_int16:
      case bt_uint16:
      case bt_int32:
      case bt_uint32:
      case bt_long:
      case bt_ulong:
      case bt_float:
      case bt_double:
      case bt_longdouble:
      case bt_func:
	return g_alignments[tp->type];
      case bt_pointer16:
      case bt_pointer32:
	return is_array_type(tp) ? alignment (referenced_type(tp)) : g_alignments[tp->type];
      case bt_bitfield:
      case bt_ubitfield:
	return alignment (tp_int);
      default:
	FATAL ((__FILE__,"g_alignment", "illegal type %d", tp->type));
	return 0L;
    }
}

static	TYP	 stp_void       = {bt_void,
				   QUAL_NONE,
				   STATE_NONE,
				   UNKNOWN_SIZE,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"void",
				   {NIL_BLOCK}};

static	TYP	 stp_long       = {bt_long,
			           QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"long",
				   {NIL_BLOCK}};

static	TYP	 stp_ulong      = {bt_ulong,
			           QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"ulong",
				   {NIL_BLOCK}};

static	TYP	 stp_char       = {bt_char,
			           QUAL_NONE,
				   STATE_NONE,
			           1L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"char",
				   {NIL_BLOCK}};

static	TYP	 stp_uchar      = {bt_uchar,
			           QUAL_NONE,
				   STATE_NONE,
			           1L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"unsigned char",
				   {NIL_BLOCK}};

static	TYP	 stp_schar      = {bt_schar,
			           QUAL_NONE,
				   STATE_NONE,
			           1L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"signed char",
				   {NIL_BLOCK}};

static	TYP	 stp_short      = {bt_short,
			           QUAL_NONE,
				   STATE_NONE,
			           2L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"short",
				   {NIL_BLOCK}};

static	TYP	 stp_ushort     = {bt_ushort,
			           QUAL_NONE,
				   STATE_NONE,
			           2L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"unsigned short",
				   {NIL_BLOCK}};

static	TYP	 stp_int        = {bt_int32,
			           QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"int",
				   {NIL_BLOCK}};

static	TYP	 stp_uint       = {bt_uint32,
			           QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"unsigned int",
				   {NIL_BLOCK}};

#ifdef FLOAT_MFFP
static	TYP	 stp_float      = {bt_float,
			           QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"float",
				   {NIL_BLOCK}};

static	TYP	 stp_double     = {bt_double,
			           QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"double",
				   {NIL_BLOCK}};

static	TYP	 stp_longdouble = {bt_longdouble,
				   QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"long double",
				   {NIL_BLOCK}};

#else
static	TYP	 stp_float      = {bt_float,
			           QUAL_NONE,
				   STATE_NONE,
			           4L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"float",
				   {NIL_BLOCK}};

static	TYP	 stp_double     = {bt_double,
			           QUAL_NONE,
				   STATE_NONE,
			           8L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"double",
				   {NIL_BLOCK}};

static	TYP	 stp_longdouble = {bt_longdouble,
				   QUAL_NONE,
				   STATE_NONE,
			           12L,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"long double",
				   {NIL_BLOCK}};

#endif /* FLOAT_MFFP */
static	TYP	 stp_string     = {bt_pointer32,
				   QUAL_NONE,
				   STATE_DERIVED,
			           4L,
				   &stp_char,
				   NIL_TYP,
				   (CHAR *)"*",
				   {NIL_BLOCK}};
static	TYP	 stp_func       = {bt_func,
			           QUAL_NONE,
				   STATE_DERIVED,
			           4L,
				   &stp_int,
				   NIL_TYP,
				   (CHAR *)"()",
				   {&init_block}};
static	TYP	 stp_struct     = {bt_struct,
			           QUAL_NONE,
				   STATE_NONE,
			           UNKNOWN_SIZE,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"struct",
				   {NIL_BLOCK}};
static	TYP	 stp_union     = {bt_union,
			           QUAL_NONE,
				   STATE_NONE,
			           UNKNOWN_SIZE,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"union",
				   {NIL_BLOCK}};
static	TYP	 stp_pointer    = {bt_pointer32,
				   QUAL_NONE,
				   STATE_NONE,
			           4L,
				   &stp_void,
				   NIL_TYP,
				   (CHAR *)"*",
				   {NIL_BLOCK}};
static	TYP	 stp_array      = {bt_pointer32,
				   QUAL_NONE,
				   STATE_DERIVED,
			           UNKNOWN_SIZE,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"[]",
				   {NIL_BLOCK}};

static	TYP	 stp_enum        = {bt_int32,
			           QUAL_NONE,
				   STATE_NONE,
			           UNKNOWN_SIZE,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"int",
				   {NIL_BLOCK}};
static	TYP	 stp_ellipsis    = {bt_ellipsis,
			           QUAL_NONE,
				   STATE_NONE,
			           UNKNOWN_SIZE,
				   NIL_TYP,
				   NIL_TYP,
				   (CHAR *)"...",
				   {NIL_BLOCK}};

void
initialize_types P0(void)
{
    if (short_option) {
	/*
	 * set 'int' and 'enum' type
	 */
	stp_int.type	= bt_int16;
	stp_uint.type	= bt_uint16;
	stp_int.size	= 2L;
	stp_uint.size	= 2L;
	int_bits	= 16;
    }
#ifdef INTEL_86
    if (small_option) {
	stp_pointer.type = bt_pointer16;
	stp_string.type	 = bt_pointer16;
	stp_array.type = bt_pointer16;
	stp_pointer.size = 2L;
	stp_string.size	 = 2L;
	stp_func.size	 = 2L;
    }
#endif /* INTEL_86 */
    if (uchar_option)
	stp_char.type	= bt_charu;

    tp_void       = mk_type(&stp_void, NULL) ;
    tp_long       = mk_type(&stp_long, NULL) ;
    tp_ulong      = mk_type(&stp_ulong, NULL) ;
    tp_char       = mk_type(&stp_char, NULL) ;
    tp_uchar      = mk_type(&stp_uchar, NULL) ;
    tp_schar      = mk_type(&stp_schar, NULL) ;
    tp_short      = mk_type(&stp_short, NULL) ;
    tp_ushort     = mk_type(&stp_ushort, NULL) ;
    tp_int        = mk_type(&stp_int, NULL) ;
    tp_uint       = mk_type(&stp_uint, NULL) ;
    tp_float      = mk_type(&stp_float, NULL) ;
    tp_double     = mk_type(&stp_double, NULL) ;
    tp_longdouble = mk_type(&stp_longdouble, NULL) ;
    tp_size       = mk_type(&STP_SIZE, NULL);
    tp_ptrdiff    = mk_type(&STP_PTRDIFF, NULL);
    tp_wchar      = mk_type(&STP_WIDE, NULL) ;
    tp_string     = mk_type(&stp_string, tp_char) ;
    tp_wstring    = mk_type(&stp_pointer, tp_wchar) ;
    tp_func       = mk_type(&stp_func, tp_int) ;
    tp_pointer    = mk_type(&stp_pointer, tp_void) ;
    tp_array	  = mk_type(&stp_array, NULL);
    tp_enum       = mk_type(&stp_enum, NULL) ;
    tp_struct     = &stp_struct ;
    tp_union      = &stp_union ;
    tp_ellipsis   = mk_type(&stp_ellipsis, NULL) ;

    if (!longdouble_option)
	tp_longdouble	= tp_double;
}
