📄 decl.c
字号:
break;
case T_LONG | T_DOUBLE | T_IMAGINARY:
tp = tp_longdoubleimaginary;
break;
case T_ALL:
break;
default:
#ifndef SYNTAX_CORRECT
message (ERR_ILLTYPE);
tp = tp_int;
#endif /* SYNTAX_CORRECT */
break;
}
return qualify_type (tp, qualifier);
}
/*ANSI 3.5.4
* direct-declarator:
* identifier
* ( declarator )
* direct-declarator [ type-qualifier-list assignment-expression[opt] ]
* direct-declarator [ static type-qualifier-list[opt] assignment-expression ]
* direct-declarator [ type-qualifier-list static assignment-expression ]
* direct-declarator [ type-qualifier-list[opt] * ]
* direct-declarator ( parameter-type-list )
* direct-declarator ( identifier-list[opt] )
*
* direct-abstract-declarator:
* ( abstract-declarator )
* direct-abstract-declarator[opt] [ constant-expression[opt] ]
* direct-abstract-declarator[opt] ( parameter-type-list[opt] )
*/
static TYP *direct_declarator_tail P2 (SYM *, sp, TYP *, tp)
{
SIZE size, ind;
switch (lastst) {
case tk_openbr:
getsym ();
if (lastst != tk_closebr) {
ind = (SIZE) intexpr ();
#ifndef SYNTAX_CORRECT
/*
*Constraint: The expression delimited by [ and ] (which
* specifies the size of an array) shall be an
* integral constant expression that has a value
* greater than zero.
*/
if (ind <= 0L) {
message (ERR_SIZE);
}
#endif /* SYNTAX_CORRECT */
} else {
ind = UNKNOWN_SIZE;
}
needpunc (tk_closebr);
tp = direct_declarator_tail (sp, tp);
size = tp ? tp->size : (SIZE) 1;
tp = mk_type (tp_array, tp);
set_array_index (tp, ind);
set_derived (tp);
if (size == UNKNOWN_SIZE || ind == UNKNOWN_SIZE) {
tp = copy_type (tp);
tp->size = UNKNOWN_SIZE;
} else {
tp->size = size * ind;
}
return tp;
case tk_openpa:
getsym ();
tp = mk_type (tp_func, tp);
set_derived (tp);
switch (lastst) {
case tk_id:
if (!is_typedef_symbol (lastsym)) {
#ifdef FACIST
#ifndef SYNTAX_CORRECT
message (WARN_OLDDEF);
#endif /* SYNTAX_CORRECT */
#endif /* FACIST */
beginparamblock ();
identifier_list ();
set_parameters (tp, endparamblock ());
#ifndef SYNTAX_CORRECT
if (obsolete_option) {
message (WARN_PROTOTYPE, nameof (sp));
}
#endif /* SYNTAX_CORRECT */
break;
}
/*lint -fallthrough */
default:
if (lang_option >= LANG_C90) {
beginparamblock ();
parameter_type_list ();
set_parameters (tp, endparamblock ());
set_ansi (tp);
}
break;
case tk_closepa:
set_parameters (tp, &init_block);
#ifndef SYNTAX_CORRECT
#ifdef FACIST
message (WARN_OLDDEF);
#endif /* FACIST */
if (obsolete_option) {
message (WARN_PROTOTYPE, nameof (sp));
}
#endif /* SYNTAX_CORRECT */
break;
}
needpunc (tk_closepa);
#ifdef ASMCALL
if (asmcall_option != NULL) {
funckind (tp) = fc_user;
funccall (tp) = asmcall_option;
asmcall_option = NULL;
}
#endif /* ASMCALL */
return direct_declarator_tail (sp, tp);
default:
return tp;
}
}
static SYM *direct_declarator P2 (STORAGE, sc, TYP *, tp)
{
SYM *sp;
switch (lastst) {
case tk_id:
sp = mk_sym (lastsym, sc, tp);
getsym ();
break;
case tk_openpa:
getsym ();
if (lastst == tk_closepa) {
/*
* empty parentheses in a type-name are interpreted as "function
* with no parameter specification", rather than redundant
* parentheses around the omitted identifier.
*/
getsym ();
tp = mk_type (tp_func, tp);
sp = mk_sym ((const CHAR *) "", sc, tp);
} else {
TYP *tp1;
sp = declarator (sc, NIL_TYP);
needpunc (tk_closepa);
tp = direct_declarator_tail (sp, tp);
tp1 = typeof (sp);
if (tp1 != NIL_TYP) {
for (; tp1->btp; tp1 = tp1->btp)
/* nothing */ ;
tp1->btp = tp;
} else {
set_type (sp, tp);
}
size_type (typeof (sp));
}
return sp;
default:
/* abstract */
sp = mk_sym ((const CHAR *) "", sc, tp);
break;
}
set_type (sp, direct_declarator_tail (sp, typeof (sp)));
return sp;
}
/*ANSI 3.5.4
* type-qualifier-list:
* type-qualifier
* type_qualifier-list type-qualifier
*/
static QUALIFIER type_qualifier_list P0 (void)
{
QUALIFIER qual = QUAL_NONE;
while (is_type_qualifier (lastst)) {
qual = type_qualifier (qual);
}
return qual;
}
/*ANSI 3.5.4
* declarator:
* pointer[opt] direct-declarator
*
* abstract-declarator:
* pointer
* pointer[opt] direct-abstract-declarator
*
* pointer:
* * type-qualifier-list[opt]
* * type-qualifier-list[opt] pointer
*/
static SYM *declarator P2 (STORAGE, sc, TYP *, tp)
{
SYM *sp;
switch (lastst) {
case tk_star:
getsym ();
tp = mk_type (tp_pointer, tp);
if (tp->btp == NIL_TYP) {
/*
* The type of pointer isn't known .... it will only be
* known later. We must ensure that the same pointer is
* therefore not used more than once.
*/
tp = copy_type (tp);
}
tp = qualify_type (tp, type_qualifier_list ());
sp = declarator (sc, tp);
break;
case tk_id:
case tk_openpa:
case tk_openbr:
sp = direct_declarator (sc, tp);
break;
default:
sp = mk_sym ((const CHAR *) "", sc, tp);
}
return sp;
}
static BLOCK *get_parameters P1 (const SYM *, sp)
{
BLOCK *block, *block2;
SYM *sp1, *sp2;
block = parameters (typeof (sp));
if (is_ansi (typeof (sp))) {
#ifndef SYNTAX_CORRECT
if (lastst == tk_begin) {
/*
* Parameters to function definitions must have a name
*/
for (sp2 = symbolsof (block); sp2 != NIL_SYM; sp2 = nextsym (sp2)) {
if (is_void (typeof (sp2)) || is_ellipsis (typeof (sp2))) {
break;
}
if (nameof (sp2) == NIL_CHAR || nameof (sp2)[0] == (CHAR) 0) {
message (ERR_PARMS);
break;
}
symbol_set (sp2);
}
}
#endif /* SYNTAX_CORRECT */
} else {
beginparamblock ();
VOIDCAST declaration_list (sc_parms, 0L);
block2 = endparamblock ();
set_parameters (typeof (sp), &init_block);
#ifndef SYNTAX_CORRECT
/*
* an id list on a function declaration is illegal
*/
if ((lastst != tk_begin) && (symbolsof (block) != NIL_SYM)) {
message (ERR_IDLIST);
}
#endif /* SYNTAX_CORRECT */
/*
* now match up the identifier list with the declarations
*/
for (sp1 = symbolsof (block); sp1 != NIL_SYM; sp1 = nextsym (sp1)) {
sp2 = search (nameof (sp1), &block2->symbols);
if (sp2 == NIL_SYM) {
#ifndef SYNTAX_CORRECT
message (WARN_IMPLICIT, nameof (sp1));
#endif /* SYNTAX_CORRECT */
set_type (sp1, tp_int);
} else {
set_storage (sp1, storageof (sp2));
set_type (sp1, typeof (sp2));
sp1->value.i = sp2->value.i;
symbol_set (sp1);
}
}
#ifndef SYNTAX_CORRECT
/*
* now check for declared items which aren't in the
* identifier list for the function.
*/
for (sp2 = symbolsof (block2); sp2 != NIL_SYM; sp2 = nextsym (sp2)) {
if (is_const (sp2)) {
continue;
}
if (search (nameof (sp2), &block->symbols) == NIL_SYM) {
message (ERR_ARG, nameof (sp2));
}
symbol_set (sp2);
}
/*
* check the function parameter declarations with any function
* prototype which may be in scope.
*/
check_parameters (block, sp);
#endif /* SYNTAX_CORRECT */
}
return block;
}
/*ANSI 3.7
* external-declaration:
* function-declaration
* declaration
*
*ANSI 3.5
* declaration:
* declaration-specifiers init-declaration-list[opt] ;
*
* init-declaration-list:
* init-declarator
* init-declarator-list , init-declarator
*
* init-declarator:
* declarator
* declarator = initializer
*
* function-definition:
* declaration-specifiers[opt] declarator declaration-list[opt]
* compound-statement
*/
static SIZE declaration P3 (STORAGE, sc, STORAGE, def_sc, SIZE, offset) {
TYP *tp;
SYM *sp;
FSPECIFIER fs = fs_none;
tp = declaration_specifiers (&sc, def_sc, &fs);
#ifndef SYNTAX_CORRECT
switch (def_sc) {
case sc_global:
if (sc == sc_register || sc == sc_auto) {
message (ERR_ILLCLASS);
}
break;
case sc_parms:
if (sc != sc_register && sc != sc_parms) {
message (ERR_ILLCLASS);
}
break;
default:
break;
}
#endif /* SYNTAX_CORRECT */
for (sp = NIL_SYM;;) {
switch (lastst) {
case tk_id:
case tk_star:
case tk_openpa:
if (sc != sc_global && tp == NIL_TYP) {
/*ANSI 3.5
* If an identifier for an object is declared with no linkage,
* the type for the object shall be complete by the end of its
* declarator, or by the end of its identifiers if it has an
* initializer.
*ANSI 3.1.2.2
* The following identifiers have no linkage: an identifier
* declared to be anything other than an object or a function;
* an identifier declared to be a function parameter; a block
* scope identifier for an object declared without the
* storage-class specifier extern.
*/
return offset;
}
sp = declarator (sc, tp);
switch (typeof (sp)->type) {
BLOCK *block;
case bt_func:
set_fspecifier (sp, fs);
check_function_definition (sp);
if (lastst != tk_semicolon) {
block = get_parameters (sp);
} else {
block = NIL_BLOCK;
}
if (def_sc == sc_parms) {
/*
* Functions which are passed as a parameter are really
* pointers to a function.
*/
set_type (sp, mk_type (tp_pointer, typeof (sp)));
}
if (lastst == tk_begin) {
/* function declaration */
sp = declare (sp, def_sc);
#ifndef SYNTAX_CORRECT
check_function_declaration (sp);
if (def_sc != sc_global) {
message (ERR_NESTED, nameof (sp));
break;
}
if (is_symbol_defined (sp)) {
message (ERR_REDECL, nameof (sp));
}
symbol_defined (sp);
#endif /* SYNTAX_CORRECT */
#ifdef EXTERNAL
funclist (sp);
#endif /* EXTERNAL */
func_symbol = sp;
funcbody (sp, block);
func_symbol = NULL;
return offset;
}
/*lint -fallthrough */
default:
#ifndef SYNTAX_CORRECT
if (fs == fs_inline) {
message (ERR_INLINE);
}
#endif /* SYNTAX_CORRECT */
sp = declare (sp, def_sc);
offset = doinit (sp, offset);
if (def_sc == sc_auto) {
switch (storageof (sp)) {
default:
#ifndef SYNTAX_CORRECT
check_complete (typeof (sp));
#endif /* SYNTAX_CORRECT */
#ifdef CPU_DEFINED
addoptinfo (sp, def_sc);
#endif /* CPU_DEFINED */
/*lint -fallthrough */
case sc_external:
case sc_typedef:
break;
}
}
}
break;
case tk_eof:
return offset;
case tk_comma:
needpunc ((TOKEN) (lastst + 1)); /* force error */
break;
default:
break;
}
if (lastst != tk_comma) {
break;
}
getsym ();
}
#ifndef SYNTAX_CORRECT
if (sp == NIL_SYM) {
switch (sc) {
case sc_typedef:
if (is_anonymous_structure (tp)) {
/* no declarator defined */
message (ERR_IDEXPECT);
} else {
/* struct declator defined so is legal */
message (WARN_TYPEDEF);
}
/*lint -fallthrough*/
case sc_external:
case sc_global:
case sc_static:
if (is_structure_type (tp)) {
} else if (is_enum (tp)) {
} else {
message (ERR_IDEXPECT);
}
break;
default:
break;
}
}
#endif /* SYNTAX_CORRECT */
if (lastst == tk_semicolon) {
needpunc (tk_semicolon);
} else {
needpunc (tk_semicolon);
getsym ();
}
return offset;
}
/*
* main compiler routine. this routine parses all of the declarations using
* declare which will call funcbody as functions are encountered.
*
*ANSI 3.7
* translation-unit:
* external-declaration
* translation-unit external-declaration
*/
void translation_unit P0 (void) {
SIZE offset = 0L;
#ifdef VERBOSE
clock_t ltime = clock ();
#endif
global_flag = 1;
strtab = NIL_STRING;
beginblock ();
nextlabel = (LABEL) 1;
#ifdef CPU_DEFINED
if (code_option) {
put_start ();
}
#endif /* CPU_DEFINED */
while (lastst != tk_eof) {
#ifndef SYNTAX_CORRECT
if (lastst == tk_semicolon) {
message (WARN_EMPTY);
}
#endif /* SYNTAX_CORRECT */
offset += declaration (sc_global, sc_global, offset);
}
endblock ();
#ifdef CPU_DEFINED
if (code_option) {
put_literals ();
put_finish ();
}
#endif /* CPU_DEFINED */
#ifdef VERBOSE
decl_time += clock () - ltime;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -