Commit 0c5baa5e authored by Daan Vreeken's avatar Daan Vreeken
Browse files

Fix forward-declarations of links to blocks that don't exist yet.

We do this by checking the final state of all links after loading the top-most
controller file. The new code will allow an included file to create links to
blocks that will only exist later on during the load process, and it will
successfully error out when links are defined for non-existing block.

Furthermore, controller_block_link() will now bail out immediately when it
hits an unrecoverable linker error. With this change, the error mesaage of the
linker step that failed will remain at the end of the output instead of being
flushed off the screen by e.g. 100+ 'Linked x to y (chained)' lines.

	modified:   controller/controller/controller_block.c
	modified:   controller/controller/controller_load.c
parent ba967183
......@@ -516,7 +516,7 @@ static int controller_block_resolve_link(struct controller_block_link *link)
term_type_str[outtype],
link->inblock, link->interm,
term_type_str[in->input[i].type]);
return -1;
return -2;
}
// Found both. Let's link them..
......@@ -564,7 +564,11 @@ int controller_block_link(void)
link = controller_block_link_get(i);
if (!link->type) {
r = controller_block_resolve_link(link);
if (r) {
if (r < -1)
// Stop as soon as we hit an unrecoverable
// error.
return r;
if (r != 0) {
ret = r;
}
}
......
......@@ -62,6 +62,9 @@ struct controller_load_extra {
};
static int controller_load_one_file(char *filename);
void yyerror(yyscan_t scanner, char const *s)
{
struct controller_load_extra *extra = yyget_extra(scanner);
......@@ -334,7 +337,7 @@ int controller_load_block_create(char *type, char *name, yyscan_t scanner)
log_send(LOG_T_DEBUG, "Load module '%s' with prefix '%s'",
file_name, prefname);
controller_module_push(prefname);
ret = controller_load(file_name);
ret = controller_load_one_file(file_name);
controller_module_pop();
log_send(LOG_T_DEBUG, "End of module '%s': %d", file_name, ret);
......@@ -523,7 +526,7 @@ int controller_load_include(yyscan_t scanner, char *rel_name)
}
log_send(LOG_T_DEBUG, "Include '%s'", file_name);
r = controller_load(file_name);
r = controller_load_one_file(file_name);
log_send(LOG_T_DEBUG, "End of include '%s': %d", file_name, r);
free(rel_name);
......@@ -579,7 +582,7 @@ int controller_load_import(yyscan_t scanner, char *rel_name)
controller_load_imports = imports;
controller_load_import_nr++;
r = controller_load(file_name);
r = controller_load_one_file(file_name);
log_send(LOG_T_DEBUG, "End of import '%s': %d", file_name, r);
free(file_name);
......@@ -686,7 +689,7 @@ static int controller_load_file_shell(char *args, char *out, int *outlen)
log_send(LOG_T_DEBUG, "loading: %s", args);
ret = controller_load(args);
ret = controller_load_one_file(args);
if (ret) {
*outlen = sprintf(out,
......@@ -721,7 +724,11 @@ int controller_load_shell_add(void)
return ret;
}
int controller_load(char *filename)
// This routine is called (possibly recursively) to load a single file.
// Linking all inputs/outputs is allowed to fail here, since there might be
// links that go to/come from blocks that will be instantiated in other files
// later on.
static int controller_load_one_file(char *filename)
{
struct controller_load_extra extra;
char *saved_context;
......@@ -758,7 +765,10 @@ int controller_load(char *filename)
fclose(extra.input_file);
ret = controller_block_link();
if (ret != 0) {
// We'll allow -1 (missing blocks), but we'll bail out on lower return
// values, which indicate unrecoverable errors like type mismatches in
// links, etc.
if (ret < -1) {
log_send(LOG_T_ERROR, "Failed to link controller!");
return ret;
}
......@@ -767,3 +777,23 @@ err_nofile:
return extra.ret;
}
// This routine will only be called to load the top-most file in a hierarchy.
// When it is loaded successfully, all earlier unresolved links must have been
// resolved.
int controller_load(char *filename)
{
int ret;
ret = controller_load_one_file(filename);
if (ret != 0)
return ret;
// See if the linker can now resolve all links.
ret = controller_block_link();
if (ret != 0) {
log_send(LOG_T_ERROR, "Final linking stage failed.");
}
return ret;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment