@@ -492,22 +492,28 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
492492 // If the module has already been ensured as usable, we are done.
493493 if (self -> is_usable)
494494 return true ;
495+
496+ /* If the module is already marked as being checked for usability,
497+ * then there must be a cyclic module dependency. */
498+ if (self -> is_in_usable_check)
499+ return false ;
500+ self -> is_in_usable_check = true ;
495501
496502 // First ensure we can resolve all its external dependencies.
497503 for (uindex_t i = 0 ; i < self -> dependency_count; i++)
498504 {
499505 MCScriptModuleRef t_module;
500506 if (!MCScriptLookupModule (self -> dependencies[i] . name, t_module))
501- return false ;
507+ goto error_cleanup ;
502508
503509 // A used module must not be a widget.
504510 if (t_module -> module_kind == kMCScriptModuleKindWidget )
505- return false ;
511+ goto error_cleanup ;
506512
507513 // A used module must be usable - do this before resolving imports so
508514 // chained imports work.
509515 if (!MCScriptEnsureModuleIsUsable (t_module))
510- return false ;
516+ goto error_cleanup ;
511517
512518 // Check all the imported definitions from the module, and compute indicies.
513519 for (uindex_t t_import = 0 ; t_import < self -> imported_definition_count; t_import++)
@@ -519,7 +525,7 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
519525
520526 MCScriptDefinition *t_def;
521527 if (!MCScriptLookupDefinitionInModule (t_module, t_import_def -> name, t_def))
522- return false ;
528+ goto error_cleanup ;
523529
524530 MCScriptModuleRef t_mod;
525531 if (t_def -> kind == kMCScriptDefinitionKindExternal )
@@ -536,7 +542,7 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
536542 {
537543 if (t_import_def -> kind != kMCScriptDefinitionKindHandler ||
538544 t_def -> kind != kMCScriptDefinitionKindForeignHandler )
539- return false ;
545+ goto error_cleanup ;
540546 }
541547
542548 // Check that signatures match.
@@ -547,7 +553,7 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
547553
548554 // Now create the instance we need.
549555 if (!MCScriptCreateInstanceOfModule (t_module, self -> dependencies[i] . instance))
550- return false ;
556+ goto error_cleanup ;
551557 }
552558
553559 // Now build all the typeinfo's
@@ -581,12 +587,11 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
581587 {
582588 MCAutoStringRef t_name_string;
583589 if (!MCStringFormat (&t_name_string, " %@.%@" , self -> name, t_public_name))
584- return false ;
590+ goto error_cleanup ;
585591
586592 MCNewAutoNameRef t_name;
587593 if (!MCNameCreate (*t_name_string, &t_name))
588- return false ;
589-
594+ goto error_cleanup;
590595 // If the target type is an alias, named type or optional type then
591596 // we just create an alias. Otherwise it must be a record, foreign,
592597 // handler type - this means it must be named.
@@ -597,21 +602,21 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
597602 MCTypeInfoIsOptional (t_target_type))
598603 {
599604 if (!MCAliasTypeInfoCreate (*t_name, t_target_type, &t_typeinfo))
600- return false ;
605+ goto error_cleanup ;
601606 }
602607 else
603608 {
604609 if (!MCNamedTypeInfoCreate (*t_name, &t_typeinfo))
605- return false ;
610+ goto error_cleanup ;
606611
607612 if (!MCNamedTypeInfoBind (*t_typeinfo, t_target_type))
608- return false ;
613+ goto error_cleanup ;
609614 }
610615 }
611616 else
612617 {
613618 if (!MCAliasTypeInfoCreate (kMCEmptyName , self -> types[t_type_def -> type] -> typeinfo, &t_typeinfo))
614- return false ;
619+ goto error_cleanup ;
615620 }
616621 }
617622 else if (t_def -> kind == kMCScriptDefinitionKindExternal )
@@ -627,15 +632,15 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
627632 t_typeinfo = t_module -> types[static_cast <MCScriptTypeDefinition *>(t_import -> resolved_definition) -> type] -> typeinfo;
628633 }
629634 else
630- return false ;
635+ goto error_cleanup ;
631636 }
632637 break ;
633638 case kMCScriptTypeKindOptional :
634639 {
635640 MCScriptOptionalType *t_type;
636641 t_type = static_cast <MCScriptOptionalType *>(self -> types[i]);
637642 if (!MCOptionalTypeInfoCreate (self -> types[t_type -> type] -> typeinfo, &t_typeinfo))
638- return false ;
643+ goto error_cleanup ;
639644 }
640645 break ;
641646 case kMCScriptTypeKindForeign :
@@ -652,7 +657,7 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
652657 if (t_symbol == nil)
653658 {
654659 MCLog (" Unable to resolve foreign type '%@'" , t_type -> binding);
655- return false ;
660+ goto error_cleanup ;
656661 }
657662
658663 t_typeinfo = MCValueRetain (*(MCTypeInfoRef *)t_symbol);
@@ -670,11 +675,11 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
670675 t_field . name = t_type -> fields[i] . name;
671676 t_field . type = self -> types[t_type -> fields[i] . type] -> typeinfo;
672677 if (!t_fields . Push (t_field))
673- return false ;
678+ goto error_cleanup ;
674679 }
675680
676681 if (!MCRecordTypeInfoCreate (t_fields . Ptr (), t_type -> field_count, self -> types[t_type -> base_type] -> typeinfo, &t_typeinfo))
677- return false ;
682+ goto error_cleanup ;
678683 }
679684 break ;
680685 case kMCScriptTypeKindHandler :
@@ -689,11 +694,11 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
689694 t_parameter . mode = (MCHandlerTypeFieldMode)t_type -> parameters[i] . mode;
690695 t_parameter . type = self -> types[t_type -> parameters[i] . type] -> typeinfo;
691696 if (!t_parameters . Push (t_parameter))
692- return false ;
697+ goto error_cleanup ;
693698 }
694699
695700 if (!MCHandlerTypeInfoCreate (t_parameters . Ptr (), t_type -> parameter_count, self -> types[t_type -> return_type] -> typeinfo, &t_typeinfo))
696- return false ;
701+ goto error_cleanup ;
697702 }
698703 break ;
699704 }
@@ -703,13 +708,18 @@ bool MCScriptEnsureModuleIsUsable(MCScriptModuleRef self)
703708
704709 // First validate the module - if this fails we do nothing more.
705710 if (!MCScriptValidateModule (self))
706- return false ;
711+ goto error_cleanup ;
707712
708713 // Now bind all the public types.
709714
710715 self -> is_usable = true ;
716+ self -> is_in_usable_check = false ;
711717
712718 return true ;
719+
720+ error_cleanup:
721+ self -> is_in_usable_check = false ;
722+ return false ;
713723}
714724
715725// //////////////////////////////////////////////////////////////////////////////
0 commit comments