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

📄 decl.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 4 页
字号:
			case bt_struct:
				offset += size;
				break;
			case bt_union:
				break;
			default:
				CANNOT_REACH_HERE ();
		}
		needpunc (tk_semicolon);
    }
#ifndef SYNTAX_CORRECT
    if (count == 0) {
		message (ERR_INCOMPLETE, nameoftype (tp));
    }
#endif /* SYNTAX_CORRECT */
    set_members (tp, endstructblock ());
    return max_size;
}


/*ANSI3.5.2.1
 *    struct-or-union-specifier:
 *              struct-or-union identifier[opt] { struct-declaration-list }
 *              struct-or-union identifier
 *
 *    struct-or-union:
 *              "struct"
 *              "union"
 */
static TYP *struct_or_union_specifier P1 (STORAGE, sc)
{
    TYP    *tp = NIL_TYP;
    SYM    *sp;
    SIZE    size;

    switch (lastst) {
		case kw_struct:
			tp = tp_struct;
			break;
		case kw_union:
			tp = tp_union;
			break;
		default:
			CANNOT_REACH_HERE ();
			break;
    }

    getsym ();

    switch (lastst) {
		case tk_id:
			if ((sp = tag_search (lastsym)) == NIL_SYM) {
				tp = mk_type (tp, NIL_TYP);
				sp = mk_sym (lastsym, sc_tag, tp);
				getsym ();
				set_nameoftype (tp, nameof (sp));
				tag_append (&sp);
#ifndef SYNTAX_CORRECT
				if (sc == sc_parms) {
					message (WARN_DUBIOUS, nameoftype (tp));
				}
#endif /* SYNTAX_CORRECT */
				beginstructblock (members (tp));
				set_members (tp, endstructblock ());
			} else {
				getsym ();
				if (is_local_scope (sp)) {
					check_tag (sp, tp);
				} else {
					switch (lastst) {
						case tk_semicolon:
							/* ANSI 3.5.2.3
							 *        A declaration of the form
							 *          struct-or-union identifier ;
							 *  specifies a structure or union and declares a tag
							 *  both visible only within the scope in which the
							 *  declaration occurs.  It declares a new type distinct
							 *  from any type with the same tag in an enclosing scope
							 *  (if any).
							 */
							tp = mk_type (tp, NIL_TYP);
							sp = mk_sym (nameof (sp), sc_tag, tp);
							set_nameoftype (tp, nameof (sp));
							tag_append (&sp);
							beginstructblock (NIL_BLOCK);
							set_members (tp, endstructblock ());
							return tp;
						case tk_begin:
						    /*
							 * Defining a new structure/union which will hide the one
						     * at an outer scope.
						     */
							tp = mk_type (tp, NIL_TYP);
							sp = mk_sym (nameof (sp), sc_tag, tp);
							set_nameoftype (tp, nameof (sp));
							tag_append (&sp);
#ifndef SYNTAX_CORRECT
							if (sc == sc_parms) {
								message (WARN_DUBIOUS, nameoftype (tp));
							}
#endif /* SYNTAX_CORRECT */
							beginstructblock (NIL_BLOCK);
							set_members (tp, endstructblock ());
							break;
						default:
							break;
					}
				}
			}
			tp = typeof (sp);
			size = tp->size;
			if (lastst == tk_begin) {
#ifndef SYNTAX_CORRECT
				if (is_symbol_defined (sp)) {
					message (ERR_REDECL, nameof (sp));
				}
#endif /* SYNTAX_CORRECT */
				getsym ();
				size = struct_declaration_list (tp);
				needpunc (tk_end);
				symbol_defined (sp);
			}
			break;
		case tk_begin:
#ifndef SYNTAX_CORRECT
			if (sc == sc_parms) {
				message (WARN_DUBIOUS, nameoftype (tp));
			}
#endif /* SYNTAX_CORRECT */
			getsym ();
			tp = mk_type (tp, NIL_TYP);
			size = struct_declaration_list (tp);
			needpunc (tk_end);
			break;
		default:
#ifndef SYNTAX_CORRECT
			message (ERR_INCOMPLETE, nameoftype (tp));
			tp = mk_type (tp, NIL_TYP);
#endif /* SYNTAX_CORRECT */
			return tp;
	}
    if (size != UNKNOWN_SIZE) {
		size += align (tp, size);
    }
    tp->size = size;
    return tp;
}


/*ANSI 3.5.1
 *    storage-class-specifier:
 *              "typedef"
 *              "extern"
 *              "static"
 *              "auto"
 *              "register"
 *
 * Only one storage-class is allowed on a declaration.
 */

static STORAGE storage_class_specifier P2 (STORAGE, sc, BOOL, sc_set)
{
    /*
     *Constraint: At most one storage-class specifier may be given in the
     *            declaration specifiers in a declaration.
     */
#ifndef SYNTAX_CORRECT
    if (sc_set) {
		message (ERR_ILLCLASS);
    }
#endif /* SYNTAX_CORRECT */
    switch (lastst) {
		case kw_typedef:
			sc = sc_typedef;
			break;
		case kw_extern:
			sc = sc_external;
			break;
		case kw_static:
			sc = sc_static;
			break;
		case kw_auto:
			sc = sc_auto;
			break;
		case kw_register:
			sc = sc_register;
			break;
		default:
			CANNOT_REACH_HERE ();
			break;
    }
    getsym ();
    return sc;
}

static FSPECIFIER function_specifier P1 (FSPECIFIER, fs)
{
    switch (lastst) {
		case kw_inline:
			fs = fs_inline;
			break;
		default:
			CANNOT_REACH_HERE ();
			break;
    }
    getsym ();
    return fs;
}

/*ANSI 3.5.3
 *    type_qualifier:
 *              "const"
 *              "volatile"
 */

static QUALIFIER type_qualifier P1 (QUALIFIER, qual)
{
    QUALIFIER q = QUAL_NONE;;

	switch (lastst) {
		case kw_const:
			q = QUAL_CONST;
			break;
		case kw_volatile:
			q = QUAL_VOLATILE;
			break;
#ifdef TOPSPEED
		case kw_cdecl:
			q = QUAL_NONE;
			break;
#endif /* TOPSPEED */
		case kw_restrict:
			q = QUAL_RESTRICT;
			break;
		default:
			CANNOT_REACH_HERE ();
			break;
	}
	/*
	*Constraint: The same type qualifier shall not appear more than once in
	*            the same specifier list or qualifier list.
	*/
#ifndef SYNTAX_CORRECT
	if (qual & q) {
		message (ERR_QUALIFIER);
	}
#endif /* SYNTAX_CORRECT */
	getsym ();
	return (QUALIFIER) (qual | q);
}


/*ANSI 3.5
 *    declaration-specifiers:
 *              storage-class-specifier declaration-specifiers[opt]
 *              type-specifier declaration-specifiers[opt]
 *              type-qualifier declaration-specifiers[opt]
 *ANSI 3.5.2.1
 *      specifier-qualifier-list:
 *              type-specifier specifier-qualifier-list[opt]
 *              type-qualifier specifier-qualifier-list[opt]
 *
 * These definitions can be combined because the "storage" for the
 * specifier-qualifier-list is "sc_member" which ensures that no
 * storage-class-specifier can be selected for this definition.
 *
 *ANSI 3.5.2
 *      type-specifier:
 *              "void"
 *              "char"
 *              "short"
 *              "int"
 *              "long"
 *              "float"
 *              "double"
 *              "signed"
 *              "unsigned"
 *              struct-or-union-specifier
 *              enum-specifier
 *              typedef-name
 *
 *    class-specifier-qualifier-list:
 *              type-specifier class-specifier-qualifier-list[opt]
 *              type-qualifier class-specifier-qualifier-list[opt]
 *              visibility class-specifier-qualifier-list[opt]
 *
 *    visibility:
 *              "public"
 *              "private"
 */
