⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decl.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * 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"
#include "outproto.h"

/********************************************************* Macro Definitions */

/* type specifiers */
#define	T_VOID		((unsigned) 1)
#define	T_CHAR		((unsigned) 2)
#define	T_SHORT		((unsigned) 4)
#define	T_INT		((unsigned) 8)
#define	T_LONG		((unsigned) 16)
#define	T_LONGLONG	((unsigned) 32)
#define	T_FLOAT		((unsigned) 64)
#define	T_DOUBLE	((unsigned) 128)
#define	T_SIGNED	((unsigned) 256)
#define	T_UNSIGNED	((unsigned) 512)
#define	T_BOOL		((unsigned) 1024)
#define	T_COMPLEX	((unsigned) 2048)
#define	T_IMAGINARY	((unsigned) 4096)
#define	T_ALL		(T_VOID|T_CHAR|T_SHORT|T_INT|T_LONG|T_FLOAT|T_DOUBLE|T_SIGNED|T_UNSIGNED|T_BOOL|T_COMPLEX|T_IMAGINARY)

#ifdef SYNTAX_CORRECT
#define	check_stdarg(x)
#define	check_tag(x1,x2)
#define	check_function_declaration(x)
#define	check_function_definition(x)
#define	check_representable(x1,x2)
#define	check_parameters(x1,x2)
#endif /* SYNTAX_CORRECT */

/*********************************************** Static Function Definitions */

static BLOCK *get_parameters P_ ((const SYM *));
static BOOL is_typedef_symbol P_ ((const CHAR *));
static QUALIFIER type_qualifier P_ ((QUALIFIER));
static QUALIFIER type_qualifier_list P_ ((void));
static SIZE declaration P_ ((STORAGE, STORAGE, SIZE));
static SIZE struct_declaration_list P_ ((const TYP *));
static STORAGE storage_class_specifier P_ ((STORAGE, BOOL));
static FSPECIFIER function_specifier P_ ((FSPECIFIER));
static SYM *declarator P_ ((STORAGE, TYP *));
static SYM *declare P_ ((SYM *, STORAGE));
static SYM *direct_declarator P_ ((STORAGE, TYP *));

static TYP *declaration_specifiers P_ ((STORAGE *, STORAGE, FSPECIFIER*));
static TYP *direct_declarator_tail P_ ((SYM *, TYP *));
static TYP *enum_specifier P_ ((STORAGE));
static TYP *enumeration_list P_ ((void));
static TYP *struct_or_union_specifier P_ ((STORAGE));
static void identifier_list P_ ((void));
static void parameter_type_list P_ ((void));

#ifndef SYNTAX_CORRECT
static void check_parameters P_ ((const BLOCK *, const SYM *));
static void check_stdarg P_ ((const SYM *));
static void check_tag P_ ((const SYM *, const TYP *));
#endif /* SYNTAX_CORRECT */

static SYM *func_symbol = NULL;

/*****************************************************************************/

/*
 *   Returns true if the token is one which starts a type
 *   specifier, otherwise it returns false.
 */

static BOOL is_type_specifier P1 (TOKEN, st)
{
    switch (st) {
		case tk_id:
			return is_typedef_symbol (lastsym);
		case kw_void:
		case kw_bool:
		case kw_char:
		case kw_short:
		case kw_unsigned:
		case kw_signed:
		case kw_long:
		case kw_struct:
		case kw_union:
		case kw_enum:
		case kw_float:
		case kw_double:
		case kw_int:
			return TRUE;
		default:
			break;
    }
    return FALSE;
}


/*
 *   Returns true if the token is one which starts a storage
 *   class specifier.
 */

static BOOL is_storage_class P1 (TOKEN, st)
{
    switch (st) {
		case kw_typedef:
		case kw_static:
		case kw_auto:
		case kw_register:
		case kw_extern:
			return TRUE;
		default:
		break;
    }
    return FALSE;
}


/*
 *   Returns true if the token is one which starts a type
 *   qualifier.
 */

static BOOL is_type_qualifier P1 (TOKEN, st)
{
    switch (st) {
		case kw_const:
		case kw_volatile:
#ifdef TOPSPEED
		case kw_cdecl:
#endif /* TOPSPEED */
		case kw_restrict:
			return TRUE;
		default:
			break;
    }
    return FALSE;
}

/*
 *   Return true if the token is one which starts a declaration
 *   specifier, otherwise it returns false.
 */

BOOL is_declaration_specifier P1 (TOKEN, st)
{
    return is_type_specifier (st) ||
		is_storage_class (st) || is_type_qualifier (st);
}


