📄 decl.c
字号:
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 + -