-- FramePackModulesImpl.Mesa  Last edited by Lewis on  2-Apr-81 14:45:27
-- last edited by Levin on July 6, 1982 3:49 pm

DIRECTORY
  Alloc USING [AddNotify, DropNotify, Handle, Notifier],
  BcdDefs USING [MTIndex],
  FramePackModules,
  PackagerDefs USING [globalData, packtreetype, packsttype, packctreetype],
  SemanticEntry USING [STIndex],
  SourceBcd USING [EnumerateModulesInConfig],
  Strings USING [SubString],
  SymTabDefs USING [HTIndex],
  SymTabOps USING [SubStringForHash],
  Table USING [Base],
  Tree: FROM "PackTree" USING [Index, Link, root, Scan, Test],
  TreeOps: FROM "PackTreeOps" USING [ScanList, SearchList];
 
FramePackModulesImpl: PROGRAM
    IMPORTS Alloc, PackagerDefs, SymTabOps, SourceBcd, Tree, TreeOps
    EXPORTS FramePackModules = 
  BEGIN 

  FPerror: PROC = {ERROR FramePackModulesError};
  FramePackModulesError: ERROR = CODE;


 -- Parse tree, semantic entry, and config tree allocator table bases 
  table: Alloc.Handle ← NIL;
  tb, stb, ctreeb: Table.Base;

  UpdateBases: Alloc.Notifier =
    BEGIN
    tb     ← base[PackagerDefs.packtreetype];  
    stb    ← base[PackagerDefs.packsttype];
    ctreeb ← base[PackagerDefs.packctreetype];
    END;


 -- ******************* Frame Pack Module Enumeration ********************

  EnumerateFramePacks: PUBLIC PROC [
      userProc: PROC [fpNode: Tree.Index] RETURNS [stop: BOOLEAN]] =
    BEGIN

    OutputOneFramePack: Tree.Test =
      BEGIN
      WITH t SELECT FROM
        subtree =>
          BEGIN treeNode: Tree.Index = index;
          SELECT tb[treeNode].name FROM
	    framePack, mergeFP =>
	      IF ~tb[treeNode].attr2 THEN                  -- not superceded 
	        {IF userProc[treeNode] THEN RETURN[TRUE]}; -- stop enumeration
	    ENDCASE;
          END;
        ENDCASE => FPerror[];
      RETURN[FALSE];
      END;
  
    table ← PackagerDefs.globalData.ownTable;
    table.AddNotify[UpdateBases];
    TreeOps.SearchList[Tree.root, OutputOneFramePack];
    table.DropNotify[UpdateBases];
    table ← NIL;
    END;


  SubStringForFramePackNode: PUBLIC PROC [
      ss: Strings.SubString, fpNode: Tree.Index] =
    BEGIN
    WITH tb[fpNode].son[1] SELECT FROM
      hash =>
	BEGIN framePackHti: SymTabDefs.HTIndex = index;
	SymTabOps.SubStringForHash[ss, framePackHti];
        END;
      ENDCASE => FPerror[];
    END;


  DoneEnumeratingModules: SIGNAL = CODE;

  EnumerateModules: PUBLIC PROC [
      fpNode: Tree.Index, 
      userProc: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN]] =
    BEGIN
    SELECT tb[fpNode].name FROM
      framePack, mergeFP =>
        IF tb[fpNode].attr2 THEN FPerror[];  -- superceded
      ENDCASE => FPerror[];
    OutputModules[fpNode, userProc ! DoneEnumeratingModules => CONTINUE];
    END;

  OutputModules: PROC [  -- called recursively when multiple layers of FP merging
      fpNode: Tree.Index, 
      userProc: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN]] =
    BEGIN
    SELECT tb[fpNode].name FROM
      framePack =>  -- fpNode is a "normal" frame pack
        OutputFPModules[cdList: tb[fpNode].son[2], userProc: userProc];
      mergeFP =>    -- fpNode is a merged frame pack
        OutputModulesOfMergedOldFPs[
	  oldFPList: tb[fpNode].son[2], userProc: userProc];
      ENDCASE => FPerror[];
    END;
    
  OutputModulesOfMergedOldFPs: PROC [
      oldFPList: Tree.Link, 
      userProc: PROC [
        mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN]] =
    BEGIN
    
    OutputModulesOfOneOldFP: Tree.Scan =
      BEGIN
      WITH t SELECT FROM
        symbol =>
          BEGIN oldFPSE: SemanticEntry.STIndex = index;
          WITH stb[oldFPSE] SELECT FROM
	    framePack =>
	      BEGIN oldFPNode: Tree.Index = treeNode;
	      OutputModules[fpNode: oldFPNode, userProc: userProc]
	      END;
	    ENDCASE;
          END;
        ENDCASE => FPerror[];
      END;
  
    TreeOps.ScanList[oldFPList, OutputModulesOfOneOldFP];
    END;
    
  OutputFPModules: PROC [
      cdList: Tree.Link, 
      userProc: PROC [
        mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN]] =
    BEGIN

    OutputModulesInOneCD: Tree.Test =
      BEGIN
      WITH t SELECT FROM
        subtree =>
          BEGIN cdNode: Tree.Index = index;
          SELECT tb[cdNode].name FROM
	    allComp =>
	      OutputAllModulesOfComponent[tb[cdNode].son[1], userProc];
	    compItems =>
	      OutputModulesOfComponentItems[tb[cdNode].son[2], userProc];
	    ENDCASE;
          END;
        ENDCASE => FPerror[];
      RETURN[FALSE];
      END;

    TreeOps.SearchList[cdList, OutputModulesInOneCD];
    END;

  OutputAllModulesOfComponent: PROC [
      compSeLink: Tree.Link, 
      userProc: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN]] =
    BEGIN  -- ComponentDesc ::= Component  (all global frames of component)

    OutputOneComponentModule: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
      BEGIN
      IF userProc[mti] THEN SIGNAL DoneEnumeratingModules;  
      RETURN[FALSE];
      END;

    WITH compSeLink SELECT FROM
      symbol =>
        BEGIN compSE: SemanticEntry.STIndex = index;
        WITH stb[compSE] SELECT FROM
	  module =>
	    IF userProc[mti] THEN SIGNAL DoneEnumeratingModules;
	  config =>
	    SourceBcd.EnumerateModulesInConfig[
	      instance, cNode, OutputOneComponentModule];
	  ENDCASE;
        END;
      ENDCASE => FPerror[];
    END;

  OutputModulesOfComponentItems: PROC [
      itemList: Tree.Link, 
      userProc: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN]] =
    BEGIN  -- ComponentDesc ::= Component [ItemList]  (frames of component's items)

    OutputModulesOfOneItem: Tree.Scan =
      {OutputAllModulesOfComponent[t, userProc]};

    TreeOps.ScanList[itemList, OutputModulesOfOneItem];
    END;

  END.