+static void parse_external_declaration(void)
+{
+ /* function-definitions and declarations both start with declaration
+ * specifiers */
+ declaration_specifiers_t specifiers;
+ memset(&specifiers, 0, sizeof(specifiers));
+ parse_declaration_specifiers(&specifiers);
+
+ /* must be a declaration */
+ if(token.type == ';') {
+ parse_anonymous_declaration_rest(&specifiers, record_declaration);
+ return;
+ }
+
+ /* declarator is common to both function-definitions and declarations */
+ declaration_t *ndeclaration = parse_declarator(&specifiers, false);
+
+ /* must be a declaration */
+ if(token.type == ',' || token.type == '=' || token.type == ';') {
+ parse_declaration_rest(ndeclaration, &specifiers, record_declaration);
+ return;
+ }
+
+ /* must be a function definition */
+ parse_kr_declaration_list(ndeclaration);
+
+ declaration_t *declaration = record_declaration(ndeclaration);
+ if(ndeclaration != declaration) {
+ memcpy(&declaration->context, &ndeclaration->context,
+ sizeof(declaration->context));
+ }
+
+ /* push function parameters and switch context */
+ int top = environment_top();
+ context_t *last_context = context;
+ set_context(&declaration->context);
+
+ declaration_t *parameter = declaration->context.declarations;
+ for( ; parameter != NULL; parameter = parameter->next) {
+ environment_push(parameter);
+ }
+
+ type_t *orig_type;
+ type_t *type;
+
+ if(token.type != '{') {
+ parse_error_expected("while parsing function definition", '{', 0);
+ eat_statement();
+ goto end_of_parse_external_declaration;
+ }
+
+ orig_type = declaration->type;
+ if(orig_type == NULL) {
+ eat_block();
+ goto end_of_parse_external_declaration;
+ }
+
+ type = skip_typeref(orig_type);
+
+ if(type->type != TYPE_FUNCTION) {
+ parser_print_error_prefix();
+ fprintf(stderr, "declarator '");
+ print_type_ext(orig_type, declaration->symbol, NULL);
+ fprintf(stderr, "' has a body but is not a function type.\n");
+ eat_block();
+ goto end_of_parse_external_declaration;
+ }
+
+ /* § 6.7.5.3 (14) a function definition with () means no
+ * parameters (and not unspecified parameters) */
+ if(type->function.unspecified_parameters) {
+ type_t *duplicate = duplicate_type(type);
+ duplicate->function.unspecified_parameters = false;
+
+ type = typehash_insert(duplicate);
+ if(type != duplicate) {
+ obstack_free(type_obst, duplicate);