static TYP *declaration_specifiers P3 (STORAGE *, storage, STORAGE, def_sc, FSPECIFIER *, fspecifier)
{
	QUALIFIER qualifier = QUAL_NONE;
	unsigned ts, type = (unsigned) 0;
	int     count;
	TYP    *tp = NIL_TYP;
	SYM    *sp;
	BOOL    done, sc_set = FALSE;

	for (count = 0, done = FALSE; !done; count++) {
		switch (lastst) {
			/* storage class specifiers */
			case kw_extern:
			case kw_static:
			case kw_auto:
			case kw_typedef:
#ifndef SYNTAX_CORRECT
				if (def_sc == sc_parms) {
					message (ERR_ILLCLASS);
				}
		/*lint -fallthrough */
#endif /* SYNTAX_CORRECT */
			case kw_register:
#ifndef SYNTAX_CORRECT
				if ((count != 0) && obsolete_option) {
					message (WARN_STORAGE);
				}
#endif /* SYNTAX_CORRECT */
				*storage = storage_class_specifier (*storage, sc_set);
				sc_set = TRUE;
				continue;

			case kw_inline:
				if (fspecifier) {
					*fspecifier = function_specifier (*fspecifier);
				} else {
					message (ERR_ILLINLINE);
					getsym ();
				}
				continue;

			/* type specifiers */
			case tk_id:
				if (type) {
					done = TRUE;
					continue;
				}
				sp = sym_search (lastsym);
				if (sp == NIL_SYM || !is_typedef (sp)) {
					done = TRUE;
					continue;
				}
				tp = typeof (sp);
#ifndef SYNTAX_CORRECT
				if (tp->qual & qualifier) {
					message (ERR_QUALIFIER);
				}
#endif /* SYNTAX_CORRECT */
				qualifier |= tp->qual;

				/*
				*       Typdef'd arrays of incomplete types must be copied as
				*       their use must not complete the typedef type.
				*/
				if (is_array_type (tp) && is_incomplete_type (tp)) {
					tp = copy_type (tp);
				}
				getsym ();
				type = T_ALL;
				continue;

			case kw_void:
				ts = T_VOID;
				break;
			case kw_char:
				ts = T_CHAR;
				break;
			case kw_short:
				ts = T_SHORT;
				break;
			case kw_int:
				ts = T_INT;
				break;
			case kw_long:
				if (lang_option >= LANG_C99) {
					ts = (type & T_LONG) ? T_LONGLONG : T_LONG;
				} else {
					ts = T_LONG;
				}
				break;
			case kw_float:
				ts = T_FLOAT;
				break;
			case kw_double:
				ts = T_DOUBLE;
				break;
			case kw_signed:
				ts = T_SIGNED;
				break;
			case kw_unsigned:
				ts = T_UNSIGNED;
				break;
			case kw_bool:
				ts = T_BOOL;
				break;
			case kw_complex:
				ts = T_COMPLEX;
				break;
			case kw_imaginary:
				ts = T_IMAGINARY;
				break;
			case kw_struct:
			case kw_union:
#ifndef SYNTAX_CORRECT
				if (type) {
					message (ERR_ILLTYPE);
				}
#endif /* SYNTAX_CORRECT */
				tp = struct_or_union_specifier (def_sc);
				type = T_ALL;
				continue;
			case kw_enum:
#ifndef SYNTAX_CORRECT
				if (type) {
					message (ERR_ILLTYPE);
				}
#endif /* SYNTAX_CORRECT */
				tp = enum_specifier (def_sc);
				type = T_ALL;
				continue;

			case kw_restrict:
#ifndef SYNTAX_CORRECT
				message (ERR_RESTRICT);
		/*lint -fallthrough */
#endif /* SYNTAX_CORRECT */

			/* type qualifiers */
			case kw_const:
			case kw_volatile:
#ifdef TOPSPEED
			case kw_cdecl:
#endif /* TOPSPEED */
				qualifier = type_qualifier (qualifier);
				continue;
			default:
				done = TRUE;
				continue;
		}
		if (type == T_ALL) {
			break;
		}
#ifndef SYNTAX_CORRECT
		if (ts & type) {
			message (ERR_TYPE, lastsym);
		}
#endif /* SYNTAX_CORRECT */
		type |= ts;
		getsym ();

	} /* END FOR */

	switch (type) {
		case T_VOID:
			tp = tp_void;
			break;
		case 0:
			if (lang_option >= LANG_C99) {
#ifndef SYNTAX_CORRECT
				message (ERR_IMPLICITINT);
#endif /* SYNTAX_CORRECT */
			}
		/*lint -fallthrough */
		case T_INT:
		case T_SIGNED:
		case T_INT | T_SIGNED:
			tp = tp_int;
			break;
		case T_UNSIGNED:
		case T_INT | T_UNSIGNED:
			tp = tp_uint;
			break;
		case T_CHAR:
			tp = tp_char;
			break;
		case T_CHAR | T_UNSIGNED:
			tp = tp_uchar;
			break;
		case T_CHAR | T_SIGNED:
			tp = tp_schar;
			break;
		case T_SHORT:
		case T_SHORT | T_SIGNED:
		case T_SHORT | T_INT:
		case T_SHORT | T_INT | T_SIGNED:
			tp = tp_short;
			break;
		case T_SHORT | T_UNSIGNED:
		case T_SHORT | T_INT | T_UNSIGNED:
			tp = tp_ushort;
			break;
		case T_LONG:
		case T_LONG | T_INT:
		case T_LONG | T_SIGNED:
		case T_LONG | T_INT | T_SIGNED:
			tp = tp_long;
			break;
		case T_LONG | T_UNSIGNED:
		case T_LONG | T_INT | T_UNSIGNED:
			tp = tp_ulong;
			break;
		case T_LONGLONG | T_LONG:
		case T_LONGLONG | T_LONG | T_INT:
		case T_LONGLONG | T_LONG | T_SIGNED:
		case T_LONGLONG | T_LONG | T_INT | T_SIGNED:
			tp = tp_longlong;
			break;
		case T_LONGLONG | T_LONG | T_UNSIGNED:
		case T_LONGLONG | T_LONG | T_INT | T_UNSIGNED:
			tp = tp_ulonglong;
			break;
		case T_FLOAT:
			tp = tp_float;
			break;
		case T_DOUBLE:
			tp = tp_double;
			break;
		case T_DOUBLE | T_LONG:
			tp = tp_longdouble;
			break;
		case T_BOOL:
			tp = tp_bool;
			break;
		case T_FLOAT | T_COMPLEX:
			tp = tp_floatcomplex;
			break;
		case T_FLOAT | T_IMAGINARY:
			tp = tp_floatimaginary;
			break;
		case T_DOUBLE | T_COMPLEX:
			tp = tp_doublecomplex;
			break;
		case T_DOUBLE | T_IMAGINARY:
			tp = tp_doubleimaginary;
			break;
		case T_LONG | T_DOUBLE | T_COMPLEX:
			tp = tp_longdoublecomplex;

⌨️ 快捷键说明

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