/*
 *   Returns true if the token is one which starts a specifier
 *   qualifier list, otherwise it returns false.
 */

static BOOL is_specifier_qualifier P1 (TOKEN, st)
{
    return is_type_specifier (st) || is_type_qualifier (st);
}


/*
 *   Returns true if the token is one which starts a type
 *   name, otherwise it returns false.
 */

BOOL is_type_name P1 (TOKEN, st)
{
    return is_specifier_qualifier (st);
}

#ifndef SYNTAX_CORRECT
/*
 *   Returns true if the integer constant can be represented by
 *   the specified type, otherwise it returns false.
 */

BOOL is_representable P2 (IVAL, i, const TYP *, tp)
{
    switch (tp->type) {
		case bt_char:
		case bt_schar:
			return (i >= -128L && i < 128L);
		case bt_uchar:
		case bt_charu:
			return (i >= 0L && i < 256L);
		case bt_short:
		case bt_int16:
			return (i >= -32768L && i < 32768L);
		case bt_ushort:
		case bt_uint16:
			return (i >= 0L && i < 65536L);
	
#ifdef LONGLONG_SUPPORT
#ifdef LONGLONG_BOOTSTRAP
		case bt_int32:
		case bt_long:
			return TRUE;
		case bt_uint32:
		case bt_ulong:
			return TRUE;
	
#else	/*  */
		case bt_int32:
		case bt_long:
			return (i >= -(IVAL) 2147483648L && i < (IVAL) 2147483647L);
		case bt_uint32:
		case bt_ulong:
			return (i >= 0L && i < (IVAL) 0x100000000L);
	
#endif	/* LONGLONG_BOOTSTRAP */
#else
		case bt_int32:
		case bt_long:
			return TRUE;
		case bt_uint32:
		case bt_ulong:
			return TRUE;
	
#endif	/* LONGLONG_SUPPORT */
		case bt_longlong:
			return TRUE;
		case bt_ulonglong:
			return TRUE;
		default:
			break;
    }
    return FALSE;
}
#endif /* SYNTAX_CORRECT */

/*
 *   Returns true if the current token is a typedef name,
 *   otherwise it returns false.
 */

static BOOL is_typedef_symbol P1 (const CHAR *, str)
{
    SYM    *sp = sym_search (str);

    return ((sp != NIL_SYM) && is_typedef (sp));
}

#ifndef SYNTAX_CORRECT
/*
 *   If the parameter parmN is declared with the register storage
 *   class, with a function or array type, or with a type that is not
 *   compatible with the type that results after application of the
 *   default promotions, the behaviour is undefined.
 */

static void check_stdarg P1 (const SYM *, sp)
{
    TYP    *tp = typeof (sp);

    if (is_register (sp) || is_array_type (tp)) {
		message (WARN_STDARG);
    } else if (is_function_type (tp)) {
		message (WARN_STDARG2);
    } else {
		switch (tp->type) {
			case bt_char:
			case bt_uchar:
			case bt_schar:
			case bt_charu:
			case bt_short:
			case bt_ushort:
			case bt_float:
				message (WARN_STDARG);
				break;
			default:
				break;
		}
    }
}

static void check_tag P2 (const SYM *, sp, const TYP *, tp)
{
    switch (typeof (sp)->type) {
		case bt_struct:
		case bt_union:
			if (is_same_type (typeof (sp), tp)) {
				return;
			}
			break;
		case bt_schar:
		case bt_uchar:
		case bt_short:
		case bt_ushort:
		case bt_int16:
		case bt_uint16:
		case bt_int32:
		case bt_uint32:
		case bt_long:
		case bt_ulong:
			if (is_same_type (tp_int, tp)) {
				return;
			}
			break;
		default:
			break;
    }
    message (ERR_TAG, nameof (sp));
}

static void check_function_declaration P1 (const SYM *, sp)
{
    /*
     *       The storage-specifier, if any, in the declaration specifiers
     *       shall be either extern or static.
     */

    switch (storageof (sp)) {
		TYP    *tp;

		case sc_global:		/* no specifier */
		case sc_external:		/* extern specifier */
		case sc_static:		/* static specifier */
			tp = typeof (sp);
			if (tp != NULL) {
				tp = returned_type (typeof (sp));
#ifndef SYNTAX_CORRECT
				if (tp != NULL && !is_void (tp)) {
					check_complete (tp);
				}
#endif /* SYNTAX_CORRECT */
			}
			break;
		default:
			message (ERR_ILLCLASS);
    }
}

