📄 decl.c
字号:
#ifndef SYNTAX_CORRECT
if (lang_option >= LANG_C99) {
message (ERR_UNDEFINEDFN, nameof (sp));
} else {
message (WARN_IMPLICITFN, nameof (sp));
}
break;
#endif /* SYNTAX_CORRECT */
default:
#ifndef SYNTAX_CORRECT
message (ERR_UNDEFINED, nameof (sp));
#endif /* SYNTAX_CORRECT */
break;
}
sym_append (&sp);
return sp;
}
/*ANSI 3.6.2
* declaration-list:
* declaration
* declaration-list declaration
*/
SIZE declaration_list P2 (STORAGE, def_sc, SIZE, offset)
{
while (is_declaration_specifier (lastst)) {
if ((def_sc != sc_member) && is_label (lastst)) {
return offset;
}
offset = declaration (def_sc, def_sc, offset);
}
return offset;
}
/*ANSI 3.5.4
* identifier-list:
* identifier
* identifier-list , identifier
*/
static void identifier_list P0 (void)
{
SYM *sp;
global_flag--;
assert (lastst == tk_id);
for (;;) {
switch (lastst) {
case tk_id:
sp = mk_sym (lastsym, sc_parms, NIL_TYP);
getsym ();
sym_append (&sp);
break;
default:
#ifndef SYNTAX_CORRECT
message (ERR_PARMS);
#endif /* SYNTAX_CORRECT */
global_flag++;
return;
}
if (lastst != tk_comma) {
global_flag++;
return;
}
getsym ();
}
}
/*ANSI 3.5.5
* type-name:
* specifier-qualifier-list abstract-declarator[opt]
*/
TYP *type_name P0 (void)
{
TYP *tp = NIL_TYP;
SYM *sp = NIL_SYM;
STORAGE sc;
if (is_type_name (lastst)) {
sc = sc_tag;
tp = declaration_specifiers (&sc, sc_global, NULL);
switch (lastst) {
case tk_star:
case tk_openbr:
case tk_openpa:
sp = declarator (sc, tp);
tp = typeof (sp);
break;
default:
break;
}
}
return tp;
}
/*ANSI 3.5.4
* parameter-type-list:
* parameter-list
* parameter-list , ...
*
* parameter-list:
* parameter-declaration
* parameter-list , parameter-declaration
*
* parameter-declaration:
* declaration-specifiers declarator
* declaration-specifiers abstract-declarator[opt]
*/
static void parameter_type_list P0 (void)
{
TYP *tp;
SYM *sp;
STORAGE sc;
global_flag++; /* allocate into global heap */
while (is_declaration_specifier (lastst)) {
sc = sc_parms;
tp = declaration_specifiers (&sc, sc_parms, NULL);
if (sc == sc_auto) {
sc = sc_parms;
}
sp = declarator (sc, tp);
if (is_func (typeof (sp))) {
/*
* Functions which are passed as a parameter are really
* pointers to a function.
*/
set_type (sp, mk_type (tp_pointer, typeof (sp)));
}
sym_append (&sp);
if (lastst != tk_comma || is_void (typeof (sp))) {
break;
}
getsym ();
switch (lastst) {
case tk_ellipsis:
getsym ();
check_stdarg (sp);
tp = mk_type (tp_ellipsis, NIL_TYP);
sp = mk_sym ((const CHAR *) "", sc_tag, tp);
sym_append (&sp);
global_flag--;
return;
case tk_closepa:
if (lattice_option) {
tp = mk_type (tp_ellipsis, NIL_TYP);
sp = mk_sym ((const CHAR *) "", sc_tag, tp);
sym_append (&sp);
global_flag--;
return;
}
break;
default:
break;
}
}
global_flag--;
return;
}
/*ANSI 3.5.2.2
* enumeration-list:
* enumerator
* enumerator-list , enumerator
*
* enumerator:
* enumeration-constant
* enumeration-constant = constant-expression
*
* enumeration-constant:
* identifier
*/
static TYP *enumeration_list P0 (void)
{
IVAL evalue, minval, maxval;
int count;
TYP *tp = mk_type (tp_enum, NIL_TYP);
TYP *tp2 = mk_type (tp_int, NIL_TYP);
set_derived (tp2);
set_enum (tp2);
set_enumtype (tp2, tp);
for (count = 0, minval = maxval = 0L, evalue = -1L; lastst == tk_id;) {
SYM *sp = mk_sym (lastsym, sc_const, tp2);
getsym ();
if (lastst == tk_assign) {
getsym ();
evalue = intexpr ();
} else {
#ifndef SYNTAX_CORRECT
switch (tp_int->size) {
case 2L:
if (evalue == 32767L)
message (ERR_ENUMWRAP);
break;
case 4L:
if (evalue == 2147483647L)
message (ERR_ENUMWRAP);
break;
#ifdef LONGLONG
#ifndef LONGLONG_BOOTSTRAP
#if 0
case 8L:
if (evalue == 9223372036854775807LL)
message (ERR_ENUMWRAP);
break;
#endif /* */
#endif /* LONGLONG_BOOTSTRAP */
#endif /* LONGLONG */
default:
break;
}
#endif /* SYNTAX_CORRECT */
evalue++;
}
/*
*Constraint: The expression that defines the value of an enumeration
* constant shall be an integral constant expression that
* has a value representable as an int.
*/
check_representable (evalue, tp_int);
if (evalue < minval) {
minval = evalue;
}
if (evalue > maxval) {
maxval = evalue;
}
sp->value.i = evalue;
sym_append (&sp);
count++;
if (lastst != tk_comma) {
break;
}
getsym ();
}
#ifndef SYNTAX_CORRECT
if (count == 0) {
message (ERR_INCOMPLETE, "enum");
}
#endif /* SYNTAX_CORRECT */
/* now determine the best integer type to hold the enumeration */
#ifdef PACKENUM
if (packenum_option) {
if (minval >= -128L && maxval <= 127L) {
tp2 = tp_schar;
} else if (minval >= 0L && maxval <= 256L) {
tp2 = tp_uchar;
} else if (minval >= -32768L && maxval <= 32767L) {
tp2 = tp_short;
} else if (minval >= 0L && maxval <= 65535L) {
tp2 = tp_ushort;
} else {
tp2 = tp_long;
}
} else
#endif /* PACKENUM */
tp2 = tp_int;
tp->type = tp2->type;
tp->size = tp2->size;
set_enum (tp);
set_enumtype (tp, tp);
return tp;
}
/*ANSI 3.5.2.2
* enum-specifier:
* "enum" identifier[opt] { enumeration-list }
* "enum" identifier
*/
static TYP *enum_specifier P1 (STORAGE, sc)
{
TYP *tp;
SYM *sp;
assert (lastst == kw_enum);
getsym ();
switch (lastst) {
case tk_begin:
getsym ();
tp = enumeration_list ();
needpunc (tk_end);
break;
case tk_id:
if ((sp = tag_search (lastsym)) == NIL_SYM) {
sp = mk_sym (lastsym, sc_tag, tp_enum);
tag_append (&sp);
#ifndef SYNTAX_CORRECT
if (sc == sc_parms) {
message (WARN_DUBIOUS, "enum");
}
#endif /* SYNTAX_CORRECT */
getsym ();
if (lastst == tk_begin) {
getsym ();
tp = enumeration_list ();
set_type (sp, tp);
set_nameoftype (tp, nameof (sp));
needpunc (tk_end);
#ifndef SYNTAX_CORRECT
} else {
tp = tp_int;
message (ERR_INCOMPLETE, "enum");
break;
#endif /* SYNTAX_CORRECT */
}
} else {
getsym ();
if (is_local_scope (sp) || lastst != tk_begin) {
check_tag (sp, tp_int);
tp = typeof (sp);
#ifndef SYNTAX_CORRECT
if (lastst == tk_semicolon) {
message (ERR_INCOMPLETE, "enum");
}
#endif /* SYNTAX_CORRECT */
} else {
getsym ();
tp = enumeration_list ();
set_type (sp, tp);
set_nameoftype (tp, nameof (sp));
needpunc (tk_end);
}
}
break;
default:
#ifndef SYNTAX_CORRECT
tp = tp_int;
message (ERR_INCOMPLETE, "enum");
#endif /* SYNTAX_CORRECT */
break;
}
return tp;
}
static int bit_width, bit_offset, bit_next;
/*ANSI 3.5.2.1
* struct-declarator-list:
* struct-declarator
* struct-declarator-list , struct-declarator
*ANSI 3.5.2.1
* struct-declarator:
* declarator
* declarator[opt] : constant-expression
*/
static SIZE struct_declarator_list P3 (TYP *, tp, SIZE, offset, const TYP *, stp)
{
SIZE size, al;
int int_bits;
TYP *tp_bit = tp_int;
for (size = 0L;;) {
SYM *sp = NIL_SYM;
switch (lastst) {
case tk_id:
case tk_star:
case tk_openpa:
sp = declarator (sc_member, tp);
#ifndef SYNTAX_CORRECT
check_complete (typeof (sp));
if (is_func (typeof (sp))) {
message (ERR_FUNC);
}
#endif /* SYNTAX_CORRECT */
if (lastst != tk_colon) {
switch (stp->type) {
case bt_struct:
al = align (typeof (sp), offset + size);
sp->value.i = (IVAL) (offset + size + al); /*lint !e776*/ /* possible truncation of addition */
field_append (&sp);
size += typeof (sp)->size + al;
break;
case bt_union:
al = align (typeof (sp), offset);
sp->value.i = (IVAL) (offset + al); /*lint !e776*/ /* possible truncation of addition */
field_append (&sp);
size = typeof (sp)->size + al;
break;
default:
CANNOT_REACH_HERE ();
}
bit_next = 0;
break;
}
tp = typeof (sp);
/*lint -fallthrough */
case tk_colon:
getsym ();
/*
*Semantic: A bit-field shall have type int, unsigned int, or
* signed int.
*/
#ifndef SYNTAX_CORRECT
if (!is_same_type (tp, tp_int)
&& !is_same_type (tp, tp_uint)
&& !is_same_type (tp, tp_bool)) {
if (tp->size > tp_int->size) {
message (ERR_FLDTYPE);
} else {
message (WARN_FLDTYPE);
}
}
#endif /* SYNTAX_CORRECT */
bit_width = (int) intexpr ();
bit_offset = bit_next;
if (packbit_option)
tp_bit = tp;
/*
*Constraint: The expression that specified the width of a bit-field
* shall be an integral constant expression that has
* nonnegative value that shall not exceed the number
* of bits in an ordinary object of compatible type.
*/
int_bits = (int) (tp_bit->size * bits_in_sizeunit);
#ifndef SYNTAX_CORRECT
if (bit_width < 0 || bit_width > int_bits) {
message (ERR_WIDTH);
bit_width = 1;
}
#endif /* SYNTAX_CORRECT */
/*ANSI 3.5.2.1
*Constraint: If the value is zero, the declaration shall have
* no declarator.
*
*Semantic: A bit-field structure member with a width of 0
* indicates that no further bit-field is to be
* packed into the unit in which the previous
* bit-field, if any, was placed.
*/
if (bit_width == 0 || bit_offset + bit_width > int_bits) {
bit_offset = 0;
}
bit_next = bit_offset + bit_width;
if (sp != NIL_SYM) {
#ifndef SYNTAX_CORRECT
if (bit_width == 0) {
message (ERR_WIDTH);
}
#endif /* SYNTAX_CORRECT */
set_type (sp, copy_type (tp));
typeof (sp)->type =
(BTYPE) (is_signed_type (tp) ? bt_bitfield :
(is_bool (tp) ? bt_bool : bt_ubitfield));
typeof (sp)->size = tp_bit->size;
set_bit_width (typeof (sp), (BITSIZE) bit_width);
if (bitfield_option) {
set_bit_offset (typeof (sp),
(BITSIZE) ((int_bits - bit_offset) - bit_width));
} else {
set_bit_offset (typeof (sp), (BITSIZE) bit_offset);
}
if (bit_offset > 0) {
offset -= tp_bit->size; /* shares space with previous field */
}
al = align (typeof (sp), offset + size);
sp->value.i = (IVAL) (offset + size + al); /*lint !e776*/ /* possible truncation of addition */
field_append (&sp);
size += typeof (sp)->size + al;
if (bit_offset > 0) {
size -= tp_bit->size;
}
} else {
if (bit_offset > 0) {
offset -= tp_bit->size; /* shares space with previous field */
}
al = align (tp_bit, offset + size);
size += tp_bit->size + al;
if (bit_offset > 0) {
size -= tp_bit->size;
}
}
break;
case tk_comma:
needpunc ((TOKEN) (lastst + 1)); /* force error */
break;
default:
break;
}
if (lastst != tk_comma) {
break;
}
getsym ();
}
return size;
}
static BOOL is_struct_declarator P1 (TOKEN, st)
{
switch (st) {
case tk_colon:
return TRUE;
default:
return is_specifier_qualifier (st);
}
}
/*ANSI 3.5.2.1
* struct-declaration-list:
* struct-declaration
* struct-declaration-list struct-declaration
*
*ANSI .5.2.1
* struct-declaration:
* specifier-qualifier-list struct-declarator-list ;
*/
static SIZE struct_declaration_list P1 (const TYP *, tp)
{
SIZE offset = 0L;
SIZE max_size = UNKNOWN_SIZE;
int count;
beginstructblock (members (tp));
bit_next = 0;
bit_offset = 0;
for (count = 0; is_struct_declarator (lastst); count++) {
TYP *tp1;
SIZE size;
STORAGE sc = sc_member;
tp1 = declaration_specifiers (&sc, sc_member, NULL);
size = struct_declarator_list (tp1, offset, tp);
if (offset + size > max_size) {
max_size = offset + size;
}
switch (tp->type) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -