-- FramePackModulesImpl.mesa
-- last edited by JGS on 17-Sep-82 14:10:00
-- last edited by Satterthwaite, December 29, 1982 12:41 pm

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

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


  table: Alloc.Handle ← NIL;

  tb, stb: Table.Base;

  UpdateBases: Alloc.Notifier = {
    tb     ← base[PackagerDefs.packtreetype];  
    stb    ← base[PackagerDefs.packsttype]};


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

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

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


  SubStringForFramePackNode: PUBLIC PROC [
      ss: String.SubString, fpNode: Tree.Index] =
    BEGIN
    WITH tb[fpNode].son[1] SELECT FROM
      hash =>
	BEGIN framePackHti: HashOps.HTIndex = index;
	HashOps.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].attrs[$superceded] THEN FPerror[]; 
      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[
	      cNode, $instance, 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.