static void check_function_definition P1 (const SYM *, sp)
{
    /*
     *       The return type of a function shall be void or an object type
     *       other than array.
     */

    TYP    *tp = returned_type (typeof (sp));

    switch (tp->type) {
		case bt_func:
			message (ERR_FUNC);
			break;
		case bt_pointer16:
		case bt_pointer32:
			if (is_array_type (tp)) {
				message (ERR_ARRAYRETURN);
			}
			break;
		case bt_void:
			if (is_qualified_type (tp)) {
				message (WARN_QUALIFIER);
			}
			break;
		default:
			break;
    }
}


/*
 *   Checks that i has a value representable as a 'tp'
 */
static void check_representable P2 (IVAL, i, const TYP *, tp)
{
    if (!is_representable (i, tp)) {
		message (ERR_REPRESENT, nameoftype (tp));
    }
}

/*
 *   Checks that the parameters in 'block' match those in any
 *   function prototype for 'sp'.
 */
static void check_parameters P2 (const BLOCK *, block, const SYM *, sp)
{
    SYM    *sp1, *sp2 = sym_search (nameof (sp));

    if ((sp2 == NIL_SYM) || !is_func (typeof (sp2))) {
		return;			/* no function definition */
    }
    sp1 = symbolsof (block);
    sp2 = parametersof (typeof (sp2));
    if (sp2 == NIL_SYM) {
		return;			/* no prototype on function definition */
    }
    if (sp1 == NIL_SYM) {
		if (!is_equal_type (tp_void, typeof (sp2))) {
			message (ERR_PROTO, nameof (sp));
		}
		sp2 = nextsym (sp2);
    }
    while ((sp1 != NIL_SYM) && (sp2 != NIL_SYM)) {
		if (!is_equal_type(promote_type (typeof (sp1)), promote_type (typeof (sp2)))) {
			message (ERR_PROTO, nameof (sp));
		} else if (!is_equal_type (promote_type (typeof (sp1)), typeof (sp2))) {
			message (ERR_PROTODEF, nameof (sp));
		}
		sp1 = nextsym (sp1);
		sp2 = nextsym (sp2);
    }
    if (sp1 != sp2) {
		message (ERR_PROTONUM, nameof (sp));
    }
}
#endif /* SYNTAX_CORRECT */

/*
 * Adds the symbol to the symbol table.
 */
static SYM *declare P2 (SYM *, sp, STORAGE, sc)
{
    BOOL    func_body;

    switch (typeof (sp)->type) {
		case bt_func:
			func_body = (lastst == tk_begin || lastst == kw_register ||
				lastst == kw_auto || is_type_name (lastst));

#ifndef SYNTAX_CORRECT
			switch (fspecifierof (sp)) {
				case fs_inline:
					if (nameof (sp) == main_name) {
						message (ERR_INLINEMAIN);
					}
					break;
				case fs_none:
					break;
				default:
					CANNOT_REACH_HERE ();
					break;
			}
#endif /* SYNTAX_CORRECT */

			switch (storageof (sp)) {
				case sc_external:
					if (func_body) {
						set_storage (sp, sc_global);
					}
					break;
				case sc_global:
					if (!func_body) {
						set_storage (sp, sc_external);
					}
					break;
				case sc_auto:
					set_storage (sp, sc_external);
					break;
				case sc_static:
				case sc_typedef:
					break;
				default:
					CANNOT_REACH_HERE ();
					break;
			}
#ifndef SYNTAX_CORRECT
			if (sc == sc_auto) {
				switch (storageof (sp)) {
					default:
						message (ERR_ILLCLASS);
					/*lint -fallthrough */
					case sc_external:
					case sc_typedef:
						break;
				}
			}
#endif /* SYNTAX_CORRECT */
			break;
		default:
			break;
    }
    sym_append (&sp);
    return sp;
}


SYM    *identifier P0 (void)
{
    SYM    *sp = sym_search (lastsym);

    if (sp != NIL_SYM) {
#ifndef SYNTAX_CORRECT
		if (is_symbol_outscope (sp)) {
			message (WARN_OUTSCOPE, nameof (sp));
		}
#endif /* SYNTAX_CORRECT */
		getsym ();
		return sp;
    }

    if (lastsym == func_name && lang_option >= LANG_C99) {
		if (func_symbol) {
			sp = mk_sym (lastsym, sc_static, copy_type (tp_conststring));
			getsym ();
			sym_append (&sp);
			initfuncid (sp, func_symbol);
			return sp;
#ifndef SYNTAX_CORRECT
		} else {
			message (ERR_FUNCID);
#endif /* SYNTAX_CORRECT */
		}
    }
    sp = mk_sym (lastsym, sc_external, tp_long);
    getsym ();
    switch (lastst) {
		case tk_openpa:
			set_type (sp, tp_func);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -